「 简化的HTTP请求 」
翻译的原文 | 与日期 | 最新更新 | 更多 |
---|---|---|---|
commit | ⏰ 2018-11-08 | 中文翻译 |
欢迎 👏 勘误/校对/更新贡献 😊 具体贡献请看
If help, buy me coffee —— 营养跟不上了,给我来瓶营养快线吧! 💰
简化的HTTP请求
Got是一个人性化,且功能强大的HTTP请求库.
它的创建是因为常用的request
包过臃肿:
Got是Node.js的请求库。对于浏览器的请求,我们建议ky.
- Promise 和 Streams API
- 请求取消
- 符合RFC的缓存
- 遵循重定向
- 失败时重试
- 进展事件
- 处理 gzip/deflate
- 超时处理
- 元数据错误
- JSON模式
- WHATWG URL支持
- 钩子
- 具有自定义默认值的实例
- 可组合
- Electron支持
- 由
2000包和500K repos使用 - 积极维护
$ npm install got
const got = require('got');
(async () => {
try {
const response = await got('sindresorhus.com');
console.log(response.body);
//=> '<!doctype html> ...'
} catch (error) {
console.log(error.response.body);
//=> 'Internal server error ...'
}
})();
const fs = require('fs');
const got = require('got');
got.stream('sindresorhus.com').pipe(fs.createWriteStream('index.html'));
// For POST, PUT, and PATCH methods `got.stream` returns a `stream.Writable`
fs.createReadStream('index.html').pipe(got.stream.post('sindresorhus.com'));
GET
方法为默认情况下的请求,但可以使用不同的方法,或在options
.
-
返回一个
response
对象的Promise或者 -
一个stream,如果
options.stream
设置为true.
参数 |
---|
url |
options |
类型: | string Object |
---|
-
请求的URL,若是字符串, 一个
https.request
选项对象或者一个WHATWGURL
. -
options
的属性将覆盖这个url
属性. -
如果未指定协议,则默认为
https
.
类型: | Object |
---|
参数 |> Streams / baseUrl / headers / stream / body / cookieJar / encoding / form / json / query / timeout / retry / followRedirect / decompress / cache / request / useElectronNet / throwHttpErrors / agent / hooks
任何一个https.request
的选项.
类型: | string Object |
---|
- 指定时,
baseUrl
将作为url
的前缀.
如果您指定绝对URL,它将跳过baseUrl
。
使用got.extend()
时非常有用,用于创建利基特定的Got实例.
可以是字符串或WHATWG URL
.
削减baseUrl
的结尾,拼接开始的url
参数,且是可选的:
await got('hello', {baseUrl: 'https://example.com/v1'});
//=> 'https://example.com/v1/hello'
await got('/hello', {baseUrl: 'https://example.com/v1/'});
//=> 'https://example.com/v1/hello'
await got('/hello', {baseUrl: 'https://example.com/v1'});
//=> 'https://example.com/v1/hello'
类型: | Object |
---|---|
默认: | {} |
请求标头.
- 现有标题将被覆盖。标题设置为
null
将被省略.
类型: | boolean |
---|---|
默认: | false |
返回一个Stream
,而不是Promise
。这相当于调用got.stream(url, [options])
.
类型: | string Buffer stream.Readable form-data 实例 |
---|
如果您提供此选项,got.stream()
将是只读的.
POST
请求发送的主体.
如果存在options
和options.method
未设定,options.method
将被设置为POST
.
该content-length
标题将自动设置,如果body
是一个string
/Buffer
/fs.createReadStream
实例/form-data
实例,和content-length
和transfer-encoding
就不再是options.headers
的手动设置.
类型: | tough.CookieJar 实例 |
---|
Cookie支持.您不必关心解析或如何存储它们.例子.
注意: options.headers.cookie
将被覆盖.
类型: | string null |
---|---|
默认: | 'utf8' |
编码-Encoding用于响应数据的setEncoding
。如果null
, 响应body会返回一个Buffer
(二进制数据).
类型: | boolean |
---|---|
默认: | false |
如果您提供此选项,got.stream()
将是只读的.
如果设置为true
和Content-Type
标头未设置,它将被设置为application/x-www-form-urlencoded
.
body
必须是一个普通的对象。它将使用(new URLSearchParams(object)).toString()
转换为查询字符串.
类型: | boolean |
---|---|
默认: | false |
如果你使用got.stream()
,此选项将被忽略.
如果设置为true
和Content-Type
标头未设置,它将被设置为application/json
.
用JSON.parse
解析响应主体,并设置accept
标题为application/json
。如果与form
选项一起使用,body
将字符串化为查询字符串,并将响应解析为JSON.
body
必须是普通对象或数组,和能对其进行字符串化.
类型: | string Object<string, string|number> URLSearchParams |
---|
添加到请求URL的查询字符串。这将覆盖url
的查询字符串.
如果你需要传入一个数组,你可以使用一个URLSearchParams
,例如:
const got = require('got');
const query = new URLSearchParams([['key', 'a'], ['key', 'b']]);
got('https://example.com', {query});
console.log(query.toString());
//=> 'key=a&key=b'
如果你需要一个不同的数组格式,你可以使用query-string
包:
const got = require('got');
const queryString = require('query-string');
const query = queryString.stringify({key: ['a', 'b']}, {arrayFormat: 'bracket'});
got('https://example.com', {query});
console.log(query);
//=> 'key[]=a&key[]=b'
类型: | number Object |
---|
在中止请求发生got.TimeoutError
错误(a.k.a.request
属性)之前,等待服务器结束响应的毫秒数。默认情况下,没有超时.
这也会接受object
,使用以下字段来约束请求生命周期的每个阶段的持续时间:
lookup
在分配套接字时启动,在解析主机名时结束。使用Unix域名套接字时不适用.connect
从lookup
完成开始(或如果lookup不适用于请求,分配套接字的时候),并在连接套接字时结束.secureConnect
从connect
完成时开始,和在握手过程完成后结束(仅限HTTPS).socket
在连接套接字时开始。看request.setTimeout.response
当请求已写入套接字时开始,并在收到响应头时结束.send
套接字连接时开始,并以请求结束写入套接字.request
在请求初始化后开始,在响应的结束事件触发时结束.
类型: | number Object |
---|---|
默认: | 重试:2 次 |
方法: | GET PUT HEAD DELETE OPTIONS TRACE |
statusCodes: | 408 413 429 500 502 503 504 |
maxRetryAfter: | undefined |
- Object对象 : 代表
retries
, 重试methods
, 允许的方法statusCodes
和maxRetryAfter
最大Retry-After
时间。
如果maxRetryAfter
被设置为undefined
,它会用options.timeout
.
如果Retry-After
标头大于maxRetryAfter
,它将取消请求.
重试之间的延迟计算是1000 * Math.pow(2, retry) + Math.random() * 100
函数,这里的retry
是尝试数(从1开始).
retries
属性可以
- 是
number
或者 - 一个带
retry
和error
参数的function
.该函数必须以毫秒为单位的延迟返回(返回0
值,会取消重试).
**注意:**它仅在指定的方法,状态代码和这些网络错误上重试:
ETIMEDOUT
: 达到超时其中一个限制.ECONNRESET
:连接被网络点强行关闭.EADDRINUSE
:无法绑定到任何自由端口.ECONNREFUSED
:连接被服务器拒绝.EPIPE
:正在写入的流的远程端已关闭.ENOTFOUND
:无法将主机名解析为IP地址.ENETUNREACH
: 没有网络连接.EAI_AGAIN
:DNS查找超时.
类型: | boolean |
---|---|
默认: | true |
定义是否应自动遵循重定向响应.
请注意,如果服务器发送回来一个303
,以响应任何请求类型(POST
,DELETE
等等),Got会自动通过GET
请求,位置头中指向的资源。这符合规范.
类型: | boolean |
---|---|
默认: | true |
自动解压响应。这将设置accept-encoding
标题为gzip, deflate
,除非你自己设定.
如果禁用此选项,则会将压缩响应作为一个Buffer
返回。如果您想自己处理解压或stream式处理原始压缩数据, 这可能很有用.
类型: | Object |
---|---|
默认: | false |
缓存适配器实例用于存储缓存的数据.
类型: | Function |
---|---|
默认: | http.request https.request (取决于协议) |
自定义请求函数.这样做的主要目的是为了通过包装HTTP2,以此支持这个协议.
类型: | boolean |
---|---|
默认: | false |
在Electron中使用时,Got会使用electron.net
替代Node.jshttp
模块。根据Electron的文档,它应该是完全兼容的,但其实不是完全兼容.看到#443和#461.
类型: | boolean |
---|---|
默认: | true |
确定是否抛出got.HTTPError
错误响应(非2xx状态代码).
如果禁用此选项,在请求遇到错误状态代码,会使用response
resolve,而不是抛出got.HTTPError
。如果您正在检查资源可用性,并且期望出现错误响应,这可能很有用.
对应http.request
的agent
选项,但有一个额外的功能:
如果您需要针对不同协议的不同代理,则可以将代理映射传递给agent
选项。这是必要的,因为对一个协议的请求可能会重定向到另一个协议。在这种情况下,Got将为您切换到正确的协议代理.
const got = require('got');
const HttpAgent = require('agentkeepalive');
const {HttpsAgent} = HttpAgent;
got('sindresorhus.com', {
agent: {
http: new HttpAgent(),
https: new HttpsAgent()
}
});
类型: | Object<string, Function[]> |
---|
钩子允许在请求生命周期中进行修改。钩子函数可以是异步的,和也能串行运行的.
类型: | Function[] |
---|---|
默认: | [] |
调用标准的 请求选项。在发送请求之前,不会对请求进行进一步更改。这对结合got.extend()
和got.create()
使用,特别有用,当您想要创建一个API客户端时,例如,使用HMAC签名.
见AWS部分举的例子.
注意:如果你修改了body
,你也需要修改content-length
标题,因为它已经被计算和分配.
类型: | Function[] |
---|---|
默认: | [] |
调用标准的 请求选项。Got的请求不会进一步更改.当您想要避免死站点时,这尤其有用.例:
const got = require('got');
got('example.com', {
hooks: {
beforeRedirect: [
options => {
if (options.hostname === 'deadSite') {
options.hostname = 'fallbackSite';
}
}
]
}
});
类型: | Function[] |
---|---|
默认: | [] |
调用标准的 请求选项,错误和重试计数。Got的请求不会进一步更改。在下次尝试之前,需要一些额外的工作时,这尤其有用.例:
const got = require('got');
got('example.com', {
hooks: {
beforeRetry: [
(options, error, retryCount) => {
if (error.statusCode === 413) { // Payload too large
options.body = getNewBody();
}
}
]
}
});
类型: | Function[] |
---|---|
默认: | [] |
调用响应对象和重试函数.
每个函数都应该返回响应。当您想要刷新访问令牌时,这尤其有用.例:
const got = require('got');
const instance = got.extend({
hooks: {
afterResponse: [
(response, retryWithMergedOptions) => {
if (response.statusCode === 401) { // Unauthorized
const updatedOptions = {
headers: {
token: getNewToken() // Refresh the access token
}
};
// Save for further requests
instance.defaults.options = got.mergeOptions(instance.defaults.options, updatedOptions);
// Make a new retry
return retryWithMergedOptions(updatedOptions);
}
// No changes otherwise
return response;
}
]
},
mutableDefaults: true
});
响应对象通常是一个Node.js HTTP响应流但是,如果从缓存返回,那它会是一个类似响应的对象和行为方式相同.
参数 |> body / url / requestUrl / timings / fromCache / redirectUrls / retryCount /
类型: | string Object (取决于options.json ) |
---|
请求的结果.
类型: | string |
---|
重定向后的请求URL或最终URL.
类型: | string |
---|
原始请求网址.
类型: | Object |
---|
该对象包含以下属性:
start
- 请求开始的时间.socket
- 将套接字分配给请求的时间.lookup
- DNS查找完成的时间.connect
- 套接字成功连接的时间.upload
- 请求完成上传的时间.response
- 请求解雇的时间response
事件.end
- 响应解雇的时间end
事件.error
- 请求解雇的时间error
事件.phases
-wait
-timings.socket - timings.start
-dns
-timings.lookup - timings.socket
-tcp
-timings.connect - timings.lookup
-request
-timings.upload - timings.connect
-firstByte
-timings.response - timings.upload
-download
-timings.end - timings.response
-total
-timings.end - timings.start
要么timings.error - timings.start
注意:时间是number
表示自UNIX纪元以来经过的毫秒数.
类型: | boolean |
---|
是否从缓存中检索响应.
类型: | Array |
---|
重定向网址.
类型: | number |
---|
重试请求的次数.
注意:进度事件,重定向事件和请求/响应事件,也可以与promise一起使用.
设options.stream
为true
.
返回带有其他活动的一个双工流:
request
事件获取请求的request对象.
小费: 您可以使用request
事件,中止请求:
got.stream('github.com')
.on('request', request => setTimeout(() => request.abort(), 50));
response
事件获取最终请求的response对象.
redirect
事件获取重定向的response对象。第二个参数是下一个重定向位置请求的选项.
上传(发送请求)和下载(接收响应)的进度事件。该progress
参数是一个像这样的对象:
{
percent: 0.1,
transferred: 1024,
total: 10240
}
如果无法检索大小(流式传输时,可能发生),total
会是null
.
(async () => {
const response = await got('sindresorhus.com')
.on('downloadProgress', progress => {
// Report download progress
})
.on('uploadProgress', progress => {
// Report upload progress
});
console.log(response);
})();
error
在协议错误的情况下,发出的事件(如ENOTFOUND
等)或状态错误(4xx或5xx)。第二个参数是状态错误时服务器响应的主体。第三个参数是响应对象.
将options.method
方法名称设置好,和做成请求.
配置一个带默认options
的新got
实例。该options
与父实例的defaults.options
合并,合并是通过使用got.mergeOptions
。您可以使用在实例上的.defaults
属性,访问已resolve的选项,.
const client = got.extend({
baseUrl: 'https://example.com',
headers: {
'x-unicorn': 'rainbow'
}
});
client.get('/demo');
/* HTTP Request =>
* GET /demo HTTP/1.1
* Host: example.com
* x-unicorn: rainbow
*/
(async () => {
const client = got.extend({
baseUrl: 'httpbin.org',
headers: {
'x-foo': 'bar'
}
});
const {headers} = (await client.get('/headers', {json: true})).body;
//=> headers['x-foo'] === 'bar'
const jsonClient = client.extend({
json: true,
headers: {
'x-baz': 'qux'
}
});
const {headers: headers2} = (await jsonClient.get('/headers')).body;
//=> headers2['x-foo'] === 'bar'
//=> headers2['x-baz'] === 'qux'
})();
需要更多控制Got的行为? 看看got.create()
.
扩展父选项。避免使用对象传播...,因为它不能递归工作:
const a = {headers: {cat: 'meow', wolf: ['bark', 'wrrr']}};
const b = {headers: {cow: 'moo', wolf: ['auuu']}};
{...a, ...b} // => {headers: {cow: 'moo', wolf: ['auuu']}}
got.mergeOptions(a, b) // => {headers: {cat: 'meow', cow: 'moo', wolf: ['auuu']}}
Options会深度合并到新对象。每个字段名的确定步骤如下:
a
为旧/父的,b
为新的。
- 如果新属性设置为
undefined
,保留了旧的. - 如果父属性是
URL
的实例,而新的值是string
或者URL
, 那就创建一个新的URL实例:new URL(new, parent)
. - 如果新属性是普通
Object
:- 如果父属性也是普通的
Object
, 那两个值递归合并为一个新的Object
. - 否则,只会深拷贝新值.
- 如果父属性也是普通的
- 如果新属性是
Array
,它用新属性的深拷贝覆盖旧的. - 否则,新值分配给对应的字段就好了。
类型: | Object |
---|
默认的Got选项.
每个错误包含(如果可用)的属性字段 |
---|
body , |
statusCode , |
statusMessage , |
host , |
hostname |
method , |
path , |
protocol |
url |
使调试更容易.
在Promise模式下,
response
也附加到错误.
例如,当缓存方法失败时,如果数据库出现故障或存在文件系统错误.
请求失败时,包含一个具有错误类代码的code
属性,如ECONNREFUSED
.
从响应流中读取失败.
当json
选项已启用,服务器响应代码为2xx,和JSON.parse
失败.
当服务器响应代码不是2xx时,包括statusCode
,statusMessage
,和redirectUrls
属性.
当服务器重定向您十次以上时,包括一个redirectUrls
属性,这是在放弃之前,重定向的一个URL数组.
不支持的协议时.
请求被.cancel()
中止时.
当请求因一个超时而中止时
Got返回的Promise有一个.cancel()
。当调用时,会中止请求.
(async () => {
const request = got(url, options);
// …
// In another part of the code
if (something) {
request.cancel();
}
// …
try {
await request;
} catch (error) {
if (request.isCanceled) { // Or `error instanceof got.CancelError`
// Handle cancelation
}
// Handle other errors
}
})();
Got实现了RFC 7234兼容的HTTP缓存,可以在内存中开箱即用,并且可以使用各种存储适配器轻松插入。直接从缓存提供新缓存项,并使用If-None-Match
/If-Modified-Since
头重新验证过时的缓存项。您可以在cacheable-request
文件中,阅读有关基本缓存行为的更多信息.
您可以使用JavaScriptMap
类型,作为内存缓存:
const got = require('got');
const map = new Map();
(async () => {
let response = await got('sindresorhus.com', {cache: map});
console.log(response.fromCache);
//=> false
response = await got('sindresorhus.com', {cache: map});
console.log(response.fromCache);
//=> true
})();
Got 内部使用Keyv支持各种存储适配器。对于更多伸缩性,你可以使用官方Keyv存储适配器:
$ npm install @keyv/redis
const got = require('got');
const KeyvRedis = require('@keyv/redis');
const redis = new KeyvRedis('redis://user:pass@localhost:6379');
got('sindresorhus.com', {cache: redis});
Got提供了Map API内容的支持,因此可以轻松编写自己的存储适配器或使用第三方解决方案.
例如,以下所有,都是有效的存储适配器:
const storageAdapter = new Map();
// Or
const storageAdapter = require('./my-storage-adapter');
// Or
const QuickLRU = require('quick-lru');
const storageAdapter = new QuickLRU({maxSize: 1000});
got('sindresorhus.com', {cache: storageAdapter});
查看keyv文档有关如何使用存储适配器的更多信息.
你可以使用tunnel
包,加上agent
与代理一起工作:
const got = require('got');
const tunnel = require('tunnel');
got('sindresorhus.com', {
agent: tunnel.httpOverHttp({
proxy: {
host: 'localhost'
}
})
});
查看下global-tunnel
,如果您想为应用程序中的所有HTTP/HTTPS流量配置代理支持.
你可以使用tough-cookie
包:
const got = require('got');
const {CookieJar} = require('tough-cookie');
const cookieJar = new CookieJar();
cookieJar.setCookie('foo=bar', 'https://www.google.com');
got('google.com', {cookieJar});
你可以使用form-data
,用表单数据创建POST请求:
const fs = require('fs');
const got = require('got');
const FormData = require('form-data');
const form = new FormData();
form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
got.post('google.com', {
body: form
});
你可以使用oauth-1.0a
包,创建签名的OAuth请求:
const got = require('got');
const crypto = require('crypto');
const OAuth = require('oauth-1.0a');
const oauth = OAuth({
consumer: {
key: process.env.CONSUMER_KEY,
secret: process.env.CONSUMER_SECRET
},
signature_method: 'HMAC-SHA1',
hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
});
const token = {
key: process.env.ACCESS_TOKEN,
secret: process.env.ACCESS_TOKEN_SECRET
};
const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
got(url, {
headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
json: true
});
请求也可以通过UNIX域名套接字发送出去。 使用以下URL方案:PROTOCOL://unix:SOCKET:PATH
.
PROTOCOL
-http
或https
(可选)SOCKET
- 一个UNIX域名套接字的绝对路径,例如:/var/run/docker.sock
PATH
- 请求路径,例如:/v2/keys
got('http://unix:/var/run/docker.sock:/containers/json');
// Or without protocol (HTTP by default)
got('unix:/var/run/docker.sock:/containers/json');
对AWS服务的请求,需要签署他们的标头(headers)。这可以通过使用aws4
包。这是一个用已签名的请求,查询"API网关"的示例..
const AWS = require('aws-sdk');
const aws4 = require('aws4');
const got = require('got');
const chain = new AWS.CredentialProviderChain();
// Create a Got instance to use relative paths and signed requests
const awsClient = got.extend({
baseUrl: 'https://<api-id>.execute-api.<api-region>.amazonaws.com/<stage>/',
hooks: {
beforeRequest: [
async options => {
const credentials = await chain.resolvePromise();
aws4.sign(options, credentials);
}
]
}
});
const response = await awsClient('endpoint/path', {
// Request-specific options
});
您可以通过使用nock
包模拟端点:
const got = require('got');
const nock = require('nock');
nock('https://sindresorhus.com')
.get('/')
.reply(200, 'Hello world!');
(async () => {
const response = await got('sindresorhus.com');
console.log(response.body);
//=> 'Hello world!'
})();
如果需要真正的集成测试,可以使用create-test-server
:
const got = require('got');
const createTestServer = require('create-test-server');
(async () => {
const server = await createTestServer();
server.get('/', 'Hello world!');
const response = await got(server.url);
console.log(response.body);
//=> 'Hello world!'
await server.close();
})();
设置'user-agent'
头是个好主意,因此提供者可以更容易地看到它们的资源是如何使用的。默认情况下,它是指向这个存储库的URL。当然您也可以设置为null
禁用.
const got = require('got');
const pkg = require('./package.json');
got('sindresorhus.com', {
headers: {
'user-agent': `my-package/${pkg.version} (https://github.com/username/my-package)`
}
});
got('sindresorhus.com', {
headers: {
'user-agent': null
}
});
记住,如果你发送一个if-modified-since
标题。和接收到了304 Not Modified
响应,主体-body就会是空的。缓存和检索主体内容是您的职责.
使用got.extend()
让它更好地与REST API一起工作。特别是你使用了baseUrl
选项.
**注:**不要对got.create()
感到疑惑,它没有默认值.
const got = require('got');
const pkg = require('./package.json');
const custom = got.extend({
baseUrl: 'example.com',
json: true,
headers: {
'user-agent': `my-package/${pkg.version} (https://github.com/username/my-package)`
}
});
// Use `custom` exactly how you use `got`
(async () => {
const list = await custom('/v1/users/list');
})();
需要将一些实例合并为单个实例吗? 查看got.mergeInstances()
.
GET提供了http2-wrapper
包,使用HTTP2的实验支持:
const got = require('got');
const {request} = require('http2-wrapper');
const h2got = got.extend({request});
(async () => {
const {body} = await h2got('https://nghttp2.org/httpbin/headers');
console.log(body);
})();
*它几乎与浏览器fetch
API兼容.
❔ 实验支持.
- gh-got - Got 便利包,与GitHub API交互
- gl-got - Got 便利包,与Gitlab API交互
- travis-got - Got 便利包,与Travis API交互
- graphql-got - Got 便利包,与GraphQL API交互
- GotQL - Got 便利包,与GraphQL API交互, 但是使用JSON解析替代字符串
Sindre Sorhus | Vsevolod Strukchinsky | Alexander Tesfamichael | Luke Childs | Szymon Marczak | Brandon Smith |
MIT