zoukankan      html  css  js  c++  java
  • http模块中的writeHead

    writeHead

    response.writeHead(statusCode[, statusMessage][, headers])
    statusMessage 好像没什么用,一般用不到。
    返回对 ServerResponse 的引用,以便可以链式调用。

    const body = 'hello world';
    response
      .writeHead(200, {
        'Content-Length': Buffer.byteLength(body),
        'Content-Type': 'text/plain'
      })
      .end(body);
    

    如果在调用writeHead之前调用了 response.write() 或 response.end(),会报错。

    net::ERR_INVALID_CHUNKED_ENCODING
    

    当使用 response.setHeader() 设置响应头时,则与传给 response.writeHead() 的任何响应头合并,且 response.writeHead() 的优先。

    res.setHeader('X-Foo', 'bar');
    res.writeHead(200, { 'X-Foo': 'bar11' });
    console.log(res.getHeader('Content-Type') ); // bar11
    

    调用writeHead之后调用setHeader,报错:

    Cannot set headers after they are sent to the client
    
    // 在源代码中有如下的定义,这里是报错的地方
    OutgoingMessage.prototype.setHeader = function setHeader(name, value) {
      if (this._header) {
        throw new ERR_HTTP_HEADERS_SENT('set');
      }
    }
    

    如果调用此方法并且尚未调用 response.setHeader(),则直接将提供的响应头值写入网络通道而不在内部进行缓存,响应头上的 response.getHeader() 将不会产生预期的结果。

    response.writeHead(200, { 'Content-Type': 'text/plain' });
    console.log(response.getHeader('Content-Type') ); // undefined
    // 没有内部缓存导致获取不到刚刚设置的'content-type'
    

    对比先调用response.setHeader,再调用writeHead:

    res.setHeader('X-Foo', 'bar');
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    console.log(res.getHeader('Content-Type') ); // 'text/plain'
    // 可以获取到刚刚设置的content-type
    

    如果需要渐进的响应头填充以及将来可能的检索和修改,则改用 response.setHeader()。

    // 返回 content-type = text/plain
    const server = http.createServer((req, res) => {
      res.setHeader('Content-Type', 'text/html');
      res.setHeader('X-Foo', 'bar');
      res.writeHead(200, { 'Content-Type': 'text/plain' });
      res.end('ok');
    });
    

    之前在遇到一个问题:

    代码中只是重新定义了res.writeHead,在向客户端返回数据的时候会自动调用res.writeHead,问题在于代码中并没有调用writeHead ?

    var http = require('http')
    var server  = http.createServer(function (req,res) {
        var _ = res.writeHead
        res.writeHead = function(...arg){
            console.log(arg);
            _.call(this,arg)
        }
        res.write('adfasdfsf') // 调用write会触发writeHead
        res.end()
    })
    server.listen(10899,function () {
        console.log(121212);
    })
    

    通过断点跟踪发现有如下的逻辑链条:

    ObjectSetPrototypeOf(ServerResponse.prototype, OutgoingMessage.prototype);// 原型继承,response上面的部分方法继承自OutgoingMessage
    
    // write方法,当调用response.write的时候就是调用的这里
    OutgoingMessage.prototype.write = function write(chunk, encoding, callback) {
      const ret = write_(this, chunk, encoding, callback, false);
      if (!ret)
        this[kNeedDrain] = true;
      return ret;
    };
    
    function write_(msg, chunk, encoding, callback, fromEnd) {
      if (!msg._header) {
        msg._implicitHeader();
      }
    }
    
    // 调用writeHead,所以只要执行write方法就会调用writeHead方法	
    ServerResponse.prototype._implicitHeader = function _implicitHeader() {
      this.writeHead(this.statusCode);
    };
    
    ServerResponse.prototype.writeHead = writeHead;
    function writeHead(statusCode, reason, obj) {}
    

    同样在在调用response.end的时候也有类似的处理:

    ServerResponse.prototype.end继承自OutgoingMessage.prototype.end
    
    OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
     ......
      if (chunk) {
     		.........
        write_(this, chunk, encoding, null, true);
      } else if (this.finished) {
        ......
      } else if (!this._header) {
        this._contentLength = 0;
        this._implicitHeader();
      }
    }
    // 如果传入了第一个参数,调用write_,接下来就是上面的步骤
    // 如果没有传入参数,并且没有header,直接调用了_implicitHeader,其实就是this.writeHead(this.statusCode);
    
  • 相关阅读:
    Hihocoder 1275 扫地机器人 计算几何
    CodeForces 771C Bear and Tree Jumps 树形DP
    CodeForces 778D Parquet Re-laying 构造
    CodeForces 785E Anton and Permutation 分块
    CodeForces 785D Anton and School
    CodeForces 785C Anton and Fairy Tale 二分
    Hexo Next 接入 google AdSense 广告
    如何统计 Hexo 网站的访问地区和IP
    Design and Implementation of Global Path Planning System for Unmanned Surface Vehicle among Multiple Task Points
    通过ODBC接口访问人大金仓数据库
  • 原文地址:https://www.cnblogs.com/walkermag/p/13586901.html
Copyright © 2011-2022 走看看