javascriptnode.jsrequestcorsrestify

Restify is returning 405 instead of 404


We are using restify 6.4.0 and instead of 404 for non-existent endpoints we get 405 (method not allowed).

I have identified the core issue which is this line server.opts('.*', (req, res) => res.send(204));. For some reason, when it is present, the 405 issue is present. When I remove it, then restify starts working as expected (404 for nonexisting endpoints, 405 for existing endpoints with different HTTP Method existing)

This is working example

var restify = require('restify');

const server = restify.createServer({
  name: 'myapp',
  version: '1.0.0'
});

server.use(restify.plugins.acceptParser(server.acceptable));
server.use(restify.plugins.queryParser());
server.use(restify.plugins.bodyParser());

server.opts('.*', (req, res) => res.send(204));

server.get('/echo/:name', function (req, res, next) {
  res.send(req.params);
  return next();
});

server.listen(8080, function () {
  console.log('%s listening at %s', server.name, server.url);
});

When I use postman and call localhost:8080/noo, this is the response

{
    "code": "MethodNotAllowed",
    "message": "GET is not allowed"
}

However when I remove the server.opts('.*', (req, res) => res.send(204)); line, I got expected result

{
    "code": "ResourceNotFound",
    "message": "/noo does not exist"
}

Its not clear to me, why this is happening - tried Postman and also another Node.js code to make sure its not caused by some pre-flight request done by Chrome or other browsers. Calling the server with this code:

var request = require('request');
var options = {
  'method': 'GET',
  'url': 'http://localhost:8080/noo',
  'headers': {
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

Is getting me this response

{"code":"MethodNotAllowed","message":"GET is not allowed"}

(and same as with postman, when I delete the server.opts... line, I get proper response

{"code":"ResourceNotFound","message":"/noo does not exist"}

Can someone explain whats happening?


Solution

  • The line:

    server.opts('.*', (req, res) => res.send(204));
    

    Is a catch all handler to return 204 response for all HTTP OPTONS requests.

    Looks like this results in restify always concluding that you do have a handler for a given route (since it is a catch all for every route), just not for the method that is being asked for - i.e. anything but OPTIONS requests.

    Hence you get 405 "Method not allowed" rather than 404 "Not found"