Nodejs http请求headers的顺序

Nodejs http请求headers的顺序

http协议请求头我们再熟悉不过了,一些诸如content-type,etag等等的协议头规定了我们如何使用http协议,以及反映着一些资源的状态。但是我们有注意过http请求头的顺序吗? 最近在做爬虫程序时发现了这个问题,在爬到某某网站时,发现之前的爬虫程序一直被爆40X错误,很是纳闷,我都是按照浏览器的请求头来伪造的,加上了referr还是如此。怀疑是因为利用算法禁止了ip地址,于是单独请求,发现还是有部分请求被挡住了,爬虫程序无法正常工作了。 但是浏览器端刷新一直很正常,于是将浏览器的请求头按照原封不动的顺序拷入爬虫程序,发现其可以正常使用了。 http请求头真的有顺序吗?下面我们看一下各个浏览器的http请求头情况。

nodejs代码:

    var http = require('http'),
        server = http.createServer(function (req, res){
      var body = JSON.stringify(req.headers) + '\n' + Object.keys(req.headers);
      res.end(body);
     }).listen(3000);

我们分别看下chrome、ff还有IE下的截屏:

enter image description here enter image description here 哼哼,这次我装了win8,不会被鄙视啦! enter image description here

然后我们利用node构造一个请求,把请求头顺序打乱:

var getfn = function(path, cb){
 var request  =  http.request({
   host:'192.168.1.220',
   port:3000,
   path:'/'+path,
   method:'GET',
   headers:{'Accept':'text/html',
      'Content-Type':'application/x-www-form-urlencoded', 
      'Content-Length':'19',
      'User-Agent':'node.js-v0.8.8', 
      'cookie':'userid=123456; mycookie2=abcdefg', 
      'X-Requested-With':'xmlhttprequest',
      'Connection':'keep-alive',
      'Referer':'http://www.cnodejs.org/'}
  }, function(res){
    var body = '';
    res.on('data', function(chunk) {
      // convert chunk to utf8 text:
       body += chunk;
      // process utf8 text chunk
     });
    res.on('end', function() {
      cb(res, body);
     });
  }).on('err', function(e){
   throw e;
  });
  request.end();
}

getfn(’/’, function(res, body){ console.log(body) });

第一次请求头顺序如下: enter image description here

我们变化了host,accept还有referer的位置:

headers:{
  'host':'192.168.1.220',
  'Referer':'http://www.cnodejs.org/',
 'Content-Type':'application/x-www-form-urlencoded', 
  'Content-Length':'19',
  'User-Agent':'node.js-v0.8.8', 
 'cookie':'userid=123456; mycookie2=abcdefg', 
  'X-Requested-With':'xmlhttprequest',
 'Connection':'keep-alive',
  'Accept':'text/html',}

第二次顺序如下: enter image description here

我们看到,请求头的顺序根据我们发送headers的顺序改变了,所以http请求头是有顺序的。原因么因为http协议是基于TCP的,而tcp协议有一个重要的准则,它会严格的根据你发送的数据顺序传输数据,这也就保证了http请求头的顺序。 所以我们也可以利用这一点来对付爬虫程序,因为一般的浏览器都有一定的http请求头顺序,比如accept 必须在accpet-language和accpet-encoding之前。


20 回复

Nodejs http请求headers的顺序

HTTP 协议的请求头是我们日常开发中非常熟悉的一部分,例如 content-typeetag 等字段定义了我们如何使用 HTTP 协议以及反映了资源的状态。然而,我们是否注意到这些请求头的顺序呢?

在开发爬虫程序时,我发现了一个有趣的现象:即使我按照浏览器的请求头来伪造请求,依然会收到 40X 错误。我最初怀疑是因为网站通过算法禁止了我的 IP 地址,但后来发现即便单独请求,部分请求仍然会被阻挡。

经过观察,我发现浏览器端的请求一直很顺畅,于是我尝试将浏览器的请求头按原样复制到我的爬虫程序中,结果发现它可以正常工作了。这让我开始思考:HTTP 请求头真的有顺序吗?

Nodejs 示例代码

让我们先来看一段 Node.js 的代码,该代码创建了一个简单的 HTTP 服务器,并打印出请求头及其键:

const http = require('http');

const server = http.createServer((req, res) => {
  const headersString = JSON.stringify(req.headers);
  const headerKeys = Object.keys(req.headers).join('\n');
  
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end(`${headersString}\n${headerKeys}`);
}).listen(3000);

console.log('Server running at http://localhost:3000/');

这段代码启动了一个 HTTP 服务器,当接收到请求时,它会输出请求头的 JSON 形式以及请求头的键列表。

测试不同的浏览器请求头

为了测试不同浏览器的请求头,你可以使用以下工具来获取 Chrome、Firefox 和 Internet Explorer 的请求头截图。请注意,你需要在你的服务器上部署上述代码并访问 / 路径以获取请求头信息。

打乱请求头顺序

接下来,我们通过 Node.js 发送一个 HTTP 请求,并手动调整请求头的顺序。我们将请求头从原始顺序调整为一个新顺序,并观察服务器返回的请求头顺序:

const http = require('http');

const getfn = (path, cb) => {
  const request = http.request({
    host: '192.168.1.220',
    port: 3000,
    path: '/' + path,
    method: 'GET',
    headers: {
      'Accept': 'text/html',
      'Content-Type': 'application/x-www-form-urlencoded', 
      'Content-Length': '19',
      'User-Agent': 'node.js-v0.8.8', 
      'Cookie': 'userid=123456; mycookie2=abcdefg', 
      'X-Requested-With': 'xmlhttprequest',
      'Connection': 'keep-alive',
      'Referer': 'http://www.cnodejs.org/'
    }
  }, (res) => {
    let body = '';
    res.on('data', (chunk) => {
      body += chunk;
    });
    res.on('end', () => {
      cb(res, body);
    });
  }).on('error', (e) => {
    throw e;
  });

  request.end();
};

getfn('/', (res, body) => {
  console.log(body);
});

如果我们改变请求头的顺序:

const request = http.request({
  host: '192.168.1.220',
  port: 3000,
  path: '/' + path,
  method: 'GET',
  headers: {
    'Host': '192.168.1.220',
    'Referer': 'http://www.cnodejs.org/',
    'Content-Type': 'application/x-www-form-urlencoded', 
    'Content-Length': '19',
    'User-Agent': 'node.js-v0.8.8', 
    'Cookie': 'userid=123456; mycookie2=abcdefg', 
    'X-Requested-With': 'xmlhttprequest',
    'Connection': 'keep-alive',
    'Accept': 'text/html'
  }
}, (res) => {
  // 处理响应...
});

结论

通过上述实验,我们可以看到 HTTP 请求头的顺序确实会影响请求的成功与否。这是因为 HTTP 协议基于 TCP 协议,而 TCP 协议严格地按照发送数据的顺序进行传输。因此,HTTP 请求头的顺序也会严格遵循发送时的顺序。

这也意味着,如果要编写一个有效的爬虫程序,必须确保请求头的顺序与浏览器一致,否则可能会遇到诸如 40X 错误这样的问题。


严重收藏

snoopy 发的文章都能够让大家学到很多东西!赞一个~

![enter image description here][1]

顶 [1]: /upload/4efc278525fa69ac6900009e/1348537677067_1_101203230708_2.jpg

严重收藏

hoho~今天修复了rrestjs的一个隐藏大bug,可能存在丢css样式表的问题。

不敢当啊,互相学习啦~

还发图片?

感谢捧场。

要我写爬虫的话,肯定是找个浏览器的header改一改啊。好吧,还是能屏蔽一些低级爬虫的。。。

爬虫直接copy浏览器的headers 。。。

我都这么干

有啥办法防止爬虫没有

楼主要请教您点问题,希望能回复,我是门外汉对于nodejs不是很懂 希望指点 下面我贴上了代码 我的困惑是为什么最后我的console.log—输出的事undefined

这是程序的代码

enter image description here

这里是routes里的代码

enter image description here

我的思路是当用户没有登入 访问时 会转到login页面去登陆 登陆成功后把req.session.name赋值在转回‘/’ 当req.session.name存在并不为空时 发送者个网页 res.render(‘index’,{name:req.session.name}) 我就是在这个网页里运用socketio的 结果最后的console显示session为undefined 按我的想法里面应该有个name值得呀
希望你能帮我解决疑惑

你说的流程没有问题啊,没大明白你的意思,留个qq私聊吧,我的53822985

时间久了,图片不显示了

这,我要批评一下你了 ’cookie’:‘userid=123456; mycookie2=abcdefg’, cookie的c要大写。。。。。。搞了我半天,对了文档在哪,github里面的md写的不详细

图片怎么都挂了

HTTP 请求头的顺序确实是有意义的,并且在某些情况下可能会导致不同的行为。例如,服务器可能会根据请求头的顺序来判断请求的有效性或合法性。

以下是一个简单的 Node.js 示例代码,展示了如何创建 HTTP 请求并改变请求头的顺序:

const http = require('http');

// 创建服务器
const server = http.createServer((req, res) => {
  let body = JSON.stringify(req.headers) + '\n' + Object.keys(req.headers).join('\n');
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end(body);
}).listen(3000);

// 创建请求
const getfn = (path, cb) => {
  const request = http.request({
    host: 'localhost',
    port: 3000,
    path: '/' + path,
    method: 'GET',
    headers: {
      'Host': 'localhost',
      'Accept': 'text/html',
      'Content-Type': 'application/x-www-form-urlencoded',
      'Content-Length': '19',
      'User-Agent': 'node.js-v0.8.8',
      'Cookie': 'userid=123456; mycookie2=abcdefg',
      'X-Requested-With': 'XMLHttpRequest',
      'Connection': 'keep-alive',
      'Referer': 'http://www.example.com/'
    }
  }, (res) => {
    let body = '';
    res.on('data', (chunk) => {
      body += chunk;
    });
    res.on('end', () => {
      cb(res, body);
    });
  });

  request.end();
};

getfn('/', (res, body) => {
  console.log(body);
});

在这个示例中,我们创建了一个简单的 HTTP 服务器,并通过 http.request 发送一个 GET 请求。你可以修改请求头的顺序并观察服务器返回的请求头顺序。

总结来说,HTTP 请求头是有顺序的,并且这种顺序可能会影响请求的行为。因此,在编写爬虫或其他需要模拟 HTTP 请求的应用程序时,需要注意请求头的顺序。

回到顶部