为解决Web应用调用后端基于HTTP通信协议的服务,Egg框架基于Node.js的URL处理模块urllib
内置实现了一个HttpClient(HTTP服务的客户端),以实现Web应用便捷地完成HTTP请求的调用。
urllib
urllib提供了一系列用于操作HTTP URL的功能,比如数字身份认证、重定向、Cookie、网络超时等。
$ npm i -S urllib
HttpClient
Egg框架基于urllib
内置实现了一个HTTP客户端HttpClient
,框架在应用初始化阶段会自动将HttpClient初始化到app.httpClient
对象上,同时会为app
对象增加一个app.curl(url, opts)
的快捷方法用来访问远程的HTTP服务端,实际上app.curl(url, opts)
方法等价于app.httpClient.request(url, opts)
方法。
app.httpClient
app.httpClient.request(url, opts)
app.curl(url, opts)
Egg框架在Context中也提供了ctx.curl(url, opts)
方法和ctx.httpClient
对象,并保持和app
对象下使用体验一致。
ctx.httpClient
ctx.curl(url, opts)
HTTP请求
请求选项
全局配置
$ vim config/config.default.js
config.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,
},
}
选项 | 默认 | 描述 |
---|---|---|
enableDNSCache | false | 是否开启本地DNS缓存 |
dnsCacheLookupInterval | 10000 | 对同一个域名进行DNS查询的最小间隔时长 |
dnsCacheMaxLength | 1000 | DNS同时缓存的最大域名数量 |
request | object | 请求参数 |
httpAgent | object | HTTP请求代理参数 |
httpsAgent | object | HTTPS请求代理参数 |
局部选项
选项 | 类型 | 描述 |
---|---|---|
data | Object | 需发送的请求数据 |
dataAsQueryString | Boolean | 是否使用查询字符串处理URL的参数 |
content | String|Buffer | 发送请求者正文,若设置则忽略data参数。 |
files | Mixed | 文件上传支持格式,可选String/ReadStream/Buffer/Array/Object类型。 |
stream | ReadStream | 发送请求正文的可读数据流,默认为null。若设置则会忽略data和content参数。 |
writeStream | WriteStream | 接收响应数据的可写数据流,默认为null。若设置则返回值result.data将会被设置为null。 |
consumeWriteStream | Boolean | 是否等待WriteStream写入流完全写完后才算响应全部接收完毕,默认为true。 |
method | String | 请求方法,默认为GET。 |
contentType | String | 请求数据格式,默认为undefined。 |
dataType | String | 响应数据格式,默认直接返回原始的Buffer格式数据,支持text和json格式。 |
fixJSONCtlChars | Boolean | 是否自动过滤响应数据中的特殊字符,默认false。 |
headers | Object | 自定义请求头 |
timeout | Number/Array | 请求超时时长,默认[5000, 5000],即创建连接超时为5秒,接收响应超时为5秒。 |
agent | HttpAgent | 设置HTTP代理参数 |
httpsAgent | HttpsAgent | 设置HTTPS代理参数 |
auth | String | 登录授权参数,以明文将登录信息以Authorization请求头字段发送出。 |
digestAuth | String | 摘要登录授权参数,自动对401响应尝试生成Authorization请求头,尝试以授权方式请求一次。 |
followRedirect | Boolean | 是否自动跟进3xx的跳转响应,默认为false。 |
maxRedirects | Number | 最大自动跳转次数,避免循环跳转无法终止,默认10次。 |
formatRedirectUrl | Function | 自定义实现301/302等跳转URL拼接。 |
beforeRequest | Function | 请求正式发送前调用的钩子 |
streaming | Boolean | 是否直接返回响应流,默认false。 |
gzip | Boolean | 是否支持GZIP响应格式,默认false。 |
timing | Boolean | 是否开启请求各阶段的时间测量,默认false。 |
GET请求
例如:以GET方式发送HTTP请求,GET请求无需设置opts.method
参数,HttpClient默认的method
为GET。
const result = await ctx.curl("http://hostname.com/api/get");
发送HTTP请求返回的响应结果result
中包含3个属性,分别是status
、headers
、data
属性 | 描述 |
---|---|
status | 响应状态码 |
headers | 响应头信息 |
data | 响应体信息,默认为Buffer类型。 |
默认HttpClient不会对响应体做任何处理,因此会直接返回Buffer
类型的数据。若提前在curl
方法中指定响应数据类型opts.dataType
,HttpClient将会根据dataType
对返回值中的data
做对应处理。
例如:
{
data: <Buffer 7b 22 65 72 72 63 6f 64 65 22 3a 34 30 30 31 38 2c 22 65 72 72 6d 73 67 22 3a 22 62 61 64 20 63 6f 64 65 22 2c 22 65 72 72 6f 72 22 3a 33 2c 22 6d 65 ... 19 more bytes>,
status: 200,
headers: {
server: 'Tengine',
'content-type': 'application/json; charset=utf-8',
'content-length': '69',
connection: 'keep-alive',
date: 'Sat, 23 May 2020 12:17:31 GMT',
'x-tt-logid': '20200523201731010131036232361281BE',
'server-timing': 'inner; dur=0, cdn-cache;desc=MISS,edge;dur=0,origin;dur=89',
'x-tt-trace-host': '01b996da57d6c895f8a74a08ea30e03c41fa589acc716cdb70b13b08d85c02f7af017e5fe10e660a2260d6706cd5436b878771057e6b8d105e7bff138312d8223b19339c99416ddebce6e88cef6d2c84b2',
'x-tt-trace-tag': 'id=3;cdn-cache=miss',
'x-tt-timestamp': '1590236251.323',
via: 'cache11.cn683[89,0]',
'timing-allow-origin': '*',
eagleid: '71db884b15902362512522488e'
},
res: {
status: 200,
statusCode: 200,
statusMessage: 'OK',
headers: {
server: 'Tengine',
'content-type': 'application/json; charset=utf-8',
'content-length': '69',
connection: 'keep-alive',
date: 'Sat, 23 May 2020 12:17:31 GMT',
'x-tt-logid': '20200523201731010131036232361281BE',
'server-timing': 'inner; dur=0, cdn-cache;desc=MISS,edge;dur=0,origin;dur=89',
'x-tt-trace-host': '01b996da57d6c895f8a74a08ea30e03c41fa589acc716cdb70b13b08d85c02f7af017e5fe10e660a2260d6706cd5436b878771057e6b8d105e7bff138312d8223b19339c99416ddebce6e88cef6d2c84b2',
'x-tt-trace-tag': 'id=3;cdn-cache=miss',
'x-tt-timestamp': '1590236251.323',
via: 'cache11.cn683[89,0]',
'timing-allow-origin': '*',
eagleid: '71db884b15902362512522488e'
},
size: 69,
aborted: false,
rt: 166,
keepAliveSocket: false,
data: <Buffer 7b 22 65 72 72 63 6f 64 65 22 3a 34 30 30 31 38 2c 22 65 72 72 6d 73 67 22 3a 22 62 61 64 20 63 6f 64 65 22 2c 22 65 72 72 6f 72 22 3a 33 2c 22 6d 65 ... 19 more bytes>,
requestUrls: [
'https://developer.toutiao.com/api/apps/jscode2session?appid=tt5e4728fac17db2af&secret=ce052ea527836f25c11d94f1b7330ecf7f9b1dec&code=1b257d9257d2a413&anonymousCode=2c13ffb4bdddf41d'
],
timing: null,
remoteAddress: '113.219.136.30',
remotePort: 443,
socketHandledRequests: 1,
socketHandledResponses: 1
}
}