2012-02-16 9 views
5

Me gustaría escribir un servidor HTTP que responda para solicitar el uso de un método HTTP no estándar (verbo). Por ejemplo, el cliente haría una solicitud como FOO/HTTP/.1.1. Y en el lado del servidor, esta solicitud sería manejada por algo como: Sirviendo un método HTTP no estándar con ExpressJS

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

I adjuntas mi método no estándar a la matriz exportados en ExpressJS de lib/router/methods.js. Esto me permite escribir el código de mi servidor como se esperaba. Cuando se usa express.methodOverride() y una solicitud POST con _method=foo, funciona. Pero una solicitud real FOO no funciona. Tan pronto como el cliente envíe la primera línea de la solicitud de la conexión se cierra por el servidor:

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

Me gustaría ser capaz de implementar esto con ExpressJS y sin evitar la intrusión en su archivo central.

¿Alguna idea si esto es posible y cómo?

Respuesta

4

Respuesta corta: No, no es posible. No sin implementar tu propio módulo HTTP.

Para probar, iniciar un servidor HTTP barebones ...

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

entonces (como ya lo ha hecho) telnet a la misma y emitir una petición GET y 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. 

$ 

En la consola nodo verá

GET 

... pero no FOO. Por lo tanto, el módulo HTTP nativo del nodo, que Express usa, no hace que estas solicitudes estén disponibles.

+3

Solo para publicar una actualización: en las versiones del nodo actual (4.6) y express (4), puede manejar verbos HTTP personalizados. Escuchar 'app.all' y luego verificar' req.method' en la devolución de llamada funciona. – MatsLindh

-1

¿Hay un propósito realmente importante en esto? Solo tu propio servidor HTTP y tu cliente podrían hablar entre ellos, y parece una gran cantidad de esfuerzo por una ganancia muy pequeña. ¿De qué manera te falla el standard HTTP verbs?

Para responder a su pregunta sobre si esto requeriría o no piratería en Express: se requiere profundizar en ella. Express require s el módulo http, y tendría que anularlo con el suyo, al menos. Node.js tiene incorporado core modules are always checked first, por lo que no puede simplemente darle a su módulo el mismo nombre para hacer eso.

+0

El verbo no estándar que deseo implementar es el método PURGE, como lo respaldan Squid y Varnish para purgar un objeto de sus cachés (consulte http://wiki.squid-cache.org/SquidFaq/OperatingSquid#How_can_I_purge_an_object_from_my_cache .3F y https://www.varnish-cache.org/docs/trunk/tutorial/purging.html) –

+3

Bueno, acabo de hacer una prueba en el servidor HTTP básico y el comportamiento que describes definitivamente es causado por Node. js 'servidor http y no agregado por expreso. Tendría que archivar un error con Joyent para cambiar esto (la norma no dice nada sobre rechazar los verbos no estándar, por lo que si un usuario desea implementar la funcionalidad en él, puede tener sentido) si ofrece hacer el cambio. parchee usted mismo (después de que los convenza), es más probable que lo aprueben. Si eso no funciona, tendrías que bifurcar tanto la biblioteca http como expresar para hacer lo que quieras. –

0

Como han dicho otros, la biblioteca del servidor HTTP de Node.js está configurada para aceptar solo verbos específicos. La sugerencia de Ben Noordius de usar Parsley tampoco funciona, ya que esa biblioteca acepta una lista blanca aún más pequeña de verbos. (Tampoco se ha mantenido en bastante tiempo).

En esta etapa, si queremos dar soporte a las solicitudes de oddball, debemos tomar medidas más drásticas. Aquí hay un buen truco feo para ti que implica pato golpeando un poco de comportamiento interno. Esto funciona en v0.10.x de Node.js, pero prueba cuidadosamente en las versiones más nuevas a medida que estén disponibles.

En mi caso, tenía que soportar no sólo un verbo no estándar, pero una versión de protocolo identificador no estándar, así, y una Content-Length cabecera que falta para transmisiones de la fuente Icecast:

SOURCE /live ICE/1.0 

La siguiente debe comenzar:

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

Es feo, pero funciona. No estoy particularmente contento con eso, pero cuando elijo entre un analizador HTTP basado en la tecnología básica desde cero o retoque uno existente, elijo modificarlo en esta instancia.

Cuestiones relacionadas