2012-02-16 41 views
5

Tôi muốn viết một máy chủ HTTP trả lời để yêu cầu sử dụng phương thức HTTP không chuẩn (động từ). Ví dụ, khách hàng sẽ thực hiện một yêu cầu như FOO/HTTP/.1.1. Và ở phía máy chủ, yêu cầu này sẽ được xử lý bởi một cái gì đó như: Cung cấp phương thức HTTP không chuẩn với 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); 

tôi nối phương pháp phi tiêu chuẩn của tôi đến các mảng xuất khẩu trong ExpressJS của lib/router/methods.js. Điều này cho phép tôi viết mã máy chủ của tôi như mong đợi. Khi sử dụng express.methodOverride() và yêu cầu POST với _method=foo, nó hoạt động. Nhưng yêu cầu thực tế FOO không hoạt động. Ngay sau khi khách hàng gửi dòng đầu tiên của các yêu cầu kết nối được đóng bởi máy chủ:

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

Tôi muốn để có thể thực hiện điều này với ExpressJS và không tránh xâm nhập vào tập tin cốt lõi của nó.

Bất kỳ ý tưởng nào nếu điều này là có thể và làm cách nào?

Trả lời

4

Câu trả lời ngắn gọn: Không, không thể. Không phải không triển khai mô-đun HTTP của riêng bạn.

Để kiểm tra, hãy bắt đầu một máy chủ HTTP barebones ...

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

Sau đó (như bạn đã làm) telnet đến nó và ban hành một GET và yêu cầu 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. 

$ 

Trong bảng điều khiển nút, bạn sẽ thấy

GET 

... nhưng không có FOO. Vì vậy, mô-đun HTTP gốc của nút, Express sử dụng, không thực hiện các yêu cầu này.

+3

Chỉ để đăng cập nhật - trong phiên bản hiện tại (4.6) và các phiên bản (4), bạn có thể xử lý các động từ HTTP tùy chỉnh. Nghe 'app.all' và sau đó kiểm tra' req.method' trong công việc gọi lại. – MatsLindh

-1

Có mục đích thực sự quan trọng đối với điều này không? Chỉ có máy chủ và máy khách HTTP của riêng bạn mới có thể nói chuyện với nhau, và nó có vẻ như một lượng lớn nỗ lực cho một sự tăng trưởng rất nhỏ. Theo cách nào thì standard HTTP verbs không thành công?

Để trả lời câu hỏi của bạn về việc liệu điều này có yêu cầu phải xâm nhập vào Express hay không: nó sẽ yêu cầu đào sâu vào nó. Express require s mô-đun http và bạn cần phải tự mình ghi đè điều đó với chính mình. Node.js được xây dựng trong core modules are always checked first, vì vậy bạn không thể chỉ cung cấp cho mô-đun của bạn cùng một tên để làm điều đó.

+0

Động từ không chuẩn mà tôi muốn triển khai là phương pháp PURGE, được Squid và Varnish hỗ trợ để loại bỏ một đối tượng khỏi bộ nhớ cache của chúng (xem http://wiki.squid-cache.org/SquidFaq/OperatingSquid#How_can_I_purge_an_object_from_my_cache) .3F và https://www.varnish-cache.org/docs/trunk/tutorial/purging.html) –

+3

Vâng, tôi vừa thực hiện một thử nghiệm trên đối tượng máy chủ http cơ bản và hành vi mà bạn mô tả chắc chắn là do Node gây ra. máy chủ http js 'và không được thêm bởi express. Bạn sẽ phải tập tin lỗi với Joyent về việc thay đổi này (tiêu chuẩn không nói gì về việc không cho phép động từ không chuẩn, vì vậy nếu người dùng muốn thực hiện chức năng trên nó, nó có thể có ý nghĩa) - nếu bạn đề nghị thực hiện tự vá (sau khi bạn thuyết phục họ), họ có thể có nhiều khả năng chấp nhận nó hơn. Nếu điều đó không hiệu quả, bạn sẽ phải chia cả thư viện http và thể hiện để làm những gì bạn muốn. –

0

Như những người khác đã nói, thư viện máy chủ HTTP của Node.js được cấu hình để chỉ chấp nhận các động từ cụ thể. Đề nghị của Ben Noordius về việc sử dụng Parsley cũng không có tác dụng vì thư viện đó chấp nhận một danh sách trắng nhỏ hơn các động từ. (Nó cũng không được duy trì trong một thời gian nữa.)

Ở giai đoạn này, nếu chúng ta muốn hỗ trợ các yêu cầu kỳ quặc, chúng ta phải thực hiện các biện pháp quyết liệt hơn. Đây là một hack xấu xí tốt đẹp cho bạn có liên quan đến vịt đấm một số hành vi nội bộ. Điều này làm việc trên v0.10.x của Node.js, nhưng kiểm tra cẩn thận trên các phiên bản mới hơn khi chúng có sẵn.

Trong trường hợp của tôi, tôi cần thiết để hỗ trợ không chỉ là một động từ phi tiêu chuẩn, nhưng một phiên bản giao thức nhận dạng phi tiêu chuẩn là tốt, và một thiếu Content-Length tiêu đề cho suối nguồn Icecast:

SOURCE /live ICE/1.0 

Sau đây sẽ giúp bạn bắt đầu:

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

Thật xấu xí, nhưng hoạt động. Tôi không đặc biệt hài lòng về nó, nhưng khi lựa chọn giữa một trình phân tích cú pháp HTTP được xây dựng sẵn từ mặt đất hoặc tinh chỉnh một trình phân tích cú pháp hiện có, tôi chọn tinh chỉnh trong trường hợp này.

Các vấn đề liên quan