Node.js http.ServerRequest 响应永远不会到达
我正在使用 Node.js 创建一个反向 HTTP 代理,以获取乐趣。目前代码非常简单。它侦听 127.0.0.1:8080 上的 HTTP 请求并将这些请求转发到 hostname.com,然后将来自 hostname.com 的响应转发回客户端。还没有做任何花哨的事情,例如重写重定向标头等。代码如下:
var http = require('http');
var server = http.createServer(
function(request, response) {
var proxy = http.createClient(8080, 'hostname.com')
var proxyRequest = proxy.request(request.method, request.url, request.headers);
proxyRequest.on('response', function(proxyResponse) {
proxyResponse.on('data', function(chunk) {
response.write(chunk, 'binary');
});
proxyResponse.on('end', function() {
response.end();
});
response.writeHead(proxyResponse.statusCode, proxyResponse.headers);
});
request.on('data', function(chunk) {
proxyRequest.write(chunk, 'binary');
});
request.on('end', function() {
proxyRequest.end();
});
proxyRequest.on('close', function(err) {
if (err) {
console.log('close error: ' + err + ' for ' + request.url);
}
});
});
server.listen(8080);
server.on('clientError', function(exception) {
console.log('boo a clientError occured :(');
});
一切似乎都运行良好,直到我浏览到需要获取许多附加资源(例如图像)的页面。当然,浏览器会向反向代理生成许多 GET 请求来获取这些额外的资源。
当我浏览到这样的页面时,某些附加资源的 http.ServerRequests 永远不会收到响应。如果我重新启动页面请求,它几乎总是会成功,因为第一次尝试成功获取的所有资源都被缓存(因此浏览器不会再次尝试获取它们),所以现在浏览器只需要获取一些丢失的资源那些。
尽管我不确定,但我猜测我会达到某种连接限制。任何帮助将不胜感激!
I'm creating a reverse HTTP proxy using Node.js for fun. The code is pretty simple at the moment. It listens on 127.0.0.1:8080 for HTTP requests and forwards these to hostname.com, responses from hostname.com are then forwarded back to the client. Nothing fancy is done yet such as rewriting redirect headers, etc. The code is as follows:
var http = require('http');
var server = http.createServer(
function(request, response) {
var proxy = http.createClient(8080, 'hostname.com')
var proxyRequest = proxy.request(request.method, request.url, request.headers);
proxyRequest.on('response', function(proxyResponse) {
proxyResponse.on('data', function(chunk) {
response.write(chunk, 'binary');
});
proxyResponse.on('end', function() {
response.end();
});
response.writeHead(proxyResponse.statusCode, proxyResponse.headers);
});
request.on('data', function(chunk) {
proxyRequest.write(chunk, 'binary');
});
request.on('end', function() {
proxyRequest.end();
});
proxyRequest.on('close', function(err) {
if (err) {
console.log('close error: ' + err + ' for ' + request.url);
}
});
});
server.listen(8080);
server.on('clientError', function(exception) {
console.log('boo a clientError occured :(');
});
All appears to work well until I browse to a page that requires many additional resources (such as images) to be fetched. Naturally the browser will generate a number of GET requests to the reverse proxy to fetch these additional resources.
When I do browse to such a page some of the http.ServerRequests for the additional resources never receive responses. If I restart the page request it almost always results in success as all the resources that were successfully fetched on the first attempt were cached (hence the browser doesn't try GET them again) and so now the browser only needs to grab a few missing ones.
At a guess I would imagine I'm hitting some kind of connection limit although I'm not sure. Any help would be greatly appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您在代理上设置 Wireshark,您几乎肯定会看到发生了什么。 (请注意,为此您可能需要第二台计算机,因为某些 TCP/IP 堆栈不提供 Wireshark 可以侦听环回流量的任何内容 - 请参阅 this)
我几乎可以肯定,您在这里遇到的问题都归因于
连接:
标头 - 代理必须解析此标头并正确处理它。据猜测,我想说您的代码正在处理Connection: keep-alive
流中的第一个请求,并忽略其余部分。作为代理,您应该在转发请求之前解析并删除/替换此标头以及任何关联的标头(在本例中为Keep-Alive:
标头)到服务器。如果您想构建 HTTP/1.1 代理,阅读 RFC 2616 并遵守它为他们的行为制定的许多规则。您在这里遇到的特定问题记录在 第 14.10 节。
If you set up Wireshark on the proxy, you'll almost certainly see what's happening. (Note that you may need a second machine for this, because some TCP/IP stacks don't provide anything that Wireshark can listen on for loopback traffic - see this)
I'm almost certain that the problem(s) you are running into here are all down to the
Connection:
header - proxies MUST parse this header and handle it correctly. At a guess, I would say your code is handling the first request in aConnection: keep-alive
stream and ignoring the rest. As a proxy, you are supposed to parse and remove/replace this header, and any associated headers (in this case theKeep-Alive:
header), before forwarding the request to the server.If you want to build a HTTP/1.1 proxy, it's very important that you read RFC 2616 and adhere to the many, many rules that it places on their behaviour. The particular problem you are running into here is documented in section 14.10.