In Nodejs, how to have individual "allowed methods" for each express enpoint?

Issue

I am building a rest API with nodejs and express.

I am trying to implement a small CORS system to the endpoints:

cors.js

export const cors = ({ allowedMethods }) => {
  return (req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    if(!allowedMethods.includes(req.method)){
      return res.sendStatus(405);
    }
    next();
  }
}

server.js

const app = express()

app.use(express.json())

app.post('/', cors({allowedMethods: ['POST']}), (req, res) => {

})

app.put('/photo', cors({allowedMethods: ['PUT']}), (req, res) => {

})

Let’s say I have these 2 endpoints, every time I go to a URL with an unallowed method, I get a 404 response but I want "405 Not Allowed". (makes sense, because of app.<method>())

How is it possible to look up the allowedMethods for each endpoint and decide what to do next?

I’ve tried using app.use(cors()), but that catches all endpoints and I’ll never know about the allowedMethod specified for a specific endpoint. And I don’t think that node cors package would do it.

Solution

You’re conflating two different things here.

CORS has a mechanism for stating what HTTP methods are allowed to be used to make a cross origin request from JavaScript which is used in combination with a preflight OPTIONS request.

HTTP has a mechanism to say that a request is using an HTTP method that is not allowed at all.


Since you are attempting to generate 405 Not Allowed responses, you are dealing with the latter. This has nothing to do with CORS and should be kept separate from CORS middleware.

all will match all requests for a path, no matter what HTTP method is used, so you can write:

const method_not_allowed = (req, res) => {
    return res.sendStatus(405);
};

app.post('/', cors(), (req, res) => { });
app.all('/', method_not_allowed);

Any POST request will get caught by app.post('/' and any other request to / will carry on and get matched by app.all('/').


That said, it looks like you are reinventing the wheel and could just use this existing module.


If you need to also deal with Access-Control-Allow-Methods then you need to take care of that separately.

That does need to be handled with the rest of your CORS logic, and you need to handle both the methods you want requests to be made with (post in this example) and OPTIONS (for the preflight).

Answered By – Quentin

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published