はじめに
Node.jsを勉強していて、setHeaderとwriteHeadって何が違うの...?となったのでソースコードなどから調べてみました。
setHeaderのソースコードを見てみる
setHeaderの実装部分を示します。setHeaderはheadersに名前と値を格納しているだけということがわかります。
headersに値を格納しているので、例えばgetHeader(name)によって値を取得することができます。
OutgoingMessage.prototype.setHeader=functionsetHeader(name,value){if(this._header){thrownewERR_HTTP_HEADERS_SENT('set');}validateHeaderName(name);validateHeaderValue(name,value);letheaders=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に格納するだけとなります。
letheaders;if(this[kOutHeaders]){// Slow-case: when progressive API and header fields are passed.letk;if(ArrayIsArray(obj)){if(obj.length%2!==0){thrownewERR_INVALID_ARG_VALUE('headers',obj);}for(letn=0;n<obj.length;n+=2){k=obj[n+0];if(k)this.setHeader(k,obj[n+1]);}}elseif(obj){constkeys=ObjectKeys(obj);for(leti=0;i<keys.length;i++){k=keys[i];if(k)this.setHeader(k,obj[k]);}}if(k===undefined&&this._header){thrownewERR_HTTP_HEADERS_SENT('render');}// Only progressive api is usedheaders=this[kOutHeaders];}else{// Only writeHead() calledheaders=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"consthttp=require("http");constserver=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'});constport=8000;server.listen(port,()=>{console.info("listening on"+port);})
setHeaderを使っていない場合undefinedと表示されます。
"use strict"consthttp=require("http");constserver=http.createServer((req,res)=>{res.writeHead(200,{'content-Type':'text/html; charset=UTF-8'});res.end();console.log(res.getHeader("content-Type"));// => undefined});constport=8000;server.listen(port,()=>{console.info("listening on"+port);})
まとめ
- setHeaderを使うと値をキャッシュすることができる
- 例えばgetHeaderなどで値を取り出すことができる
- setHeaderの実行後はwriteHeadでも値のキャッシュが行われるようになる
- writeHeadだけを使うと値のキャッシュなどが行われない
- その分、処理は早くなる