如何在解析 Node 中的响应之前 change/remove/ignore 一个 http header?
How to change/remove/ignore a http header just before parsing the response in Node?
我目前正在使用 Node 从 API (Discogs API) 获取数据,但在请求时出现此错误:
{ [Error: Parse Error] bytesParsed: 0, code: 'HPE_INVALID_CONSTANT' }
使用此 link:http://api.discogs.com/releases/249504(但当 content-length != actual content length
时我对其他所有请求都有相同的错误)
还有这段代码:
var http = require('http');
var options = {
hostname: 'api.discogs.com',
port: 80,
path: '/releases/249504',
method: 'GET'
};
var req = http.request(options, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
res.on('data', function(d) {
console.log(d);
});
});
req.end();
req.on('error', function(e) {
console.error(e);
});
我发现 Content-length 值总是小于实际响应字节长度。
Content-length : 2142
Actual Byte Length : 7,734 Bytes (according to https://mothereff.in/byte-counter)
我了解到 Node 的解析器非常严格,这就是它无法解析响应的原因。
最后,我问你是否有办法在 Node 解析响应之前 ignore/modify/delete 和 Header,这样解析器就可以通过忽略 Content-Length ?
这与(感知到的,见下文)无效 content-length 无关,因为它也无法使用 cURL:
$ curl http://api.discogs.com/releases/249504
curl: (52) Empty reply from server
显然 API 服务器要求设置用户代理 header:
var options = {
hostname : 'api.discogs.com',
port : 80,
path : '/releases/249504',
method : 'GET',
headers : { 'user-agent' : 'foo/1.0' }
};
至于content-length的区别:2142是gzip-compressed响应(content-encoding: gzip
)的大小,7734是未压缩响应的大小。显然,您的 byte-counter 测试仅请求未压缩的响应,但您检查 header 的客户端正在请求压缩响应。
回到 在解析 Node 中的响应之前更改 headers 的主题,您可以通过将标准处理程序替换为您自己的函数来轻松完成socket: "data"
事件。
https://github.com/nodejs/http2/blob/master/lib/_http_client.js#L655
var req = http.request(options, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers); // without "Pragma: public" header
res.on('data', function(d) {
console.log(d);
});
});
// catch socket object on conection initialization
req.on('socket', function (socket) {
// https://nodejs.org/api/events.html
var standardHandler = socket.listeners('data')[0];
socket.off('data', standardHandler);
socket.on('data', function(data) {
var str = data.toString();
console.log(str);
// HTTP/1.x 200 OK
// Date: Sat, 28 Nov 2009 04:36:25 GMT
// Connection: close
// Pragma: public
// Expires: Sat, 28 Nov 2009 05:36:25 GMT
// Cache-Control: max-age=3600, public
// Content-Type: text/html; charset=UTF-8
// Content-Length: 533424
// Content-Encoding: gzip
// Vary: Accept-Encoding, Cookie, User-Agent
//
// <!DOCTYPE html PUBLIC "-//W3C//DTD
// Do anything you need
// removing 4 line
var lines = str.split('\r\n');
lines.splice(3, 1)
str = lines.join('\r\n');
// Now pass new data onto standard request handler
standardHandler.call(socket, Buffer.from(str, "utf-8"));
})
});
req.end();
我目前正在使用 Node 从 API (Discogs API) 获取数据,但在请求时出现此错误:
{ [Error: Parse Error] bytesParsed: 0, code: 'HPE_INVALID_CONSTANT' }
使用此 link:http://api.discogs.com/releases/249504(但当 content-length != actual content length
时我对其他所有请求都有相同的错误)
还有这段代码:
var http = require('http');
var options = {
hostname: 'api.discogs.com',
port: 80,
path: '/releases/249504',
method: 'GET'
};
var req = http.request(options, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
res.on('data', function(d) {
console.log(d);
});
});
req.end();
req.on('error', function(e) {
console.error(e);
});
我发现 Content-length 值总是小于实际响应字节长度。
Content-length : 2142
Actual Byte Length : 7,734 Bytes (according to https://mothereff.in/byte-counter)
我了解到 Node 的解析器非常严格,这就是它无法解析响应的原因。
最后,我问你是否有办法在 Node 解析响应之前 ignore/modify/delete 和 Header,这样解析器就可以通过忽略 Content-Length ?
这与(感知到的,见下文)无效 content-length 无关,因为它也无法使用 cURL:
$ curl http://api.discogs.com/releases/249504
curl: (52) Empty reply from server
显然 API 服务器要求设置用户代理 header:
var options = {
hostname : 'api.discogs.com',
port : 80,
path : '/releases/249504',
method : 'GET',
headers : { 'user-agent' : 'foo/1.0' }
};
至于content-length的区别:2142是gzip-compressed响应(content-encoding: gzip
)的大小,7734是未压缩响应的大小。显然,您的 byte-counter 测试仅请求未压缩的响应,但您检查 header 的客户端正在请求压缩响应。
回到 在解析 Node 中的响应之前更改 headers 的主题,您可以通过将标准处理程序替换为您自己的函数来轻松完成socket: "data"
事件。
https://github.com/nodejs/http2/blob/master/lib/_http_client.js#L655
var req = http.request(options, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers); // without "Pragma: public" header
res.on('data', function(d) {
console.log(d);
});
});
// catch socket object on conection initialization
req.on('socket', function (socket) {
// https://nodejs.org/api/events.html
var standardHandler = socket.listeners('data')[0];
socket.off('data', standardHandler);
socket.on('data', function(data) {
var str = data.toString();
console.log(str);
// HTTP/1.x 200 OK
// Date: Sat, 28 Nov 2009 04:36:25 GMT
// Connection: close
// Pragma: public
// Expires: Sat, 28 Nov 2009 05:36:25 GMT
// Cache-Control: max-age=3600, public
// Content-Type: text/html; charset=UTF-8
// Content-Length: 533424
// Content-Encoding: gzip
// Vary: Accept-Encoding, Cookie, User-Agent
//
// <!DOCTYPE html PUBLIC "-//W3C//DTD
// Do anything you need
// removing 4 line
var lines = str.split('\r\n');
lines.splice(3, 1)
str = lines.join('\r\n');
// Now pass new data onto standard request handler
standardHandler.call(socket, Buffer.from(str, "utf-8"));
})
});
req.end();