Skip to content

中文翻译: <got> 简化的HTTP请求 ❤️ 校对 ✅

Notifications You must be signed in to change notification settings

chinanf-boy/got-zh

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sindresorhus/got explain translate-svg

「 简化的HTTP请求 」

中文 | english


校对 ✅

翻译的原文 与日期 最新更新 更多
commit ⏰ 2018-11-08 last 中文翻译

贡献

欢迎 👏 勘误/校对/更新贡献 😊 具体贡献请看

生活

If help, buy me coffee —— 营养跟不上了,给我来瓶营养快线吧! 💰




Got


非常感谢 赞助 me!



简化的HTTP请求

Build Status: Linux Coverage Status Downloads Install size

Got是一个人性化,且功能强大的HTTP请求库.

它的创建是因为常用的request包过臃肿: Install size

Got是Node.js的请求库。对于浏览器的请求,我们建议ky.

Highlights

了解Got,如何与其他HTTP库进行比较

Install

$ npm install got

Usage

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 ...'
	}
})();
Streams
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'));

API

GET方法为默认情况下的请求,但可以使用不同的方法,或在options.

got(url, [options])

参数
url
options
url
类型: string Object
options
类型: Object

参数 |> Streams / baseUrl / headers / stream / body / cookieJar / encoding / form / json / query / timeout / retry / followRedirect / decompress / cache / request / useElectronNet / throwHttpErrors / agent / hooks

任何一个https.request的选项.

baseUrl
类型: 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'
headers
类型: Object
默认: {}

请求标头.

  • 现有标题将被覆盖。标题设置为null将被省略.
stream
类型: boolean
默认: false

返回一个Stream,而不是Promise。这相当于调用got.stream(url, [options]).

body
类型: string Buffer stream.Readable form-data实例

如果您提供此选项,got.stream()将是只读的.

POST请求发送的主体.

如果存在optionsoptions.method未设定,options.method将被设置为POST.

content-length标题将自动设置,如果body是一个string/Buffer/fs.createReadStream实例/form-data实例,和content-lengthtransfer-encoding就不再是options.headers的手动设置.

cookieJar
类型: tough.CookieJar实例

Cookie支持.您不必关心解析或如何存储它们.例子.

注意: options.headers.cookie将被覆盖.

encoding
类型: string null
默认: 'utf8'

编码-Encoding用于响应数据的setEncoding。如果null, 响应body会返回一个Buffer(二进制数据).

form
类型: boolean
默认: false

如果您提供此选项,got.stream()将是只读的.

如果设置为trueContent-Type标头未设置,它将被设置为application/x-www-form-urlencoded.

body必须是一个普通的对象。它将使用(new URLSearchParams(object)).toString()转换为查询字符串.

json
类型: boolean
默认: false

如果你使用got.stream(),此选项将被忽略.

如果设置为trueContent-Type标头未设置,它将被设置为application/json.

JSON.parse解析响应主体,并设置accept标题为application/json。如果与form选项一起使用,body将字符串化为查询字符串,并将响应解析为JSON.

body必须是普通对象或数组,和能对其进行字符串化.

query
类型: 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'
timeout
类型: number Object

在中止请求发生got.TimeoutError错误(a.k.a.request属性)之前,等待服务器结束响应的毫秒数。默认情况下,没有超时.

这也会接受object,使用以下字段来约束请求生命周期的每个阶段的持续时间:

  • lookup在分配套接字时启动,在解析主机名时结束。使用Unix域名套接字时不适用.
  • connectlookup完成开始(或如果lookup不适用于请求,分配套接字的时候),并在连接套接字时结束.
  • secureConnectconnect完成时开始,和在握手过程完成后结束(仅限HTTPS).
  • socket在连接套接字时开始。看request.setTimeout.
  • response当请求已写入套接字时开始,并在收到响应头时结束.
  • send套接字连接时开始,并以请求结束写入套接字.
  • request在请求初始化后开始,在响应的结束事件触发时结束.
retry
类型: 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或者
  • 一个带retryerror参数的function.该函数必须以毫秒为单位的延迟返回(返回0值,会取消重试).

**注意:**它仅在指定的方法,状态代码和这些网络错误上重试:

  • ETIMEDOUT: 达到超时其中一个限制.
  • ECONNRESET:连接被网络点强行关闭.
  • EADDRINUSE:无法绑定到任何自由端口.
  • ECONNREFUSED:连接被服务器拒绝.
  • EPIPE:正在写入的流的远程端已关闭.
  • ENOTFOUND:无法将主机名解析为IP地址.
  • ENETUNREACH: 没有网络连接.
  • EAI_AGAIN:DNS查找超时.
followRedirect
类型: boolean
默认: true

定义是否应自动遵循重定向响应.

请注意,如果服务器发送回来一个303,以响应任何请求类型(POST,DELETE等等),Got会自动通过GET请求,位置头中指向的资源。这符合规范.

decompress
类型: boolean
默认: true

自动解压响应。这将设置accept-encoding标题为gzip, deflate,除非你自己设定.

如果禁用此选项,则会将压缩响应作为一个Buffer返回。如果您想自己处理解压或stream式处理原始压缩数据, 这可能很有用.

cache
类型: Object
默认: false

缓存适配器实例用于存储缓存的数据.

request
类型: Function
默认: http.request https.request (取决于协议)

自定义请求函数.这样做的主要目的是为了通过包装HTTP2,以此支持这个协议.

useElectronNet
类型: boolean
默认: false

在Electron中使用时,Got会使用electron.net替代Node.jshttp模块。根据Electron的文档,它应该是完全兼容的,但其实不是完全兼容.看到#443#461.

throwHttpErrors
类型: boolean
默认: true

确定是否抛出got.HTTPError错误响应(非2xx状态代码).

如果禁用此选项,在请求遇到错误状态代码,会使用response resolve,而不是抛出got.HTTPError。如果您正在检查资源可用性,并且期望出现错误响应,这可能很有用.

agent

对应http.requestagent选项,但有一个额外的功能:

如果您需要针对不同协议的不同代理,则可以将代理映射传递给agent选项。这是必要的,因为对一个协议的请求可能会重定向到另一个协议。在这种情况下,Got将为您切换到正确的协议代理.

const got = require('got');
const HttpAgent = require('agentkeepalive');
const {HttpsAgent} = HttpAgent;

got('sindresorhus.com', {
	agent: {
		http: new HttpAgent(),
		https: new HttpsAgent()
	}
});
hooks
类型: Object<string, Function[]>

钩子允许在请求生命周期中进行修改。钩子函数可以是异步的,和也能串行运行的.

hooks.beforeRequest
类型: Function[]
默认: []

调用标准的 请求选项。在发送请求之前,不会对请求进行进一步更改。这对结合got.extend()got.create()使用,特别有用,当您想要创建一个API客户端时,例如,使用HMAC签名.

AWS部分举的例子.

注意:如果你修改了body,你也需要修改content-length标题,因为它已经被计算和分配.

hooks.beforeRedirect
类型: Function[]
默认: []

调用标准的 请求选项。Got的请求不会进一步更改.当您想要避免死站点时,这尤其有用.例:

const got = require('got');

got('example.com', {
	hooks: {
		beforeRedirect: [
			options => {
				if (options.hostname === 'deadSite') {
					options.hostname = 'fallbackSite';
				}
			}
		]
	}
});
hooks.beforeRetry
类型: Function[]
默认: []

调用标准的 请求选项,错误和重试计数。Got的请求不会进一步更改。在下次尝试之前,需要一些额外的工作时,这尤其有用.例:

const got = require('got');

got('example.com', {
	hooks: {
		beforeRetry: [
			(options, error, retryCount) => {
				if (error.statusCode === 413) { // Payload too large
					options.body = getNewBody();
				}
			}
		]
	}
});
hooks.afterResponse
类型: 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
});

Response

响应对象通常是一个Node.js HTTP响应流但是,如果从缓存返回,那它会是一个类似响应的对象和行为方式相同.

参数 |> body / url / requestUrl / timings / fromCache / redirectUrls / retryCount /

body
类型: string Object (取决于options.json)

请求的结果.

url
类型: string

重定向后的请求URL或最终URL.

requestUrl
类型: string

原始请求网址.

timings
类型: 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纪元以来经过的毫秒数.

fromCache
类型: boolean

是否从缓存中检索响应.

redirectUrls
类型: Array

重定向网址.

retryCount
类型: number

重试请求的次数.

Streams

注意:进度事件,重定向事件和请求/响应事件,也可以与promise一起使用.

got.stream(url, [options])

options.streamtrue.

返回带有其他活动的一个双工流:

.on('request', request)

request事件获取请求的request对象.

小费: 您可以使用request事件,中止请求:

got.stream('github.com')
	.on('request', request => setTimeout(() => request.abort(), 50));
.on('response', response)

response事件获取最终请求的response对象.

.on('redirect', response, nextOptions)

redirect事件获取重定向的response对象。第二个参数是下一个重定向位置请求的选项.

.on('uploadProgress', progress)
.on('downloadProgress', progress)

上传(发送请求)和下载(接收响应)的进度事件。该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);
})();
.on('error', error, body, response)

error在协议错误的情况下,发出的事件(如ENOTFOUND等)或状态错误(4xx或5xx)。第二个参数是状态错误时服务器响应的主体。第三个参数是响应对象.

got.get(url, [options])

got.post(url, [options])

got.put(url, [options])

got.patch(url, [options])

got.head(url, [options])

got.delete(url, [options])

options.method方法名称设置好,和做成请求.

Instances

got.extend([options])

配置一个带默认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().

got.mergeOptions(parentOptions, newOptions)

扩展父选项。避免使用对象传播...,因为它不能递归工作:

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,它用新属性的深拷贝覆盖旧的.
  • 否则,新值分配给对应的字段就好了。

got.defaults

类型: Object

默认的Got选项.

Errors

每个错误包含(如果可用)的属性字段
body,
statusCode,
statusMessage,
host,
hostname
method,
path,
protocol
url

使调试更容易.

在Promise模式下, response也附加到错误.

got.CacheError

例如,当缓存方法失败时,如果数据库出现故障或存在文件系统错误.

got.RequestError

请求失败时,包含一个具有错误类代码的code属性,如ECONNREFUSED.

got.ReadError

从响应流中读取失败.

got.ParseError

json选项已启用,服务器响应代码为2xx,和JSON.parse失败.

got.HTTPError

当服务器响应代码不是2xx时,包括statusCode,statusMessage,和redirectUrls属性.

got.MaxRedirectsError

当服务器重定向您十次以上时,包括一个redirectUrls属性,这是在放弃之前,重定向的一个URL数组.

got.UnsupportedProtocolError

不支持的协议时.

got.CancelError

请求被.cancel()中止时.

got.TimeoutError

当请求因一个超时而中止时

Aborting the request

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
	}
})();

Cache

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文档有关如何使用存储适配器的更多信息.

Proxies

你可以使用tunnel包,加上agent与代理一起工作:

const got = require('got');
const tunnel = require('tunnel');

got('sindresorhus.com', {
	agent: tunnel.httpOverHttp({
		proxy: {
			host: 'localhost'
		}
	})
});

查看下global-tunnel,如果您想为应用程序中的所有HTTP/HTTPS流量配置代理支持.

Cookies

你可以使用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

你可以使用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

你可以使用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 Domain Sockets

请求也可以通过UNIX域名套接字发送出去。 使用以下URL方案:PROTOCOL://unix:SOCKET:PATH.

  • PROTOCOL - httphttps (可选)
  • 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

对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
});

Testing

您可以通过使用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();
})();

Tips

User Agent

设置'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
	}
});

304 Responses

记住,如果你发送一个if-modified-since标题。和接收到了304 Not Modified响应,主体-body就会是空的。缓存和检索主体内容是您的职责.

Custom endpoints

使用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().

Experimental HTTP2 support

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);
})();

Comparison

got request node-fetch axios
HTTP/2 支持
Browser 支持 ✔*
Electron 支持
Promise API
Stream API Node.js only
Request 中止
RFC compliant caching
Cookies (out-of-box)
跟踪 重定向网址
失败重试
Progress 事件 Browser only
可控 gzip/deflate
timeouts 优化
Timings
Errors 元数据
JSON 模式
Custom defaults
Composable
Hooks
Issues open
Issues closed
Downloads
Coverage
Build
Bugs
Dependents
Install size

*它几乎与浏览器fetch API兼容.
❔ 实验支持.

Related

  • 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解析替代字符串

Maintainers

Sindre Sorhus Vsevolod Strukchinsky Alexander Tesfamichael Luke Childs Szymon Marczak Brandon Smith
Sindre Sorhus Vsevolod Strukchinsky Alexander Tesfamichael Luke Childs Szymon Marczak Brandon Smith

License

MIT

About

中文翻译: <got> 简化的HTTP请求 ❤️ 校对 ✅

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published