Serving non-standard HTTP method with ExpressJS

前端 未结 3 936
我在风中等你
我在风中等你 2021-01-05 05:57

I would like to write an HTTP server that answer to request using a non-standard HTTP method (verb). For instance, the client would make a request like FOO / HTTP/.1.1

相关标签:
3条回答
  • 2021-01-05 06:30

    Short answer: No, it's not possible. Not without implementing your own HTTP module.

    To test, start a barebones HTTP server ...

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

    Then (as you've already done) telnet to it and issue a GET and FOO request ...

    $ 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.
    
    $ 
    

    In node console you'll see

    GET
    

    ... but no FOO. So, node's native HTTP module, which Express uses, does not make these requests available.

    0 讨论(0)
  • 2021-01-05 06:41

    As others have said, Node.js' HTTP server library is configured to accept only specific verbs. Ben Noordius' suggestion of using Parsley doesn't work either, since that library accepts an even smaller whitelist of verbs. (It also hasn't been maintained in quite some time.)

    At this stage, if we want to support oddball requests, we have to take more drastic measures. Here's a nice ugly hack for you that involves duck punching some internal behavior. This works on v0.10.x of Node.js, but test carefully on newer versions as they become available.

    In my case, I needed to support not only a non-standard verb, but a non-standard protocol version identifier as well, and a missing Content-Length header for Icecast source streams:

    SOURCE /live ICE/1.0
    

    The following should get you started:

    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]);
            }
        };
    }
    

    It's ugly, but works. I'm not particularly happy about it, but when choosing between a rough built-from-the-ground-up HTTP parser or tweaking an existing one, I choose to tweak in this instance.

    0 讨论(0)
  • 2021-01-05 06:44

    Node has a hard-coded whitelist of acceptable HTTP verbs in C.

    In order to accept custom verbs, you must modify the HTTP parser and recompile node.


    You mentioned that you're trying to implement PURGE, which was added to the whitelist in v0.7.5.

    0 讨论(0)
提交回复
热议问题