Express のレスポンス関連メソッド「res.end()」「res.send()」「res.json()」の違い
Express でレスポンスを返す時、res.end()・res.send()・res.json() などのメソッドを使用するが、それぞれの違いは何か、res.end() は必ず呼ばなければならないのか、あたりを調べた。
Express の API リファレンスを呼んでみる
まずは Express の API リファレンスを読んでみよう。
res.send()
The body parameter can be a Buffer object, a String, an object, or an Array.
When the parameter is an
ArrayorObject, Express responds with the JSON representation:
色んなレスポンスが返せる汎用的なメソッド。引数に配列やオブジェクトを渡した場合は、Content-Type を application/json に設定して適切に処理してくれるようだ。
…じゃあ、res.json() との違いは?
res.json()
Sends a JSON response. This method sends a response (with the correct content-type) that is the parameter converted to a JSON string using JSON.stringify().
引数のオブジェクトや配列などを JSON.stringify() で string に直し、適切な Content-Type をセットしてレスポンスする。
…ふむ、ココまでは res.send() との違いを感じられない。
res.end()
Use to quickly end the response without any data. If you need to respond with data, instead use methods such as
res.send()andres.json().
何のデータも返さない時に使う。データを返したい時は res.send() や res.json() を使ってね、とのこと。
ということは、res.send('Hoge').end() とか res.json({ result: 'OK' }).end() みたいな呼び方はしなくて良い、ってことだな。疑問の一つは解決した。
res.send() と res.json() の違いは?
res.send() で res.json() と同じようなことができてるっぽいじゃん。何が違うの?ということで res.json() の実装を見てみよう。
コレを見ると、リクエストヘッダを設定し、JSON.stringify() したボディを res.send() に渡しているだけのようだ。
じゃあ res.send() の実装はというと。
- express/response.js at 4.x · expressjs/express · GitHub …
res.send定義
res.send() の引数に Buffer でないオブジェクトが渡された場合は、res.json() を呼び出して JSON.stringify() をかけて再度 res.send() 自身を呼び出している。結局は、res.json() は res.send() のエイリアス的な役割でしかなく、res.send() で JSON が送れるのも内部で res.json() を呼び出しているから、という関係のようだ。よく出来ている。
res.send() の引数 body が文字列になったら、ヘッダを調整して res.end() を呼んでレスポンスしている。この res.end() は http.ServerResponse.prototype 由来のモノのようで、Express 側では特に何もしていないようだ。
- express/response.js at 4.x · expressjs/express · GitHub …
var res部分 - HTTP | Node.js v11.10.0 Documentation … Node.js の
response.end()の API リファレンス
res.end() が「何もデータを返さないレスポンス用のメソッド」なのではなく、Node.js の response.end() が求める引数を与えていないために空のレスポンスが返る、という仕組みのようだ。
結論
- JSON を返す時は
res.send({})でもres.json({})でも全く同じ結果になる。どっちでも好きに使えば良い。- 内部では相互の関数を呼び合ってリクエストヘッダやリクエストボディを調整している。
res.end()は Node.js のresponse.end()と同じモノ。引数を渡さずに使うことで、空のレスポンスを返す用に使うのが良い。- Node.js の
response.end()が求める引数を自分で与えればレスポンスデータを返せるっぽいが、Express が上手く処理してくれるres.send()やres.json()を使えば良いので、無意味なことかと。
- Node.js の
res.send().end()とかres.json().end()といった併用は不要。res.send()・res.json()の時点でres.end()を呼んでレスポンスを返している。併用してもおかしくはならないようだが、不必要。
ということのようだ。
- 参考 : res.json() vs res.send() vs res.end() in Express
- こちらによると、「
res.json()の方はJSON.stringify()の際のreplacerとspaceが設定されている点でres.send()と異なる」とされているが、Express 4.x 系の実装を見る限り、少し意味合いが違うっぽい。
- こちらによると、「