Ответ 1
Вот такой подход, который я успешно использовал с несколькими приложениями Django и теперь с Node и Express. Также следует RFC 2616 (HTTP/1.1), в котором говорится о HTTP 405:
Ответ должен включать заголовок Allow, содержащий список действительных методы для запрошенного ресурса.
Итак, ключевым моментом является маршрутизировать запросы к одному и тому же обработчику без учета методов.
app.all('/page/:id', page.page);
app.all('/page/:id/comments', page.comments);
app.all('/page/:id/attachments', page.attachments);
...
Следующий момент - проверить метод в функции обработчика. Обратите внимание, что обработчик отвечает за обработку всех методов. В мире Django это единственный путь, потому что структура заставляет вас отделять маршрутизацию URL-адресов от фактического действия, которое необходимо выполнить против ресурса, который представляет URL.
В обработчике вы могли проверить метод, подобный этому...
exports.comments = function (req, res) {
if (req.route.method === 'get') {
res.send(200, 'Hello universe.');
} else {
res.set('Allow', 'GET');
res.send(405, 'Method Not Allowed');
}
}
... но, как вы можете ожидать, код быстро станет повторяющимся и не славным читать, особенно если у вас много функций обработчика и множество различных разрешенных методов.
Поэтому я подготовил функцию ярлыка, названную restful для задания. Определите функцию везде, где вы хотите. Я лично поместил бы его в helpers.js в тот же каталог, где реализованы функции обработчика.
var restful = function (req, res, handlers) {
//
// This shortcut function responses with HTTP 405
// to the requests having a method that does not
// have corresponding request handler. For example
// if a resource allows only GET and POST requests
// then PUT, DELETE, etc requests will be responsed
// with the 405. HTTP 405 is required to have Allow
// header set to a list of allowed methods so in
// this case the response has "Allow: GET, POST" in
// its headers [1].
//
// Example usage
//
// A handler that allows only GET requests and returns
//
// exports.myrestfulhandler = function (req, res) {
// restful(req, res, {
// get: function (req, res) {
// res.send(200, 'Hello restful world.');
// }
// });
// }
//
// References
//
// [1] RFC-2616, 10.4.6 405 Method Not Allowed
// https://tools.ietf.org/html/rfc2616#page-66
//
// [2] Express.js request method
// http://expressjs.com/api.html#req.route
//
var method = req.route.method; // [2]
if (!(method in handlers)) {
res.set('Allow', Object.keys(handlers).join(', ').toUpperCase());
res.send(405);
} else {
handlers[method](req, res);
}
}
С успокоительным теперь совершенно безболезненно обрабатывать 405 ответов автоматически и иметь правильный разрешающий заголовок. Просто дайте функцию для каждого метода, который вы разрешаете, и успокаиваете остальные.
Таким образом, можно изменить предыдущий пример:
exports.comments = function (req, res) {
restful(req, res, {
get: function (req, res) {
res.send(200, 'Hello restful universe.');
}
});
}
Почему имя успокаивается? В RESTful веб-интерфейсом очень важно, чтобы API выполнял соглашения, подобные тому, как отвечать на HTTP 405 на запрос, имеющий не поддерживаемый метод. Многие из этих конвенций могут быть интегрированы, чтобы успокоиться, когда это необходимо. Поэтому имя является спокойным, а не что-то вроде auto405 или http405handler.
Надеюсь, это поможет. Любые мысли?