Skip to main content

nodeのrequestライブラリの`json`オプションの取り扱いについて調べてみた

TL;DR

つべこべいわず、該当コード見たほうが早い

コードを読んでもわからなかったら続きをどうぞ。

簡単に調べてみた

nodeのHTTP ClientであるrequestをPOST時に利用したとき、 json: trueのoptionがあるけど、bodyがjsonかされないっていう話を聞いたので、調べてみた。

どうやら、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に厳格に対応したライブラリ

RFC3986関連