LoginSignup
4
3

More than 3 years have passed since last update.

[Node.js] response.writeHeadとresponse.setHeaderって何が違うの?

Posted at

はじめに

Node.jsを勉強していて、setHeaderとwriteHeadって何が違うの...?となったのでソースコードなどから調べてみました。

setHeaderのソースコードを見てみる

setHeaderの実装部分を示します。setHeaderはheadersに名前と値を格納しているだけということがわかります。
headersに値を格納しているので、例えばgetHeader(name)によって値を取得することができます。

OutgoingMessage.prototype.setHeader = function setHeader(name, value) {
  if (this._header) {
    throw new ERR_HTTP_HEADERS_SENT('set');
  }
  validateHeaderName(name);
  validateHeaderValue(name, value);

  let headers = this[kOutHeaders];
  if (headers === null)
    this[kOutHeaders] = headers = ObjectCreate(null);

  headers[name.toLowerCase()] = [name, value];
};

(https://github.com/nodejs/node/blob/master/lib/_http_outgoing.js)

writeHeadのソースコードを見てみる

writeHeadの一部を抜き出したものを示します。
this[kOutHeaders]がtruthyな値かどうかで場合分けがされています。this[kOutHeaders]はヘッダーの名前と値をキャッシュしているデータになるので、setHeader()などでキャッシュされているかどうかで分かれることになります。
setHeader()が呼び出されていた場合、writeHeadの内部でもsetHeader()が実行され、writeHeadの引数で指定した名前と値もキャッシュされます。
一方、setHeader()が呼び出されていない場合、引数で指定した名前と値をheadersに格納するだけとなります。

  let headers;
  if (this[kOutHeaders]) {
    // Slow-case: when progressive API and header fields are passed.
    let k;
    if (ArrayIsArray(obj)) {
      if (obj.length % 2 !== 0) {
        throw new ERR_INVALID_ARG_VALUE('headers', obj);
      }

      for (let n = 0; n < obj.length; n += 2) {
        k = obj[n + 0];
        if (k) this.setHeader(k, obj[n + 1]);
      }
    } else if (obj) {
      const keys = ObjectKeys(obj);
      for (let i = 0; i < keys.length; i++) {
        k = keys[i];
        if (k) this.setHeader(k, obj[k]);
      }
    }
    if (k === undefined && this._header) {
      throw new ERR_HTTP_HEADERS_SENT('render');
    }
    // Only progressive api is used
    headers = this[kOutHeaders];
  } else {
    // Only writeHead() called
    headers = obj;
  }

(https://github.com/nodejs/node/blob/299984561eff45bddc5bb802e5b22d47277e5ca5/lib/_http_server.js)

具体例

setHeaderを使っている場合は、console.log(res.getHeader("content-Type"));が実行されると
content-Type':'text/html; charset=UTF-8と表示されます。

"use strict"
const http = require("http");
const server = http.createServer((req, res) => {
    res.setHeader('Set-Cookie', "accessed_date=" + Date.now() + ";");

    res.writeHead(200, {
        'content-Type':'text/html; charset=UTF-8'
    });

    res.end();
    console.log(res.getHeader("content-Type")); // => 'content-Type':'text/html; charset=UTF-8'
});

const port = 8000;
server.listen(port, () => {
    console.info("listening on" + port);
})

setHeaderを使っていない場合undefinedと表示されます。

"use strict"
const http = require("http");
const server = http.createServer((req, res) => {
    res.writeHead(200, {
        'content-Type':'text/html; charset=UTF-8'
    });

    res.end();
    console.log(res.getHeader("content-Type")); // => undefined
});

const port = 8000;
server.listen(port, () => {
    console.info("listening on" + port);
})

まとめ

  • setHeaderを使うと値をキャッシュすることができる
    •  例えばgetHeaderなどで値を取り出すことができる
    •  setHeaderの実行後はwriteHeadでも値のキャッシュが行われるようになる
  • writeHeadだけを使うと値のキャッシュなどが行われない
    • その分、処理は早くなる
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3