- options 参数详解
- HttpClient 默认全局配置
data: Object
dataAsQueryString: Boolean
content: String|Buffer
files: Mixed
stream: ReadStream
writeStream: WriteStream
consumeWriteStream: Boolean
method: String
contentType: String
dataType: String
fixJSONCtlChars: Boolean
headers: Object
timeout: Number|Array
agent: HttpAgent
httpsAgent: HttpsAgent
auth: String
digestAuth: String
followRedirect: Boolean
maxRedirects: Number
formatRedirectUrl: Function(from, to)
beforeRequest: Function(options)
streaming: Boolean
gzip: Boolean
timing: Boolean
ca,rejectUnauthorized,pfx,key,cert,passphrase,ciphers,secureProtocol
options 参数详解
由于 HTTP 请求的复杂性,导致 httpclient.request(url, options)
的 options 参数会非常多。接下来将会以参数说明和代码配合一起讲解每个可选参数的实际用途。
HttpClient 默认全局配置
// config/config.default.js
exports.httpclient = {
// 是否开启本地 DNS 缓存,默认关闭,开启后有两个特性
// 1. 所有的 DNS 查询都会默认优先使用缓存的,即使 DNS 查询错误也不影响应用
// 2. 对同一个域名,在 dnsCacheLookupInterval 的间隔内(默认 10s)只会查询一次
enableDNSCache: false,
// 对同一个域名进行 DNS 查询的最小间隔时间
dnsCacheLookupInterval: 10000,
// DNS 同时缓存的最大域名数量,默认 1000
dnsCacheMaxLength: 1000,
request: {
// 默认 request 超时时间
timeout: 3000,
},
httpAgent: {
// 默认开启 http KeepAlive 功能
keepAlive: true,
// 空闲的 KeepAlive socket 最长可以存活 4 秒
freeSocketTimeout: 4000,
// 当 socket 超过 30 秒都没有任何活动,就会被当作超时处理掉
timeout: 30000,
// 允许创建的最大 socket 数
maxSockets: Number.MAX_SAFE_INTEGER,
// 最大空闲 socket 数
maxFreeSockets: 256,
},
httpsAgent: {
// 默认开启 https KeepAlive 功能
keepAlive: true,
// 空闲的 KeepAlive socket 最长可以存活 4 秒
freeSocketTimeout: 4000,
// 当 socket 超过 30 秒都没有任何活动,就会被当作超时处理掉
timeout: 30000,
// 允许创建的最大 socket 数
maxSockets: Number.MAX_SAFE_INTEGER,
// 最大空闲 socket 数
maxFreeSockets: 256,
},
};
应用可以通过 config/config.default.js
覆盖此配置。
data: Object
需要发送的请求数据,根据 method
自动选择正确的数据处理方式。
- GET,HEAD:通过
querystring.stringify(data)
处理后拼接到 url 的 query 参数上。 - POST,PUT 和 DELETE 等:需要根据
contentType
做进一步判断处理。contentType = json
:通过JSON.stringify(data)
处理,并设置为 body 发送。- 其他:通过
querystring.stringify(data)
处理,并设置为 body 发送。
// GET + data
ctx.curl(url, {
data: { foo: 'bar' },
});
// POST + data
ctx.curl(url, {
method: 'POST',
data: { foo: 'bar' },
});
// POST + JSON + data
ctx.curl(url, {
method: 'POST',
contentType: 'json',
data: { foo: 'bar' },
});
dataAsQueryString: Boolean
如果设置了 dataAsQueryString=true
,那么即使在 POST 情况下,也会强制将 options.data
以 querystring.stringify
处理之后拼接到 url
的 query 参数上。
可以很好地解决以 stream
发送数据,且额外的请求参数以 url
query 形式传递的应用场景:
ctx.curl(url, {
method: 'POST',
dataAsQueryString: true,
data: {
// 一般来说都是 access token 之类的权限验证参数
accessToken: 'some access token value',
},
stream: myFileStream,
});
content: String|Buffer
发送请求正文,如果设置了此参数,那么会直接忽略 data
参数。
ctx.curl(url, {
method: 'POST',
// 直接发送原始 xml 数据,不需要 HttpClient 做特殊处理
content: '<xml><hello>world</hello></xml>',
headers: {
'content-type': 'text/html',
},
});
files: Mixed
文件上传,支持格式: String | ReadStream | Buffer | Array | Object
。
ctx.curl(url, {
method: 'POST',
files: '/path/to/read',
data: {
foo: 'other fields',
},
});
多文件上传:
ctx.curl(url, {
method: 'POST',
files: {
file1: '/path/to/read',
file2: fs.createReadStream(__filename),
file3: Buffer.from('mock file content'),
},
data: {
foo: 'other fields',
},
});
stream: ReadStream
设置发送请求正文的可读数据流,默认是 null
。一旦设置了此参数,HttpClient 将会忽略 data
和 content
。
ctx.curl(url, {
method: 'POST',
stream: fs.createReadStream('/path/to/read'),
});
writeStream: WriteStream
设置接受响应数据的可写数据流,默认是 null
。一旦设置此参数,那么返回值 result.data
将会被设置为 null
,因为数据已经全部写入到 writeStream
中了。
ctx.curl(url, {
writeStream: fs.createWriteStream('/path/to/store'),
});
consumeWriteStream: Boolean
是否等待 writeStream
完全写完才算响应全部接收完毕,默认是 true
。此参数不建议修改默认值,除非我们明确知道它的副作用是可接受的,否则很可能会导致 writeStream
数据不完整。
method: String
设置请求方法,默认是 GET
。支持 GET、POST、PUT、DELETE、PATCH
等所有 HTTP 方法。
contentType: String
设置请求数据格式,默认是 undefined
,HttpClient 会自动根据 data
和 content
参数自动设置。data
是 object 的时候默认设置的是 form
。支持 json
格式。
如需要以 JSON 格式发送 data
:
ctx.curl(url, {
method: 'POST',
data: {
foo: 'bar',
now: Date.now(),
},
contentType: 'json',
});
dataType: String
设置响应数据格式,默认不对响应数据做任何处理,直接返回原始的 buffer 格式数据。支持 text
和 json
两种格式。
注意:设置成 json
时,如果响应数据解析失败会抛 JSONResponseFormatError
异常。
const jsonResult = await ctx.curl(url, {
dataType: 'json',
});
console.log(jsonResult.data);
const htmlResult = await ctx.curl(url, {
dataType: 'text',
});
console.log(htmlResult.data);
fixJSONCtlChars: Boolean
是否自动过滤响应数据中的特殊控制字符 (U+0000 ~ U+001F),默认是 false
。通常一些 CGI 系统返回的 JSON 数据会包含这些特殊控制字符,通过此参数可以自动过滤掉它们。
ctx.curl(url, {
fixJSONCtlChars: true,
dataType: 'json',
});
headers: Object
自定义请求头。
ctx.curl(url, {
headers: {
'x-foo': 'bar',
},
});
timeout: Number|Array
请求超时时间,默认是 [ 5000, 5000 ]
,即创建连接超时是 5 秒,接收响应超时是 5 秒。
ctx.curl(url, {
// 创建连接超时 3 秒,接收响应超时 3 秒
timeout: 3000,
});
ctx.curl(url, {
// 创建连接超时 1 秒,接收响应超时 30 秒,用于响应比较大的场景
timeout: [ 1000, 30000 ],
});
agent: HttpAgent
允许通过此参数覆盖默认的 HttpAgent,如果你不想开启 KeepAlive,可以设置此参数为 false
。
ctx.curl(url, {
agent: false,
});
httpsAgent: HttpsAgent
允许通过此参数覆盖默认的 HttpsAgent,如果你不想开启 KeepAlive,可以设置此参数为 false
。
ctx.curl(url, {
httpsAgent: false,
});
auth: String
简单登录授权(Basic Authentication)参数,将以明文方式将登录信息以 Authorization
请求头发送出去。
ctx.curl(url, {
// 参数必须按照 `user:password` 格式设置
auth: 'foo:bar',
});
digestAuth: String
摘要登录授权(Digest Authentication)参数,设置此参数会自动对 401 响应尝试生成 Authorization
请求头,尝试以授权方式请求一次。
ctx.curl(url, {
// 参数必须按照 `user:password` 格式设置
digestAuth: 'foo:bar',
});
followRedirect: Boolean
是否自动跟进 3xx 的跳转响应,默认是 false
。
ctx.curl(url, {
followRedirect: true,
});
maxRedirects: Number
设置最大自动跳转次数,避免循环跳转无法终止,默认是 10 次。此参数不宜设置过大,它只在 followRedirect=true
情况下才会生效。
ctx.curl(url, {
followRedirect: true,
// 最大只允许自动跳转 5 次。
maxRedirects: 5,
});
formatRedirectUrl: Function(from, to)
允许我们通过 formatRedirectUrl
自定义实现 302、301 等跳转 url 拼接, 默认是 url.resolve(from, to)
。
ctx.curl(url, {
formatRedirectUrl: (from, to) => {
// 例如可在这里修正跳转不正确的 url
if (to === '//foo/') {
to = '/foo';
}
return url.resolve(from, to);
},
});
beforeRequest: Function(options)
HttpClient 在请求正式发送之前,会尝试调用 beforeRequest
钩子,允许我们在这里对请求参数做最后一次修改。
ctx.curl(url, {
beforeRequest: options => {
// 例如我们可以设置全局请求 id,方便日志跟踪
options.headers['x-request-id'] = uuid.v1();
},
});
streaming: Boolean
是否直接返回响应流,默认为 false
。开启 streaming 之后,HttpClient 会在拿到响应对象 res 之后马上返回,此时 result.headers
和 result.status
已经可以读取到,只是没有读取 data 数据而已。
const result = await ctx.curl(url, {
streaming: true,
});
console.log(result.status, result.data);
// result.res 是一个 ReadStream 对象
ctx.body = result.res;
注意:如果 res 不是直接传递给 body,那么我们必须消费这个 stream,并且要做好 error 事件处理。
gzip: Boolean
是否支持 gzip 响应格式,默认为 false
。开启 gzip 之后,HttpClient 将自动设置 Accept-Encoding: gzip
请求头,并且会自动解压带 Content-Encoding: gzip
响应头的数据。
ctx.curl(url, {
gzip: true,
});
timing: Boolean
是否开启请求各阶段的时间测量,默认为 false
。开启 timing 之后,可以通过 result.res.timing
拿到这次 HTTP 请求各阶段的时间测量值(单位是毫秒),通过这些测量值,我们可以非常方便地定位到这次请求最慢的环境发生在那个阶段,效果如同 Chrome network timing 的作用。
timing 各阶段测量值解析:
- queuing:分配 socket 耗时
- dnslookup:DNS 查询耗时
- connected:socket 三次握手连接成功耗时
- requestSent:请求数据完整发送完毕耗时
- waiting:收到第一个字节的响应数据耗时
- contentDownload:全部响应数据接收完毕耗时
const result = await ctx.curl(url, {
timing: true,
});
console.log(result.res.timing);
// {
// "queuing":29,
// "dnslookup":37,
// "connected":370,
// "requestSent":1001,
// "waiting":1833,
// "contentDownload":3416
// }
ca,rejectUnauthorized,pfx,key,cert,passphrase,ciphers,secureProtocol
这几个都是透传给 [HTTPS] 模块的参数,具体请查看 https.request(options, callback)
。