Обслуживание нестандартного метода HTTP с ExpressJS - PullRequest
7 голосов
/ 17 февраля 2012

Я хотел бы написать HTTP-сервер, который отвечает на запрос, используя нестандартный метод HTTP (глагол). Например, клиент сделал бы запрос как FOO / HTTP/.1.1. А на стороне сервера этот запрос будет обрабатываться примерно так:

var express = require('express');

var app = express.createServer();

app.configure(function(){
  app.use(express.logger({ format: ':method :url' }));
  app.use(express.methodOverride());
});

app.foo('/', function(req, res){
    res.send('Hello World');
});

app.listen(3000);

Я добавил свой нестандартный метод в массив, экспортированный в ExpressJS lib/router/methods.js. Это позволяет мне писать свой серверный код, как и ожидалось. При использовании express.methodOverride() и POST запроса с _method=foo это работает. Но фактический запрос FOO не работает. Как только клиент отправляет первую строку запроса, сервер закрывает соединение:

$telnet localhost 3000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
FOO / HTTP/1.1
Connection closed by foreign host.

Я хотел бы иметь возможность реализовать это с помощью ExpressJS и без взлома его основного файла.

Есть идеи, возможно ли это и как?

Ответы [ 4 ]

4 голосов
/ 17 февраля 2012

Краткий ответ: нет, это невозможно. Не без реализации собственного HTTP-модуля.

Для проверки запустите базовый HTTP-сервер ...

$ node
> require('http').createServer(function(req, res) {
...   console.log(req.method);
...   res.end();
... }).listen(8080);

Затем (как вы уже сделали) подключитесь к нему и выполните запрос GET и FOO ...

$ telnet localhost 8080
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1

HTTP/1.1 200 OK
Connection: keep-alive
Transfer-Encoding: chunked

0

FOO / HTTP/1.1
Connection closed by foreign host.

$ 

В консоли узла вы увидите

GET

... но нет FOO. Таким образом, собственный модуль HTTP узла, который использует Express, не делает эти запросы доступными.

1 голос
/ 19 июня 2014

Узел имеет жестко запрограммированный белый список допустимых HTTP-глаголов в C.

Чтобы принимать пользовательские глаголы, необходимо изменить синтаксический анализатор HTTP и перекомпилировать узел.1006 *

Вы упомянули , что вы пытаетесь реализовать PURGE, который был добавлен в белый список в v0.7.5.

0 голосов
/ 19 июня 2014

Как уже говорили, библиотека HTTP-сервера Node.js настроена на прием только определенных глаголов. Предложение Бен Нурдиуса об использовании Петрушка также не работает, так как эта библиотека принимает еще меньший белый список глаголов. (Это также не поддерживалось в течение долгого времени.)

На этом этапе, если мы хотим поддержать запросы на странный мяч, мы должны принять более решительные меры. Вот хороший уродливый хак для вас, который включает в себя утку, пробивающую внутреннее поведение. Это работает на v0.10.x Node.js, но тщательно проверяйте новые версии по мере их появления.

В моем случае мне нужно было поддерживать не только нестандартный глагол, но и нестандартный идентификатор версии протокола, а также отсутствующий заголовок Content-Length для исходных потоков Icecast:

SOURCE /live ICE/1.0

Следующее должно вас начать:

server.on('connection', function (socket) {
    var originalOnDataFunction = socket.ondata;
    var newLineOffset;
    var receiveBuffer = new Buffer(0);
    socket.ondata = function (d, start, end) {
        receiveBuffer = Buffer.concat([receiveBuffer, d.slice(start, end)]);
        if ((newLineOffset = receiveBuffer.toString('ascii').indexOf('\n')) > -1) {
            var firstLineParts = receiveBuffer.slice(0, newLineOffset).toString().split(' ');
            firstLineParts[0] = firstLineParts[0].replace(/^SOURCE$/ig, 'PUT');
            firstLineParts[2] = firstLineParts[2].replace(/^ICE\//ig, 'HTTP/');
            receiveBuffer = Buffer.concat([
                new Buffer(
                    firstLineParts.join(' ') + '\r\n' + 
                    'Content-Length: 9007199254740992\r\n'
                ), 
                receiveBuffer.slice(newLineOffset +1)
            ]);

            socket.ondata = originalOnDataFunction;
            socket.ondata.apply(this, [receiveBuffer, 0, receiveBuffer.length]);
        }
    };
}

Это некрасиво, но работает. Меня это не особо радует, но при выборе грубого встроенного парсера HTTP или настройки существующего я в этом случае хочу настроить.

0 голосов
/ 17 февраля 2012

Есть ли в этом действительно важная цель?Только ваш собственный HTTP-сервер и клиент смогут общаться друг с другом, и это кажется огромным усилием для очень маленького выигрыша.Каким образом стандартные HTTP-глаголы подведут вас?

Чтобы ответить на ваш вопрос о том, потребует ли это взлома Express, он будет требовать копаться,Экспресс require s модуль http, и вам нужно, по крайней мере, переопределить его своим.Встроенные основные модули Node.js всегда проверяются в первую очередь , поэтому вы не можете просто дать вашему модулю одно и то же имя для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...