skip to Main Content

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


  1. 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 your server.js:

    app.use("/api/*", apiRouter)
    

    This route will catch anything that has the /api path in the first position in it. Nevertheless, in your router.js, you have the following:

    router.get("/api/get/", (req, res) => {
      console.log("fallen into the get1");
    });
    

    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 the get3 from:

    router.get("/get", (req, res) => {
      console.log("fallen into the get3");
    });
    

    The log that says API request passed through: /api/get comes from this one specifically.

    Nested routers apply the "parent" path like a tree.

    Login or Signup to reply.
  2. The problem is in this part:

    app.use("/api/*", apiRouter);
    

    Change this to:

    app.use("/api", apiRouter);
    

    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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search