nodeのrequestライブラリの`json`オプションの取り扱いについて調べてみた
TL;DR
つべこべいわず、該当コード見たほうが早い
コードを読んでもわからなかったら続きをどうぞ。
簡単に調べてみた
nodeのHTTP ClientであるrequestをPOST時に利用したとき、
json: true
のoptionがあるけど、body
がjsonかされないっていう話を聞いたので、調べてみた。
- https://stackoverflow.com/questions/27190447/pass-json-to-http-post-request
- send Content-Type: application/json post with node.js
どうやら、optionのjson
にBooleanではなく、直接Objectを渡したほうが早い。
実装コードから調べてみた
オプションのjson
をどうのように取り扱っているか
冒頭でも紹介したhttps://github.com/request/request/blob/master/request.js#L1278-L1313である。
いろいろぶっ飛ばして、
Request.prototype.json = function (val) {
var self = this
// 中略
self._json = true
if (typeof val === 'boolean') {
// jsonオプションの値がbooleanの場合
if (self.body !== undefined) {
// bodyがundefinedでなけれあば
if (!/^application\/x-www-form-urlencoded\b/.test(self.getHeader('content-type'))) {
// content-typeが application/x-www-form-urlencoded とマッチした倍、
// https://github.com/request/request/blob/master/lib/helpers.js#L20-L28
self.body = safeStringify(self.body, self._jsonReplacer)
} else {
// rfc3986でエンコード
// https://github.com/request/request/blob/master/lib/querystring.js#L42-L46
self.body = self._qs.rfc3986(self.body)
}
if (!self.hasHeader('content-type')) {
// content-typeが指定されていなければ、application/jsonに指定
self.setHeader('content-type', 'application/json')
}
}
} else {
// jsonがbooleanでないとき
// bodyに入れ直していますね。
self.body = safeStringify(val, self._jsonReplacer)
if (!self.hasHeader('content-type')) {
// content-typeが指定されていなければ、application/jsonに指定
self.setHeader('content-type', 'application/json')
}
}
return self
}
これで謎は解けました。
rfc3986
が出てきたのですが、別の章で紹介。
もっと詳しく見てみる
渋川さんの記事が大変参考になります。 読んでいた当時はよくわからなかったのですが、今となっては噛み締めて読めますね。。。 RFC大事。
RFC3986に厳格に対応したライブラリ
- ljharb/qs
- Query String - Node.js v9.11.1 Documentation
- requests内部で利用されていますね
RFC3986関連