Home > Blockchain >  Express wildcard route overwriting other routes
Express wildcard route overwriting other routes

Time:01-17

I'm currently making a Node.js server using Express.js and Typescript. I have a routes folder in which I create .ts files containing routes. One of these files may look something like this:

import { Router, Request, Response } from "express";

export const router: Router = Router();

router.get("/", (_: Request, res: Response) => {
    res.json({
        message: "Hello world",
    });
});

export const path = "/users";

In my main file server.ts I dynamically add all routes using the exported variables in the routes. This looks something like this:

// set __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const routesPath: string = path.join(__dirname, "routes");

// register routes
try {
    fs.readdirSync(routesPath).forEach(async (file: string) => {
        const route: { path: string; router: Router } = await import(
            `./routes/${file}`
        );

        app.use(route.path, route.router);
    });

    // ! Causes Issue
    app.all("*", (_: Request, res: Response) =>
        res.status(404).json({
            message: "Not found",
            status: 404,
        })
    );
} catch (err) {
    console.log(err);
}

In the route below that has the * route I'm getting an issue where when it is uncommented it overwrites all other routes to itself but the routes work normally when I have it commented out. What may be causing this? I also tried to move the 404 route before registering all routes but that didn't help.

CodePudding user response:

The issue is because of the loop block running asynchronously, even though you have defined app.all("*", ...) after the forEach, but it will be executed before forEach.

So you need to change the forEach part like below:

await Promise.all(fs.readdirSync(routesPath).map(async (file: string) => {
    const route: { path: string; router: Router } = await import(
        `./routes/${file}`
    );

    app.use(route.path, route.router);
}));

app.all("*", (_: Request, res: Response) =>
    res.status(404).json({
        message: "Not found",
        status: 404,
    })
);

CodePudding user response:

async function registerRoutes() {
let files = fs.readdirSync(routesPath);
for (let i = 0; i < files.length; i  ) {
  let file = files[i];
  const route = await import(`./routes/${file}`);

  app.use(route.path, route.router);
  console.log("register ");
}
console.log("final");
app.use("*", (_, res) =>
  res.status(404).json({
    message: "Not found",
    status: 404,
  })
);

}

  • Related