Using router express, I can not get paths like http://localhost:5000/api/get and http://localhost:5000/api/get/blah falling into where I want them to. I know router.js is working, because anything with /api/ works, but falls into the catch all in router.js.
e.g.
Console.log output from http://localhost:5000/api/get/blah
falling into the catch all api route
API request passed through: /api/get/blah
API request passed through:
I’d have expected this to have fallen into "router.get("/get/:dictionaryId", (req, res) => {", but it hasn’t
Console.log output from http://localhost:5000/api/get
falling into the catch all api route
API request passed through: /api/get
API request passed through: /
I’d have expected this to have fallen into "router.get("/get", (req, res) => {", but it hasn’t.
What am I missing?
server.js
var path = require("path");
var app = express();
var webpack = require("webpack");
var config = require("./webpack.config");
const compiler = webpack(config);
const apiRouter = require("./router"); // Import the API router
var port = 5000;
// Serve static files from the build directory
app.use(express.static(path.join(__dirname, "build")));
app.use("/api/*", apiRouter);
app.use("/api/*", (req, res, next) => {
console.log(`API request passed through in server.js and currently won't be hit: ${req.originalUrl}`);
next();
});
// This code makes sure that any request that does not matches a static file
// in the build folder, will just serve index.html. Client side routing is
// going to make sure that the correct content will be loaded.
app.use((req, res, next) => {
if (/(.ico|.js|.css|.jpg|.png|.map)$/i.test(req.path)) {
next();
} else {
res.header("Cache-Control", "private, no-cache, no-store, must-revalidate");
res.header("Expires", "-1");
res.header("Pragma", "no-cache");
res.sendFile(path.join(__dirname, "build", "index.html"));
}
});
app.use(
require("webpack-dev-middleware")(compiler, {
publicPath: config.output.publicPath,
}),
);
app.listen(port, function (error) {
if (error) {
console.log(error);
} else {
console.log("Application running on port: " + port);
}
});
router.js
const express = require("express");
const router = express.Router();
// Define multiple API endpoints
router.get("/api/get/", (req, res) => {
console.log("fallen into the get1");
});
router.get("/api/get", (req, res) => {
console.log("fallen into the get2");
});
router.get("/get", (req, res) => {
console.log("fallen into the get3");
});
router.get("/get/", (req, res) => {
console.log("fallen into the get4");
});
router.get("get", (req, res) => {
console.log("fallen into the get5");
});
router.get("get/", (req, res) => {
console.log("fallen into the get6");
});
// Define multiple API endpoints
router.get("/get/:dictionaryId", (req, res) => {
console.log("fallen into the get");
});
router.get("*", (req, res) => {
console.log("falling into the catch all api route");
console.log(`API request passed through: ${req.originalUrl}`);
console.log(`API request passed through: ${req.path}`);
});
module.exports = router;
2
Answers
I am unsure as to what you mean with your example, but I believe you are accidentally duplicating paths.
Given
Express
having the following in yourserver.js
:This route will catch anything that has the
/api
path in the first position in it. Nevertheless, in yourrouter.js
, you have the following:This piece of code does not correspond to
/api/get
, but rather to/api/api/get
. This means that the router is going through all possible matches, the first one being/api/get
is theget3
from:The log that says
API request passed through: /api/get
comes from this one specifically.Nested routers apply the "parent" path like a tree.
The problem is in this part:
Change this to:
and it works. When you add an asterisk (‘*’) it becomes a wildcard route and if you want to proceed with it you need more specific route handling. You can read more about it in the express docs