为解决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: ,
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: ,
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
}
}