UNPKG

17.6 kBMarkdownView Raw
1<h1 align="center">
2 <br>
3 <img width="360" src="https://rawgit.com/sindresorhus/got/master/media/logo.svg" alt="got">
4 <br>
5 <br>
6 <br>
7</h1>
8
9> Simplified HTTP requests
10
11[![Build Status](https://travis-ci.org/sindresorhus/got.svg?branch=master)](https://travis-ci.org/sindresorhus/got) [![Coverage Status](https://coveralls.io/repos/github/sindresorhus/got/badge.svg?branch=master)](https://coveralls.io/github/sindresorhus/got?branch=master) [![Downloads](https://img.shields.io/npm/dm/got.svg)](https://npmjs.com/got)
12
13A nicer interface to the built-in [`http`](http://nodejs.org/api/http.html) module.
14
15Created because [`request`](https://github.com/request/request) is bloated *(several megabytes!)*.
16
17
18## Highlights
19
20- [Promise & stream API](#api)
21- [Request cancelation](#aborting-the-request)
22- [RFC compliant caching](#cache-adapters)
23- [Follows redirects](#followredirect)
24- [Retries on network failure](#retries)
25- [Progress events](#onuploadprogress-progress)
26- [Handles gzip/deflate](#decompress)
27- [Timeout handling](#timeout)
28- [Errors with metadata](#errors)
29- [JSON mode](#json)
30- [WHATWG URL support](#url)
31- [Electron support](#useelectronnet)
32
33
34## Install
35
36```
37$ npm install got
38```
39
40
41## Usage
42
43```js
44const got = require('got');
45
46(async () => {
47 try {
48 const response = await got('sindresorhus.com');
49 console.log(response.body);
50 //=> '<!doctype html> ...'
51 } catch (error) {
52 console.log(error.response.body);
53 //=> 'Internal server error ...'
54 }
55})();
56```
57
58###### Streams
59
60```js
61const fs = require('fs');
62const got = require('got');
63
64got.stream('sindresorhus.com').pipe(fs.createWriteStream('index.html'));
65
66// For POST, PUT, and PATCH methods `got.stream` returns a `stream.Writable`
67fs.createReadStream('index.html').pipe(got.stream.post('sindresorhus.com'));
68```
69
70
71### API
72
73It's a `GET` request by default, but can be changed by using different methods or in the `options`.
74
75#### got(url, [options])
76
77Returns a Promise for a `response` object with a `body` property, a `url` property with the request URL or the final URL after redirects, and a `requestUrl` property with the original request URL.
78
79The response object will normally be a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage), however if returned from the cache it will be a [responselike object](https://github.com/lukechilds/responselike) which behaves in the same way.
80
81The response will also have a `fromCache` property set with a boolean value.
82
83##### url
84
85Type: `string` `Object`
86
87The URL to request as simple string, a [`http.request` options](https://nodejs.org/api/http.html#http_http_request_options_callback), or a [WHATWG `URL`](https://nodejs.org/api/url.html#url_class_url).
88
89Properties from `options` will override properties in the parsed `url`.
90
91If no protocol is specified, it will default to `https`.
92
93##### options
94
95Type: `Object`
96
97Any of the [`http.request`](http://nodejs.org/api/http.html#http_http_request_options_callback) options.
98
99###### body
100
101Type: `string` `Buffer` `stream.Readable`
102
103*This is mutually exclusive with stream mode.*
104
105Body that will be sent with a `POST` request.
106
107If present in `options` and `options.method` is not set, `options.method` will be set to `POST`.
108
109If `content-length` or `transfer-encoding` is not set in `options.headers` and `body` is a string or buffer, `content-length` will be set to the body length.
110
111###### encoding
112
113Type: `string` `null`<br>
114Default: `'utf8'`
115
116[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. If `null`, the body is returned as a Buffer.
117
118###### form
119
120Type: `boolean`<br>
121Default: `false`
122
123*This is mutually exclusive with stream mode.*
124
125If set to `true` and `Content-Type` header is not set, it will be set to `application/x-www-form-urlencoded`.
126
127`body` must be a plain object or array and will be stringified.
128
129###### json
130
131Type: `boolean`<br>
132Default: `false`
133
134*This is mutually exclusive with stream mode.*
135
136If set to `true` and `Content-Type` header is not set, it will be set to `application/json`.
137
138Parse response body with `JSON.parse` and set `accept` header to `application/json`. If used in conjunction with the `form` option, the `body` will the stringified as querystring and the response parsed as JSON.
139
140`body` must be a plain object or array and will be stringified.
141
142###### query
143
144Type: `string` `Object`<br>
145
146Query string object that will be added to the request URL. This will override the query string in `url`.
147
148###### timeout
149
150Type: `number` `Object`
151
152Milliseconds to wait for the server to end the response before aborting request with `ETIMEDOUT` error.
153
154This also accepts an object with separate `connect`, `socket`, and `request` fields for connection, socket, and entire request timeouts.
155
156###### retries
157
158Type: `number` `Function`<br>
159Default: `2`
160
161Number of request retries when network errors happens. Delays between retries counts with function `1000 * Math.pow(2, retry) + Math.random() * 100`, where `retry` is attempt number (starts from 0).
162
163Option accepts `function` with `retry` and `error` arguments. Function must return delay in milliseconds (`0` return value cancels retry).
164
165**Note:** if `retries` is `number`, `ENOTFOUND` and `ENETUNREACH` error will not be retried (see full list in [`is-retry-allowed`](https://github.com/floatdrop/is-retry-allowed/blob/master/index.js#L12) module).
166
167###### followRedirect
168
169Type: `boolean`<br>
170Default: `true`
171
172Defines if redirect responses should be followed automatically.
173
174Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), got will automatically
175request the resource pointed to in the location header via `GET`. This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4).
176
177###### decompress
178
179Type: `boolean`<br>
180Default: `true`
181
182Decompress the response automatically.
183
184If this is disabled, a compressed response is returned as a `Buffer`. This may be useful if you want to handle decompression yourself or stream the raw compressed data.
185
186###### cache
187
188Type: `Object`<br>
189Default: `false`
190
191[Cache adapter instance](#cache-adapters) for storing cached data.
192
193###### useElectronNet
194
195Type: `boolean`<br>
196Default: `false`
197
198When used in Electron, Got will use [`electron.net`](https://electronjs.org/docs/api/net/) instead of the Node.js `http` module. According to the Electron docs, it should be fully compatible, but it's not entirely. See [#315](https://github.com/sindresorhus/got/issues/315).
199
200
201#### Streams
202
203#### got.stream(url, [options])
204
205`stream` method will return Duplex stream with additional events:
206
207##### .on('request', request)
208
209`request` event to get the request object of the request.
210
211**Tip**: You can use `request` event to abort request:
212
213```js
214got.stream('github.com')
215 .on('request', req => setTimeout(() => req.abort(), 50));
216```
217
218##### .on('response', response)
219
220`response` event to get the response object of the final request.
221
222##### .on('redirect', response, nextOptions)
223
224`redirect` event to get the response object of a redirect. The second argument is options for the next request to the redirect location.
225
226##### .on('uploadProgress', progress)
227##### .on('downloadProgress', progress)
228
229Progress events for uploading (sending request) and downloading (receiving response). The `progress` argument is an object like:
230
231```js
232{
233 percent: 0.1,
234 transferred: 1024,
235 total: 10240
236}
237```
238
239If it's not possible to retrieve the body size (can happen when streaming), `total` will be `null`.
240
241**Note**: Progress events can also be used with promises.
242
243```js
244(async () => {
245 const response = await got('sindresorhus.com')
246 .on('downloadProgress', progress => {
247 // Report download progress
248 })
249 .on('uploadProgress', progress => {
250 // Report upload progress
251 });
252
253 console.log(response);
254})();
255```
256
257##### .on('error', error, body, response)
258
259`error` event emitted in case of protocol error (like `ENOTFOUND` etc.) or status error (4xx or 5xx). The second argument is the body of the server response in case of status error. The third argument is response object.
260
261#### got.get(url, [options])
262#### got.post(url, [options])
263#### got.put(url, [options])
264#### got.patch(url, [options])
265#### got.head(url, [options])
266#### got.delete(url, [options])
267
268Sets `options.method` to the method name and makes a request.
269
270
271## Errors
272
273Each error contains (if available) `statusCode`, `statusMessage`, `host`, `hostname`, `method`, `path`, `protocol` and `url` properties to make debugging easier.
274
275In Promise mode, the `response` is attached to the error.
276
277#### got.CacheError
278
279When a cache method fails, for example if the database goes down, or there's a filesystem error.
280
281#### got.RequestError
282
283When a request fails. Contains a `code` property with error class code, like `ECONNREFUSED`.
284
285#### got.ReadError
286
287When reading from response stream fails.
288
289#### got.ParseError
290
291When `json` option is enabled, server response code is 2xx, and `JSON.parse` fails.
292
293#### got.HTTPError
294
295When server response code is not 2xx. Includes `statusCode`, `statusMessage`, and `redirectUrls` properties.
296
297#### got.MaxRedirectsError
298
299When server redirects you more than 10 times. Includes a `redirectUrls` property, which is an array of the URLs Got was redirected to before giving up.
300
301#### got.UnsupportedProtocolError
302
303When given an unsupported protocol.
304
305#### got.CancelError
306
307When the request is aborted with `.cancel()`.
308
309
310## Aborting the request
311
312The promise returned by Got has a [`.cancel()`](https://github.com/sindresorhus/p-cancelable) method which, when called, aborts the request.
313
314```js
315(async () => {
316 const request = got(url, options);
317
318
319
320 // In another part of the code
321 if (something) {
322 request.cancel();
323 }
324
325
326
327 try {
328 await request;
329 } catch (error) {
330 if (request.canceled) { // Or `error instanceof got.CancelError`
331 // Handle cancelation
332 }
333
334 // Handle other errors
335 }
336})();
337```
338
339<a name="cache-adapters"></a>
340## Cache
341
342Got implements [RFC 7234](http://httpwg.org/specs/rfc7234.html) compliant HTTP caching which works out of the box in memory or is easily pluggable with a wide range of storage adapters. Fresh cache entries are served directly from cache and stale cache entries are revalidated with `If-None-Match`/`If-Modified-Since` headers. You can read more about the underlying cache behaviour in the `cacheable-request` [documentation](https://github.com/lukechilds/cacheable-request).
343
344You can use the JavaScript `Map` type as an in memory cache:
345
346```js
347const got = require('got');
348const map = new Map();
349
350(async () => {
351 let response = await got('sindresorhus.com', {cache: map});
352 console.log(response.fromCache);
353 //=> false
354
355 response = await got('sindresorhus.com', {cache: map});
356 console.log(response.fromCache);
357 //=> true
358})();
359```
360
361Got uses [Keyv](https://github.com/lukechilds/keyv) internally to support a wide range of storage adapters. For something more scalable you could use an [official Keyv storage adapter](https://github.com/lukechilds/keyv#official-storage-adapters):
362
363```
364$ npm install @keyv/redis
365```
366
367```js
368const got = require('got');
369const KeyvRedis = require('@keyv/redis');
370
371const redis = new KeyvRedis('redis://user:pass@localhost:6379');
372
373got('sindresorhus.com', {cache: redis});
374```
375
376Got supports anything that follows the Map API, so it's easy to write your own storage adapter or use a third-party solution.
377
378For example, the following are all valid storage adapters:
379
380```js
381const storageAdapter = new Map();
382// or
383const storageAdapter = require('./my-storage-adapter');
384// or
385const QuickLRU = require('quick-lru');
386const storageAdapter = new QuickLRU({maxSize: 1000});
387
388got('sindresorhus.com', {cache: storageAdapter});
389```
390
391View the [Keyv docs](https://github.com/lukechilds/keyv) for more information on how to use storage adapters.
392
393
394## Proxies
395
396You can use the [`tunnel`](https://github.com/koichik/node-tunnel) module with the `agent` option to work with proxies:
397
398```js
399const got = require('got');
400const tunnel = require('tunnel');
401
402got('sindresorhus.com', {
403 agent: tunnel.httpOverHttp({
404 proxy: {
405 host: 'localhost'
406 }
407 })
408});
409```
410
411If you require different agents for different protocols, you can pass a map of agents to the `agent` option. This is necessary because a request to one protocol might redirect to another. In such a scenario, `got` will switch over to the right protocol agent for you.
412
413```js
414const got = require('got');
415const HttpAgent = require('agentkeepalive');
416const HttpsAgent = HttpAgent.HttpsAgent;
417
418got('sindresorhus.com', {
419 agent: {
420 http: new HttpAgent(),
421 https: new HttpsAgent()
422 }
423});
424```
425
426
427## Cookies
428
429You can use the [`cookie`](https://github.com/jshttp/cookie) module to include cookies in a request:
430
431```js
432const got = require('got');
433const cookie = require('cookie');
434
435got('google.com', {
436 headers: {
437 cookie: cookie.serialize('foo', 'bar')
438 }
439});
440```
441
442
443## Form data
444
445You can use the [`form-data`](https://github.com/form-data/form-data) module to create POST request with form data:
446
447```js
448const fs = require('fs');
449const got = require('got');
450const FormData = require('form-data');
451const form = new FormData();
452
453form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
454
455got.post('google.com', {
456 body: form
457});
458```
459
460
461## OAuth
462
463You can use the [`oauth-1.0a`](https://github.com/ddo/oauth-1.0a) module to create a signed OAuth request:
464
465```js
466const got = require('got');
467const crypto = require('crypto');
468const OAuth = require('oauth-1.0a');
469
470const oauth = OAuth({
471 consumer: {
472 key: process.env.CONSUMER_KEY,
473 secret: process.env.CONSUMER_SECRET
474 },
475 signature_method: 'HMAC-SHA1',
476 hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
477});
478
479const token = {
480 key: process.env.ACCESS_TOKEN,
481 secret: process.env.ACCESS_TOKEN_SECRET
482};
483
484const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
485
486got(url, {
487 headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
488 json: true
489});
490```
491
492
493## Unix Domain Sockets
494
495Requests can also be sent via [unix domain sockets](http://serverfault.com/questions/124517/whats-the-difference-between-unix-socket-and-tcp-ip-socket). Use the following URL scheme: `PROTOCOL://unix:SOCKET:PATH`.
496
497- `PROTOCOL` - `http` or `https` *(optional)*
498- `SOCKET` - absolute path to a unix domain socket, e.g. `/var/run/docker.sock`
499- `PATH` - request path, e.g. `/v2/keys`
500
501```js
502got('http://unix:/var/run/docker.sock:/containers/json');
503
504// or without protocol (http by default)
505got('unix:/var/run/docker.sock:/containers/json');
506```
507
508## AWS
509
510Requests to AWS services need to have their headers signed. This can be accomplished by using the [`aws4`](https://www.npmjs.com/package/aws4) package. This is an example for querying an ["Elasticsearch Service"](https://aws.amazon.com/elasticsearch-service/) host with a signed request.
511
512```js
513const url = require('url');
514const AWS = require('aws-sdk');
515const aws4 = require('aws4');
516const got = require('got');
517const config = require('./config');
518
519// Reads keys from the environment or `~/.aws/credentials`. Could be a plain object.
520const awsConfig = new AWS.Config({ region: config.region });
521
522function request(uri, options) {
523 const awsOpts = {
524 region: awsConfig.region,
525 headers: {
526 accept: 'application/json',
527 'content-type': 'application/json'
528 },
529 method: 'GET',
530 json: true
531 };
532
533 // We need to parse the URL before passing it to `got` so `aws4` can sign the request
534 const opts = Object.assign(url.parse(uri), awsOpts, options);
535 aws4.sign(opts, awsConfig.credentials);
536
537 return got(opts);
538}
539
540request(`https://${config.host}/production/users/1`);
541
542request(`https://${config.host}/production/`, {
543 // All usual `got` options
544});
545```
546
547
548## Tips
549
550### User Agent
551
552It's a good idea to set the `'user-agent'` header so the provider can more easily see how their resource is used. By default, it's the URL to this repo.
553
554```js
555const got = require('got');
556const pkg = require('./package.json');
557
558got('sindresorhus.com', {
559 headers: {
560 'user-agent': `my-module/${pkg.version} (https://github.com/username/my-module)`
561 }
562});
563```
564
565### 304 Responses
566
567Bear in mind, if you send an `if-modified-since` header and receive a `304 Not Modified` response, the body will be empty. It's your responsibility to cache and retrieve the body contents.
568
569
570## Related
571
572- [gh-got](https://github.com/sindresorhus/gh-got) - Got convenience wrapper to interact with the GitHub API
573- [gl-got](https://github.com/singapore/gl-got) - Got convenience wrapper to interact with the GitLab API
574- [travis-got](https://github.com/samverschueren/travis-got) - Got convenience wrapper to interact with the Travis API
575- [graphql-got](https://github.com/kevva/graphql-got) - Got convenience wrapper to interact with GraphQL
576- [GotQL](https://github.com/khaosdoctor/gotql) - Got convenience wrapper to interact with GraphQL using JSON-parsed queries instead of strings
577
578
579## Created by
580
581[![Sindre Sorhus](https://github.com/sindresorhus.png?size=100)](https://sindresorhus.com) | [![Vsevolod Strukchinsky](https://github.com/floatdrop.png?size=100)](https://github.com/floatdrop) | [![Alexander Tesfamichael](https://github.com/AlexTes.png?size=100)](https://github.com/AlexTes) | [![Luke Childs](https://github.com/lukechilds.png?size=100)](https://github.com/lukechilds)
582---|---|---|---
583[Sindre Sorhus](https://sindresorhus.com) | [Vsevolod Strukchinsky](https://github.com/floatdrop) | [Alexander Tesfamichael](https://alextes.me) | [Luke Childs](https://github.com/lukechilds)
584
585
586## License
587
588MIT