twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

README.md (46383B)


      1 # Deprecated!
      2 
      3 As of Feb 11th 2020, request is fully deprecated. No new changes are expected land. In fact, none have landed for some time.
      4 
      5 For more information about why request is deprecated and possible alternatives refer to
      6 [this issue](https://github.com/request/request/issues/3142).
      7 
      8 # Request - Simplified HTTP client
      9 
     10 [![npm package](https://nodei.co/npm/request.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/request/)
     11 
     12 [![Build status](https://img.shields.io/travis/request/request/master.svg?style=flat-square)](https://travis-ci.org/request/request)
     13 [![Coverage](https://img.shields.io/codecov/c/github/request/request.svg?style=flat-square)](https://codecov.io/github/request/request?branch=master)
     14 [![Coverage](https://img.shields.io/coveralls/request/request.svg?style=flat-square)](https://coveralls.io/r/request/request)
     15 [![Dependency Status](https://img.shields.io/david/request/request.svg?style=flat-square)](https://david-dm.org/request/request)
     16 [![Known Vulnerabilities](https://snyk.io/test/npm/request/badge.svg?style=flat-square)](https://snyk.io/test/npm/request)
     17 [![Gitter](https://img.shields.io/badge/gitter-join_chat-blue.svg?style=flat-square)](https://gitter.im/request/request?utm_source=badge)
     18 
     19 
     20 ## Super simple to use
     21 
     22 Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.
     23 
     24 ```js
     25 const request = require('request');
     26 request('http://www.google.com', function (error, response, body) {
     27   console.error('error:', error); // Print the error if one occurred
     28   console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
     29   console.log('body:', body); // Print the HTML for the Google homepage.
     30 });
     31 ```
     32 
     33 
     34 ## Table of contents
     35 
     36 - [Streaming](#streaming)
     37 - [Promises & Async/Await](#promises--asyncawait)
     38 - [Forms](#forms)
     39 - [HTTP Authentication](#http-authentication)
     40 - [Custom HTTP Headers](#custom-http-headers)
     41 - [OAuth Signing](#oauth-signing)
     42 - [Proxies](#proxies)
     43 - [Unix Domain Sockets](#unix-domain-sockets)
     44 - [TLS/SSL Protocol](#tlsssl-protocol)
     45 - [Support for HAR 1.2](#support-for-har-12)
     46 - [**All Available Options**](#requestoptions-callback)
     47 
     48 Request also offers [convenience methods](#convenience-methods) like
     49 `request.defaults` and `request.post`, and there are
     50 lots of [usage examples](#examples) and several
     51 [debugging techniques](#debugging).
     52 
     53 
     54 ---
     55 
     56 
     57 ## Streaming
     58 
     59 You can stream any response to a file stream.
     60 
     61 ```js
     62 request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))
     63 ```
     64 
     65 You can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types (in this case `application/json`) and use the proper `content-type` in the PUT request (if the headers don’t already provide one).
     66 
     67 ```js
     68 fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))
     69 ```
     70 
     71 Request can also `pipe` to itself. When doing so, `content-type` and `content-length` are preserved in the PUT headers.
     72 
     73 ```js
     74 request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))
     75 ```
     76 
     77 Request emits a "response" event when a response is received. The `response` argument will be an instance of [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage).
     78 
     79 ```js
     80 request
     81   .get('http://google.com/img.png')
     82   .on('response', function(response) {
     83     console.log(response.statusCode) // 200
     84     console.log(response.headers['content-type']) // 'image/png'
     85   })
     86   .pipe(request.put('http://mysite.com/img.png'))
     87 ```
     88 
     89 To easily handle errors when streaming requests, listen to the `error` event before piping:
     90 
     91 ```js
     92 request
     93   .get('http://mysite.com/doodle.png')
     94   .on('error', function(err) {
     95     console.error(err)
     96   })
     97   .pipe(fs.createWriteStream('doodle.png'))
     98 ```
     99 
    100 Now let’s get fancy.
    101 
    102 ```js
    103 http.createServer(function (req, resp) {
    104   if (req.url === '/doodle.png') {
    105     if (req.method === 'PUT') {
    106       req.pipe(request.put('http://mysite.com/doodle.png'))
    107     } else if (req.method === 'GET' || req.method === 'HEAD') {
    108       request.get('http://mysite.com/doodle.png').pipe(resp)
    109     }
    110   }
    111 })
    112 ```
    113 
    114 You can also `pipe()` from `http.ServerRequest` instances, as well as to `http.ServerResponse` instances. The HTTP method, headers, and entity-body data will be sent. Which means that, if you don't really care about security, you can do:
    115 
    116 ```js
    117 http.createServer(function (req, resp) {
    118   if (req.url === '/doodle.png') {
    119     const x = request('http://mysite.com/doodle.png')
    120     req.pipe(x)
    121     x.pipe(resp)
    122   }
    123 })
    124 ```
    125 
    126 And since `pipe()` returns the destination stream in ≥ Node 0.5.x you can do one line proxying. :)
    127 
    128 ```js
    129 req.pipe(request('http://mysite.com/doodle.png')).pipe(resp)
    130 ```
    131 
    132 Also, none of this new functionality conflicts with requests previous features, it just expands them.
    133 
    134 ```js
    135 const r = request.defaults({'proxy':'http://localproxy.com'})
    136 
    137 http.createServer(function (req, resp) {
    138   if (req.url === '/doodle.png') {
    139     r.get('http://google.com/doodle.png').pipe(resp)
    140   }
    141 })
    142 ```
    143 
    144 You can still use intermediate proxies, the requests will still follow HTTP forwards, etc.
    145 
    146 [back to top](#table-of-contents)
    147 
    148 
    149 ---
    150 
    151 
    152 ## Promises & Async/Await
    153 
    154 `request` supports both streaming and callback interfaces natively. If you'd like `request` to return a Promise instead, you can use an alternative interface wrapper for `request`. These wrappers can be useful if you prefer to work with Promises, or if you'd like to use `async`/`await` in ES2017.
    155 
    156 Several alternative interfaces are provided by the request team, including:
    157 - [`request-promise`](https://github.com/request/request-promise) (uses [Bluebird](https://github.com/petkaantonov/bluebird) Promises)
    158 - [`request-promise-native`](https://github.com/request/request-promise-native) (uses native Promises)
    159 - [`request-promise-any`](https://github.com/request/request-promise-any) (uses [any-promise](https://www.npmjs.com/package/any-promise) Promises)
    160 
    161 Also, [`util.promisify`](https://nodejs.org/api/util.html#util_util_promisify_original), which is available from Node.js v8.0 can be used to convert a regular function that takes a callback to return a promise instead.
    162 
    163 
    164 [back to top](#table-of-contents)
    165 
    166 
    167 ---
    168 
    169 
    170 ## Forms
    171 
    172 `request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.
    173 
    174 
    175 #### application/x-www-form-urlencoded (URL-Encoded Forms)
    176 
    177 URL-encoded forms are simple.
    178 
    179 ```js
    180 request.post('http://service.com/upload', {form:{key:'value'}})
    181 // or
    182 request.post('http://service.com/upload').form({key:'value'})
    183 // or
    184 request.post({url:'http://service.com/upload', form: {key:'value'}}, function(err,httpResponse,body){ /* ... */ })
    185 ```
    186 
    187 
    188 #### multipart/form-data (Multipart Form Uploads)
    189 
    190 For `multipart/form-data` we use the [form-data](https://github.com/form-data/form-data) library by [@felixge](https://github.com/felixge). For the most cases, you can pass your upload form data via the `formData` option.
    191 
    192 
    193 ```js
    194 const formData = {
    195   // Pass a simple key-value pair
    196   my_field: 'my_value',
    197   // Pass data via Buffers
    198   my_buffer: Buffer.from([1, 2, 3]),
    199   // Pass data via Streams
    200   my_file: fs.createReadStream(__dirname + '/unicycle.jpg'),
    201   // Pass multiple values /w an Array
    202   attachments: [
    203     fs.createReadStream(__dirname + '/attachment1.jpg'),
    204     fs.createReadStream(__dirname + '/attachment2.jpg')
    205   ],
    206   // Pass optional meta-data with an 'options' object with style: {value: DATA, options: OPTIONS}
    207   // Use case: for some types of streams, you'll need to provide "file"-related information manually.
    208   // See the `form-data` README for more information about options: https://github.com/form-data/form-data
    209   custom_file: {
    210     value:  fs.createReadStream('/dev/urandom'),
    211     options: {
    212       filename: 'topsecret.jpg',
    213       contentType: 'image/jpeg'
    214     }
    215   }
    216 };
    217 request.post({url:'http://service.com/upload', formData: formData}, function optionalCallback(err, httpResponse, body) {
    218   if (err) {
    219     return console.error('upload failed:', err);
    220   }
    221   console.log('Upload successful!  Server responded with:', body);
    222 });
    223 ```
    224 
    225 For advanced cases, you can access the form-data object itself via `r.form()`. This can be modified until the request is fired on the next cycle of the event-loop. (Note that this calling `form()` will clear the currently set form data for that request.)
    226 
    227 ```js
    228 // NOTE: Advanced use-case, for normal use see 'formData' usage above
    229 const r = request.post('http://service.com/upload', function optionalCallback(err, httpResponse, body) {...})
    230 const form = r.form();
    231 form.append('my_field', 'my_value');
    232 form.append('my_buffer', Buffer.from([1, 2, 3]));
    233 form.append('custom_file', fs.createReadStream(__dirname + '/unicycle.jpg'), {filename: 'unicycle.jpg'});
    234 ```
    235 See the [form-data README](https://github.com/form-data/form-data) for more information & examples.
    236 
    237 
    238 #### multipart/related
    239 
    240 Some variations in different HTTP implementations require a newline/CRLF before, after, or both before and after the boundary of a `multipart/related` request (using the multipart option). This has been observed in the .NET WebAPI version 4.0. You can turn on a boundary preambleCRLF or postamble by passing them as `true` to your request options.
    241 
    242 ```js
    243   request({
    244     method: 'PUT',
    245     preambleCRLF: true,
    246     postambleCRLF: true,
    247     uri: 'http://service.com/upload',
    248     multipart: [
    249       {
    250         'content-type': 'application/json',
    251         body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})
    252       },
    253       { body: 'I am an attachment' },
    254       { body: fs.createReadStream('image.png') }
    255     ],
    256     // alternatively pass an object containing additional options
    257     multipart: {
    258       chunked: false,
    259       data: [
    260         {
    261           'content-type': 'application/json',
    262           body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})
    263         },
    264         { body: 'I am an attachment' }
    265       ]
    266     }
    267   },
    268   function (error, response, body) {
    269     if (error) {
    270       return console.error('upload failed:', error);
    271     }
    272     console.log('Upload successful!  Server responded with:', body);
    273   })
    274 ```
    275 
    276 [back to top](#table-of-contents)
    277 
    278 
    279 ---
    280 
    281 
    282 ## HTTP Authentication
    283 
    284 ```js
    285 request.get('http://some.server.com/').auth('username', 'password', false);
    286 // or
    287 request.get('http://some.server.com/', {
    288   'auth': {
    289     'user': 'username',
    290     'pass': 'password',
    291     'sendImmediately': false
    292   }
    293 });
    294 // or
    295 request.get('http://some.server.com/').auth(null, null, true, 'bearerToken');
    296 // or
    297 request.get('http://some.server.com/', {
    298   'auth': {
    299     'bearer': 'bearerToken'
    300   }
    301 });
    302 ```
    303 
    304 If passed as an option, `auth` should be a hash containing values:
    305 
    306 - `user` || `username`
    307 - `pass` || `password`
    308 - `sendImmediately` (optional)
    309 - `bearer` (optional)
    310 
    311 The method form takes parameters
    312 `auth(username, password, sendImmediately, bearer)`.
    313 
    314 `sendImmediately` defaults to `true`, which causes a basic or bearer
    315 authentication header to be sent. If `sendImmediately` is `false`, then
    316 `request` will retry with a proper authentication header after receiving a
    317 `401` response from the server (which must contain a `WWW-Authenticate` header
    318 indicating the required authentication method).
    319 
    320 Note that you can also specify basic authentication using the URL itself, as
    321 detailed in [RFC 1738](http://www.ietf.org/rfc/rfc1738.txt). Simply pass the
    322 `user:password` before the host with an `@` sign:
    323 
    324 ```js
    325 const username = 'username',
    326     password = 'password',
    327     url = 'http://' + username + ':' + password + '@some.server.com';
    328 
    329 request({url}, function (error, response, body) {
    330    // Do more stuff with 'body' here
    331 });
    332 ```
    333 
    334 Digest authentication is supported, but it only works with `sendImmediately`
    335 set to `false`; otherwise `request` will send basic authentication on the
    336 initial request, which will probably cause the request to fail.
    337 
    338 Bearer authentication is supported, and is activated when the `bearer` value is
    339 available. The value may be either a `String` or a `Function` returning a
    340 `String`. Using a function to supply the bearer token is particularly useful if
    341 used in conjunction with `defaults` to allow a single function to supply the
    342 last known token at the time of sending a request, or to compute one on the fly.
    343 
    344 [back to top](#table-of-contents)
    345 
    346 
    347 ---
    348 
    349 
    350 ## Custom HTTP Headers
    351 
    352 HTTP Headers, such as `User-Agent`, can be set in the `options` object.
    353 In the example below, we call the github API to find out the number
    354 of stars and forks for the request repository. This requires a
    355 custom `User-Agent` header as well as https.
    356 
    357 ```js
    358 const request = require('request');
    359 
    360 const options = {
    361   url: 'https://api.github.com/repos/request/request',
    362   headers: {
    363     'User-Agent': 'request'
    364   }
    365 };
    366 
    367 function callback(error, response, body) {
    368   if (!error && response.statusCode == 200) {
    369     const info = JSON.parse(body);
    370     console.log(info.stargazers_count + " Stars");
    371     console.log(info.forks_count + " Forks");
    372   }
    373 }
    374 
    375 request(options, callback);
    376 ```
    377 
    378 [back to top](#table-of-contents)
    379 
    380 
    381 ---
    382 
    383 
    384 ## OAuth Signing
    385 
    386 [OAuth version 1.0](https://tools.ietf.org/html/rfc5849) is supported. The
    387 default signing algorithm is
    388 [HMAC-SHA1](https://tools.ietf.org/html/rfc5849#section-3.4.2):
    389 
    390 ```js
    391 // OAuth1.0 - 3-legged server side flow (Twitter example)
    392 // step 1
    393 const qs = require('querystring')
    394   , oauth =
    395     { callback: 'http://mysite.com/callback/'
    396     , consumer_key: CONSUMER_KEY
    397     , consumer_secret: CONSUMER_SECRET
    398     }
    399   , url = 'https://api.twitter.com/oauth/request_token'
    400   ;
    401 request.post({url:url, oauth:oauth}, function (e, r, body) {
    402   // Ideally, you would take the body in the response
    403   // and construct a URL that a user clicks on (like a sign in button).
    404   // The verifier is only available in the response after a user has
    405   // verified with twitter that they are authorizing your app.
    406 
    407   // step 2
    408   const req_data = qs.parse(body)
    409   const uri = 'https://api.twitter.com/oauth/authenticate'
    410     + '?' + qs.stringify({oauth_token: req_data.oauth_token})
    411   // redirect the user to the authorize uri
    412 
    413   // step 3
    414   // after the user is redirected back to your server
    415   const auth_data = qs.parse(body)
    416     , oauth =
    417       { consumer_key: CONSUMER_KEY
    418       , consumer_secret: CONSUMER_SECRET
    419       , token: auth_data.oauth_token
    420       , token_secret: req_data.oauth_token_secret
    421       , verifier: auth_data.oauth_verifier
    422       }
    423     , url = 'https://api.twitter.com/oauth/access_token'
    424     ;
    425   request.post({url:url, oauth:oauth}, function (e, r, body) {
    426     // ready to make signed requests on behalf of the user
    427     const perm_data = qs.parse(body)
    428       , oauth =
    429         { consumer_key: CONSUMER_KEY
    430         , consumer_secret: CONSUMER_SECRET
    431         , token: perm_data.oauth_token
    432         , token_secret: perm_data.oauth_token_secret
    433         }
    434       , url = 'https://api.twitter.com/1.1/users/show.json'
    435       , qs =
    436         { screen_name: perm_data.screen_name
    437         , user_id: perm_data.user_id
    438         }
    439       ;
    440     request.get({url:url, oauth:oauth, qs:qs, json:true}, function (e, r, user) {
    441       console.log(user)
    442     })
    443   })
    444 })
    445 ```
    446 
    447 For [RSA-SHA1 signing](https://tools.ietf.org/html/rfc5849#section-3.4.3), make
    448 the following changes to the OAuth options object:
    449 * Pass `signature_method : 'RSA-SHA1'`
    450 * Instead of `consumer_secret`, specify a `private_key` string in
    451   [PEM format](http://how2ssl.com/articles/working_with_pem_files/)
    452 
    453 For [PLAINTEXT signing](http://oauth.net/core/1.0/#anchor22), make
    454 the following changes to the OAuth options object:
    455 * Pass `signature_method : 'PLAINTEXT'`
    456 
    457 To send OAuth parameters via query params or in a post body as described in The
    458 [Consumer Request Parameters](http://oauth.net/core/1.0/#consumer_req_param)
    459 section of the oauth1 spec:
    460 * Pass `transport_method : 'query'` or `transport_method : 'body'` in the OAuth
    461   options object.
    462 * `transport_method` defaults to `'header'`
    463 
    464 To use [Request Body Hash](https://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html) you can either
    465 * Manually generate the body hash and pass it as a string `body_hash: '...'`
    466 * Automatically generate the body hash by passing `body_hash: true`
    467 
    468 [back to top](#table-of-contents)
    469 
    470 
    471 ---
    472 
    473 
    474 ## Proxies
    475 
    476 If you specify a `proxy` option, then the request (and any subsequent
    477 redirects) will be sent via a connection to the proxy server.
    478 
    479 If your endpoint is an `https` url, and you are using a proxy, then
    480 request will send a `CONNECT` request to the proxy server *first*, and
    481 then use the supplied connection to connect to the endpoint.
    482 
    483 That is, first it will make a request like:
    484 
    485 ```
    486 HTTP/1.1 CONNECT endpoint-server.com:80
    487 Host: proxy-server.com
    488 User-Agent: whatever user agent you specify
    489 ```
    490 
    491 and then the proxy server make a TCP connection to `endpoint-server`
    492 on port `80`, and return a response that looks like:
    493 
    494 ```
    495 HTTP/1.1 200 OK
    496 ```
    497 
    498 At this point, the connection is left open, and the client is
    499 communicating directly with the `endpoint-server.com` machine.
    500 
    501 See [the wikipedia page on HTTP Tunneling](https://en.wikipedia.org/wiki/HTTP_tunnel)
    502 for more information.
    503 
    504 By default, when proxying `http` traffic, request will simply make a
    505 standard proxied `http` request. This is done by making the `url`
    506 section of the initial line of the request a fully qualified url to
    507 the endpoint.
    508 
    509 For example, it will make a single request that looks like:
    510 
    511 ```
    512 HTTP/1.1 GET http://endpoint-server.com/some-url
    513 Host: proxy-server.com
    514 Other-Headers: all go here
    515 
    516 request body or whatever
    517 ```
    518 
    519 Because a pure "http over http" tunnel offers no additional security
    520 or other features, it is generally simpler to go with a
    521 straightforward HTTP proxy in this case. However, if you would like
    522 to force a tunneling proxy, you may set the `tunnel` option to `true`.
    523 
    524 You can also make a standard proxied `http` request by explicitly setting
    525 `tunnel : false`, but **note that this will allow the proxy to see the traffic
    526 to/from the destination server**.
    527 
    528 If you are using a tunneling proxy, you may set the
    529 `proxyHeaderWhiteList` to share certain headers with the proxy.
    530 
    531 You can also set the `proxyHeaderExclusiveList` to share certain
    532 headers only with the proxy and not with destination host.
    533 
    534 By default, this set is:
    535 
    536 ```
    537 accept
    538 accept-charset
    539 accept-encoding
    540 accept-language
    541 accept-ranges
    542 cache-control
    543 content-encoding
    544 content-language
    545 content-length
    546 content-location
    547 content-md5
    548 content-range
    549 content-type
    550 connection
    551 date
    552 expect
    553 max-forwards
    554 pragma
    555 proxy-authorization
    556 referer
    557 te
    558 transfer-encoding
    559 user-agent
    560 via
    561 ```
    562 
    563 Note that, when using a tunneling proxy, the `proxy-authorization`
    564 header and any headers from custom `proxyHeaderExclusiveList` are
    565 *never* sent to the endpoint server, but only to the proxy server.
    566 
    567 
    568 ### Controlling proxy behaviour using environment variables
    569 
    570 The following environment variables are respected by `request`:
    571 
    572  * `HTTP_PROXY` / `http_proxy`
    573  * `HTTPS_PROXY` / `https_proxy`
    574  * `NO_PROXY` / `no_proxy`
    575 
    576 When `HTTP_PROXY` / `http_proxy` are set, they will be used to proxy non-SSL requests that do not have an explicit `proxy` configuration option present. Similarly, `HTTPS_PROXY` / `https_proxy` will be respected for SSL requests that do not have an explicit `proxy` configuration option. It is valid to define a proxy in one of the environment variables, but then override it for a specific request, using the `proxy` configuration option. Furthermore, the `proxy` configuration option can be explicitly set to false / null to opt out of proxying altogether for that request.
    577 
    578 `request` is also aware of the `NO_PROXY`/`no_proxy` environment variables. These variables provide a granular way to opt out of proxying, on a per-host basis. It should contain a comma separated list of hosts to opt out of proxying. It is also possible to opt of proxying when a particular destination port is used. Finally, the variable may be set to `*` to opt out of the implicit proxy configuration of the other environment variables.
    579 
    580 Here's some examples of valid `no_proxy` values:
    581 
    582  * `google.com` - don't proxy HTTP/HTTPS requests to Google.
    583  * `google.com:443` - don't proxy HTTPS requests to Google, but *do* proxy HTTP requests to Google.
    584  * `google.com:443, yahoo.com:80` - don't proxy HTTPS requests to Google, and don't proxy HTTP requests to Yahoo!
    585  * `*` - ignore `https_proxy`/`http_proxy` environment variables altogether.
    586 
    587 [back to top](#table-of-contents)
    588 
    589 
    590 ---
    591 
    592 
    593 ## UNIX Domain Sockets
    594 
    595 `request` supports making requests to [UNIX Domain Sockets](https://en.wikipedia.org/wiki/Unix_domain_socket). To make one, use the following URL scheme:
    596 
    597 ```js
    598 /* Pattern */ 'http://unix:SOCKET:PATH'
    599 /* Example */ request.get('http://unix:/absolute/path/to/unix.socket:/request/path')
    600 ```
    601 
    602 Note: The `SOCKET` path is assumed to be absolute to the root of the host file system.
    603 
    604 [back to top](#table-of-contents)
    605 
    606 
    607 ---
    608 
    609 
    610 ## TLS/SSL Protocol
    611 
    612 TLS/SSL Protocol options, such as `cert`, `key` and `passphrase`, can be
    613 set directly in `options` object, in the `agentOptions` property of the `options` object, or even in `https.globalAgent.options`. Keep in mind that, although `agentOptions` allows for a slightly wider range of configurations, the recommended way is via `options` object directly, as using `agentOptions` or `https.globalAgent.options` would not be applied in the same way in proxied environments (as data travels through a TLS connection instead of an http/https agent).
    614 
    615 ```js
    616 const fs = require('fs')
    617     , path = require('path')
    618     , certFile = path.resolve(__dirname, 'ssl/client.crt')
    619     , keyFile = path.resolve(__dirname, 'ssl/client.key')
    620     , caFile = path.resolve(__dirname, 'ssl/ca.cert.pem')
    621     , request = require('request');
    622 
    623 const options = {
    624     url: 'https://api.some-server.com/',
    625     cert: fs.readFileSync(certFile),
    626     key: fs.readFileSync(keyFile),
    627     passphrase: 'password',
    628     ca: fs.readFileSync(caFile)
    629 };
    630 
    631 request.get(options);
    632 ```
    633 
    634 ### Using `options.agentOptions`
    635 
    636 In the example below, we call an API that requires client side SSL certificate
    637 (in PEM format) with passphrase protected private key (in PEM format) and disable the SSLv3 protocol:
    638 
    639 ```js
    640 const fs = require('fs')
    641     , path = require('path')
    642     , certFile = path.resolve(__dirname, 'ssl/client.crt')
    643     , keyFile = path.resolve(__dirname, 'ssl/client.key')
    644     , request = require('request');
    645 
    646 const options = {
    647     url: 'https://api.some-server.com/',
    648     agentOptions: {
    649         cert: fs.readFileSync(certFile),
    650         key: fs.readFileSync(keyFile),
    651         // Or use `pfx` property replacing `cert` and `key` when using private key, certificate and CA certs in PFX or PKCS12 format:
    652         // pfx: fs.readFileSync(pfxFilePath),
    653         passphrase: 'password',
    654         securityOptions: 'SSL_OP_NO_SSLv3'
    655     }
    656 };
    657 
    658 request.get(options);
    659 ```
    660 
    661 It is able to force using SSLv3 only by specifying `secureProtocol`:
    662 
    663 ```js
    664 request.get({
    665     url: 'https://api.some-server.com/',
    666     agentOptions: {
    667         secureProtocol: 'SSLv3_method'
    668     }
    669 });
    670 ```
    671 
    672 It is possible to accept other certificates than those signed by generally allowed Certificate Authorities (CAs).
    673 This can be useful, for example,  when using self-signed certificates.
    674 To require a different root certificate, you can specify the signing CA by adding the contents of the CA's certificate file to the `agentOptions`.
    675 The certificate the domain presents must be signed by the root certificate specified:
    676 
    677 ```js
    678 request.get({
    679     url: 'https://api.some-server.com/',
    680     agentOptions: {
    681         ca: fs.readFileSync('ca.cert.pem')
    682     }
    683 });
    684 ```
    685 
    686 The `ca` value can be an array of certificates, in the event you have a private or internal corporate public-key infrastructure hierarchy. For example, if you want to connect to https://api.some-server.com which presents a key chain consisting of:
    687 1. its own public key, which is signed by:
    688 2. an intermediate "Corp Issuing Server", that is in turn signed by: 
    689 3. a root CA "Corp Root CA";
    690 
    691 you can configure your request as follows:
    692 
    693 ```js
    694 request.get({
    695     url: 'https://api.some-server.com/',
    696     agentOptions: {
    697         ca: [
    698           fs.readFileSync('Corp Issuing Server.pem'),
    699           fs.readFileSync('Corp Root CA.pem')
    700         ]
    701     }
    702 });
    703 ```
    704 
    705 [back to top](#table-of-contents)
    706 
    707 
    708 ---
    709 
    710 ## Support for HAR 1.2
    711 
    712 The `options.har` property will override the values: `url`, `method`, `qs`, `headers`, `form`, `formData`, `body`, `json`, as well as construct multipart data and read files from disk when `request.postData.params[].fileName` is present without a matching `value`.
    713 
    714 A validation step will check if the HAR Request format matches the latest spec (v1.2) and will skip parsing if not matching.
    715 
    716 ```js
    717   const request = require('request')
    718   request({
    719     // will be ignored
    720     method: 'GET',
    721     uri: 'http://www.google.com',
    722 
    723     // HTTP Archive Request Object
    724     har: {
    725       url: 'http://www.mockbin.com/har',
    726       method: 'POST',
    727       headers: [
    728         {
    729           name: 'content-type',
    730           value: 'application/x-www-form-urlencoded'
    731         }
    732       ],
    733       postData: {
    734         mimeType: 'application/x-www-form-urlencoded',
    735         params: [
    736           {
    737             name: 'foo',
    738             value: 'bar'
    739           },
    740           {
    741             name: 'hello',
    742             value: 'world'
    743           }
    744         ]
    745       }
    746     }
    747   })
    748 
    749   // a POST request will be sent to http://www.mockbin.com
    750   // with body an application/x-www-form-urlencoded body:
    751   // foo=bar&hello=world
    752 ```
    753 
    754 [back to top](#table-of-contents)
    755 
    756 
    757 ---
    758 
    759 ## request(options, callback)
    760 
    761 The first argument can be either a `url` or an `options` object. The only required option is `uri`; all others are optional.
    762 
    763 - `uri` || `url` - fully qualified uri or a parsed url object from `url.parse()`
    764 - `baseUrl` - fully qualified uri string used as the base url. Most useful with `request.defaults`, for example when you want to do many requests to the same domain. If `baseUrl` is `https://example.com/api/`, then requesting `/end/point?test=true` will fetch `https://example.com/api/end/point?test=true`. When `baseUrl` is given, `uri` must also be a string.
    765 - `method` - http method (default: `"GET"`)
    766 - `headers` - http headers (default: `{}`)
    767 
    768 ---
    769 
    770 - `qs` - object containing querystring values to be appended to the `uri`
    771 - `qsParseOptions` - object containing options to pass to the [qs.parse](https://github.com/hapijs/qs#parsing-objects) method. Alternatively pass options to the [querystring.parse](https://nodejs.org/docs/v0.12.0/api/querystring.html#querystring_querystring_parse_str_sep_eq_options) method using this format `{sep:';', eq:':', options:{}}`
    772 - `qsStringifyOptions` - object containing options to pass to the [qs.stringify](https://github.com/hapijs/qs#stringifying) method. Alternatively pass options to the  [querystring.stringify](https://nodejs.org/docs/v0.12.0/api/querystring.html#querystring_querystring_stringify_obj_sep_eq_options) method using this format `{sep:';', eq:':', options:{}}`. For example, to change the way arrays are converted to query strings using the `qs` module pass the `arrayFormat` option with one of `indices|brackets|repeat`
    773 - `useQuerystring` - if true, use `querystring` to stringify and parse
    774   querystrings, otherwise use `qs` (default: `false`). Set this option to
    775   `true` if you need arrays to be serialized as `foo=bar&foo=baz` instead of the
    776   default `foo[0]=bar&foo[1]=baz`.
    777 
    778 ---
    779 
    780 - `body` - entity body for PATCH, POST and PUT requests. Must be a `Buffer`, `String` or `ReadStream`. If `json` is `true`, then `body` must be a JSON-serializable object.
    781 - `form` - when passed an object or a querystring, this sets `body` to a querystring representation of value, and adds `Content-type: application/x-www-form-urlencoded` header. When passed no options, a `FormData` instance is returned (and is piped to request). See "Forms" section above.
    782 - `formData` - data to pass for a `multipart/form-data` request. See
    783   [Forms](#forms) section above.
    784 - `multipart` - array of objects which contain their own headers and `body`
    785   attributes. Sends a `multipart/related` request. See [Forms](#forms) section
    786   above.
    787   - Alternatively you can pass in an object `{chunked: false, data: []}` where
    788     `chunked` is used to specify whether the request is sent in
    789     [chunked transfer encoding](https://en.wikipedia.org/wiki/Chunked_transfer_encoding)
    790     In non-chunked requests, data items with body streams are not allowed.
    791 - `preambleCRLF` - append a newline/CRLF before the boundary of your `multipart/form-data` request.
    792 - `postambleCRLF` - append a newline/CRLF at the end of the boundary of your `multipart/form-data` request.
    793 - `json` - sets `body` to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as JSON.
    794 - `jsonReviver` - a [reviver function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) that will be passed to `JSON.parse()` when parsing a JSON response body.
    795 - `jsonReplacer` - a [replacer function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) that will be passed to `JSON.stringify()` when stringifying a JSON request body.
    796 
    797 ---
    798 
    799 - `auth` - a hash containing values `user` || `username`, `pass` || `password`, and `sendImmediately` (optional). See documentation above.
    800 - `oauth` - options for OAuth HMAC-SHA1 signing. See documentation above.
    801 - `hawk` - options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example).
    802 - `aws` - `object` containing AWS signing information. Should have the properties `key`, `secret`, and optionally `session` (note that this only works for services that require session as part of the canonical string). Also requires the property `bucket`, unless you’re specifying your `bucket` as part of the path, or the request doesn’t use a bucket (i.e. GET Services). If you want to use AWS sign version 4 use the parameter `sign_version` with value `4` otherwise the default is version 2. If you are using SigV4, you can also include a `service` property that specifies the service name. **Note:** you need to `npm install aws4` first.
    803 - `httpSignature` - options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options.
    804 
    805 ---
    806 
    807 - `followRedirect` - follow HTTP 3xx responses as redirects (default: `true`). This property can also be implemented as function which gets `response` object as a single argument and should return `true` if redirects should continue or `false` otherwise.
    808 - `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects (default: `false`)
    809 - `followOriginalHttpMethod` - by default we redirect to HTTP method GET. you can enable this property to redirect to the original HTTP method (default: `false`)
    810 - `maxRedirects` - the maximum number of redirects to follow (default: `10`)
    811 - `removeRefererHeader` - removes the referer header when a redirect happens (default: `false`). **Note:** if true, referer header set in the initial request is preserved during redirect chain.
    812 
    813 ---
    814 
    815 - `encoding` - encoding to be used on `setEncoding` of response data. If `null`, the `body` is returned as a `Buffer`. Anything else **(including the default value of `undefined`)** will be passed as the [encoding](http://nodejs.org/api/buffer.html#buffer_buffer) parameter to `toString()` (meaning this is effectively `utf8` by default). (**Note:** if you expect binary data, you should set `encoding: null`.)
    816 - `gzip` - if `true`, add an `Accept-Encoding` header to request compressed content encodings from the server (if not already present) and decode supported content encodings in the response. **Note:** Automatic decoding of the response content is performed on the body data returned through `request` (both through the `request` stream and passed to the callback function) but is not performed on the `response` stream (available from the `response` event) which is the unmodified `http.IncomingMessage` object which may contain compressed data. See example below.
    817 - `jar` - if `true`, remember cookies for future use (or define your custom cookie jar; see examples section)
    818 
    819 ---
    820 
    821 - `agent` - `http(s).Agent` instance to use
    822 - `agentClass` - alternatively specify your agent's class name
    823 - `agentOptions` - and pass its options. **Note:** for HTTPS see [tls API doc for TLS/SSL options](http://nodejs.org/api/tls.html#tls_tls_connect_options_callback) and the [documentation above](#using-optionsagentoptions).
    824 - `forever` - set to `true` to use the [forever-agent](https://github.com/request/forever-agent) **Note:** Defaults to `http(s).Agent({keepAlive:true})` in node 0.12+
    825 - `pool` - an object describing which agents to use for the request. If this option is omitted the request will use the global agent (as long as your options allow for it). Otherwise, request will search the pool for your custom agent. If no custom agent is found, a new agent will be created and added to the pool. **Note:** `pool` is used only when the `agent` option is not specified.
    826   - A `maxSockets` property can also be provided on the `pool` object to set the max number of sockets for all agents created (ex: `pool: {maxSockets: Infinity}`).
    827   - Note that if you are sending multiple requests in a loop and creating
    828     multiple new `pool` objects, `maxSockets` will not work as intended. To
    829     work around this, either use [`request.defaults`](#requestdefaultsoptions)
    830     with your pool options or create the pool object with the `maxSockets`
    831     property outside of the loop.
    832 - `timeout` - integer containing number of milliseconds, controls two timeouts.
    833   - **Read timeout**: Time to wait for a server to send response headers (and start the response body) before aborting the request.
    834   - **Connection timeout**: Sets the socket to timeout after `timeout` milliseconds of inactivity. Note that increasing the timeout beyond the OS-wide TCP connection timeout will not have any effect ([the default in Linux can be anywhere from 20-120 seconds][linux-timeout])
    835 
    836 [linux-timeout]: http://www.sekuda.com/overriding_the_default_linux_kernel_20_second_tcp_socket_connect_timeout
    837 
    838 ---
    839 
    840 - `localAddress` - local interface to bind for network connections.
    841 - `proxy` - an HTTP proxy to be used. Supports proxy Auth with Basic Auth, identical to support for the `url` parameter (by embedding the auth info in the `uri`)
    842 - `strictSSL` - if `true`, requires SSL certificates be valid. **Note:** to use your own certificate authority, you need to specify an agent that was created with that CA as an option.
    843 - `tunnel` - controls the behavior of
    844   [HTTP `CONNECT` tunneling](https://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_tunneling)
    845   as follows:
    846    - `undefined` (default) - `true` if the destination is `https`, `false` otherwise
    847    - `true` - always tunnel to the destination by making a `CONNECT` request to
    848      the proxy
    849    - `false` - request the destination as a `GET` request.
    850 - `proxyHeaderWhiteList` - a whitelist of headers to send to a
    851   tunneling proxy.
    852 - `proxyHeaderExclusiveList` - a whitelist of headers to send
    853   exclusively to a tunneling proxy and not to destination.
    854 
    855 ---
    856 
    857 - `time` - if `true`, the request-response cycle (including all redirects) is timed at millisecond resolution. When set, the following properties are added to the response object:
    858   - `elapsedTime` Duration of the entire request/response in milliseconds (*deprecated*).
    859   - `responseStartTime` Timestamp when the response began (in Unix Epoch milliseconds) (*deprecated*).
    860   - `timingStart` Timestamp of the start of the request (in Unix Epoch milliseconds).
    861   - `timings` Contains event timestamps in millisecond resolution relative to `timingStart`. If there were redirects, the properties reflect the timings of the final request in the redirect chain:
    862     - `socket` Relative timestamp when the [`http`](https://nodejs.org/api/http.html#http_event_socket) module's `socket` event fires. This happens when the socket is assigned to the request.
    863     - `lookup` Relative timestamp when the [`net`](https://nodejs.org/api/net.html#net_event_lookup) module's `lookup` event fires. This happens when the DNS has been resolved.
    864     - `connect`: Relative timestamp when the [`net`](https://nodejs.org/api/net.html#net_event_connect) module's `connect` event fires. This happens when the server acknowledges the TCP connection.
    865     - `response`: Relative timestamp when the [`http`](https://nodejs.org/api/http.html#http_event_response) module's `response` event fires. This happens when the first bytes are received from the server.
    866     - `end`: Relative timestamp when the last bytes of the response are received.
    867   - `timingPhases` Contains the durations of each request phase. If there were redirects, the properties reflect the timings of the final request in the redirect chain:
    868     - `wait`: Duration of socket initialization (`timings.socket`)
    869     - `dns`: Duration of DNS lookup (`timings.lookup` - `timings.socket`)
    870     - `tcp`: Duration of TCP connection (`timings.connect` - `timings.socket`)
    871     - `firstByte`: Duration of HTTP server response (`timings.response` - `timings.connect`)
    872     - `download`: Duration of HTTP download (`timings.end` - `timings.response`)
    873     - `total`: Duration entire HTTP round-trip (`timings.end`)
    874 
    875 - `har` - a [HAR 1.2 Request Object](http://www.softwareishard.com/blog/har-12-spec/#request), will be processed from HAR format into options overwriting matching values *(see the [HAR 1.2 section](#support-for-har-12) for details)*
    876 - `callback` - alternatively pass the request's callback in the options object
    877 
    878 The callback argument gets 3 arguments:
    879 
    880 1. An `error` when applicable (usually from [`http.ClientRequest`](http://nodejs.org/api/http.html#http_class_http_clientrequest) object)
    881 2. An [`http.IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage) object (Response object)
    882 3. The third is the `response` body (`String` or `Buffer`, or JSON object if the `json` option is supplied)
    883 
    884 [back to top](#table-of-contents)
    885 
    886 
    887 ---
    888 
    889 ## Convenience methods
    890 
    891 There are also shorthand methods for different HTTP METHODs and some other conveniences.
    892 
    893 
    894 ### request.defaults(options)
    895 
    896 This method **returns a wrapper** around the normal request API that defaults
    897 to whatever options you pass to it.
    898 
    899 **Note:** `request.defaults()` **does not** modify the global request API;
    900 instead, it **returns a wrapper** that has your default settings applied to it.
    901 
    902 **Note:** You can call `.defaults()` on the wrapper that is returned from
    903 `request.defaults` to add/override defaults that were previously defaulted.
    904 
    905 For example:
    906 ```js
    907 //requests using baseRequest() will set the 'x-token' header
    908 const baseRequest = request.defaults({
    909   headers: {'x-token': 'my-token'}
    910 })
    911 
    912 //requests using specialRequest() will include the 'x-token' header set in
    913 //baseRequest and will also include the 'special' header
    914 const specialRequest = baseRequest.defaults({
    915   headers: {special: 'special value'}
    916 })
    917 ```
    918 
    919 ### request.METHOD()
    920 
    921 These HTTP method convenience functions act just like `request()` but with a default method already set for you:
    922 
    923 - *request.get()*: Defaults to `method: "GET"`.
    924 - *request.post()*: Defaults to `method: "POST"`.
    925 - *request.put()*: Defaults to `method: "PUT"`.
    926 - *request.patch()*: Defaults to `method: "PATCH"`.
    927 - *request.del() / request.delete()*: Defaults to `method: "DELETE"`.
    928 - *request.head()*: Defaults to `method: "HEAD"`.
    929 - *request.options()*: Defaults to `method: "OPTIONS"`.
    930 
    931 ### request.cookie()
    932 
    933 Function that creates a new cookie.
    934 
    935 ```js
    936 request.cookie('key1=value1')
    937 ```
    938 ### request.jar()
    939 
    940 Function that creates a new cookie jar.
    941 
    942 ```js
    943 request.jar()
    944 ```
    945 
    946 ### response.caseless.get('header-name')
    947 
    948 Function that returns the specified response header field using a [case-insensitive match](https://tools.ietf.org/html/rfc7230#section-3.2)
    949 
    950 ```js
    951 request('http://www.google.com', function (error, response, body) {
    952   // print the Content-Type header even if the server returned it as 'content-type' (lowercase)
    953   console.log('Content-Type is:', response.caseless.get('Content-Type')); 
    954 });
    955 ```
    956 
    957 [back to top](#table-of-contents)
    958 
    959 
    960 ---
    961 
    962 
    963 ## Debugging
    964 
    965 There are at least three ways to debug the operation of `request`:
    966 
    967 1. Launch the node process like `NODE_DEBUG=request node script.js`
    968    (`lib,request,otherlib` works too).
    969 
    970 2. Set `require('request').debug = true` at any time (this does the same thing
    971    as #1).
    972 
    973 3. Use the [request-debug module](https://github.com/request/request-debug) to
    974    view request and response headers and bodies.
    975 
    976 [back to top](#table-of-contents)
    977 
    978 
    979 ---
    980 
    981 ## Timeouts
    982 
    983 Most requests to external servers should have a timeout attached, in case the
    984 server is not responding in a timely manner. Without a timeout, your code may
    985 have a socket open/consume resources for minutes or more.
    986 
    987 There are two main types of timeouts: **connection timeouts** and **read
    988 timeouts**. A connect timeout occurs if the timeout is hit while your client is
    989 attempting to establish a connection to a remote machine (corresponding to the
    990 [connect() call][connect] on the socket). A read timeout occurs any time the
    991 server is too slow to send back a part of the response.
    992 
    993 These two situations have widely different implications for what went wrong
    994 with the request, so it's useful to be able to distinguish them. You can detect
    995 timeout errors by checking `err.code` for an 'ETIMEDOUT' value. Further, you
    996 can detect whether the timeout was a connection timeout by checking if the
    997 `err.connect` property is set to `true`.
    998 
    999 ```js
   1000 request.get('http://10.255.255.1', {timeout: 1500}, function(err) {
   1001     console.log(err.code === 'ETIMEDOUT');
   1002     // Set to `true` if the timeout was a connection timeout, `false` or
   1003     // `undefined` otherwise.
   1004     console.log(err.connect === true);
   1005     process.exit(0);
   1006 });
   1007 ```
   1008 
   1009 [connect]: http://linux.die.net/man/2/connect
   1010 
   1011 ## Examples:
   1012 
   1013 ```js
   1014   const request = require('request')
   1015     , rand = Math.floor(Math.random()*100000000).toString()
   1016     ;
   1017   request(
   1018     { method: 'PUT'
   1019     , uri: 'http://mikeal.iriscouch.com/testjs/' + rand
   1020     , multipart:
   1021       [ { 'content-type': 'application/json'
   1022         ,  body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})
   1023         }
   1024       , { body: 'I am an attachment' }
   1025       ]
   1026     }
   1027   , function (error, response, body) {
   1028       if(response.statusCode == 201){
   1029         console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)
   1030       } else {
   1031         console.log('error: '+ response.statusCode)
   1032         console.log(body)
   1033       }
   1034     }
   1035   )
   1036 ```
   1037 
   1038 For backwards-compatibility, response compression is not supported by default.
   1039 To accept gzip-compressed responses, set the `gzip` option to `true`. Note
   1040 that the body data passed through `request` is automatically decompressed
   1041 while the response object is unmodified and will contain compressed data if
   1042 the server sent a compressed response.
   1043 
   1044 ```js
   1045   const request = require('request')
   1046   request(
   1047     { method: 'GET'
   1048     , uri: 'http://www.google.com'
   1049     , gzip: true
   1050     }
   1051   , function (error, response, body) {
   1052       // body is the decompressed response body
   1053       console.log('server encoded the data as: ' + (response.headers['content-encoding'] || 'identity'))
   1054       console.log('the decoded data is: ' + body)
   1055     }
   1056   )
   1057   .on('data', function(data) {
   1058     // decompressed data as it is received
   1059     console.log('decoded chunk: ' + data)
   1060   })
   1061   .on('response', function(response) {
   1062     // unmodified http.IncomingMessage object
   1063     response.on('data', function(data) {
   1064       // compressed data as it is received
   1065       console.log('received ' + data.length + ' bytes of compressed data')
   1066     })
   1067   })
   1068 ```
   1069 
   1070 Cookies are disabled by default (else, they would be used in subsequent requests). To enable cookies, set `jar` to `true` (either in `defaults` or `options`).
   1071 
   1072 ```js
   1073 const request = request.defaults({jar: true})
   1074 request('http://www.google.com', function () {
   1075   request('http://images.google.com')
   1076 })
   1077 ```
   1078 
   1079 To use a custom cookie jar (instead of `request`’s global cookie jar), set `jar` to an instance of `request.jar()` (either in `defaults` or `options`)
   1080 
   1081 ```js
   1082 const j = request.jar()
   1083 const request = request.defaults({jar:j})
   1084 request('http://www.google.com', function () {
   1085   request('http://images.google.com')
   1086 })
   1087 ```
   1088 
   1089 OR
   1090 
   1091 ```js
   1092 const j = request.jar();
   1093 const cookie = request.cookie('key1=value1');
   1094 const url = 'http://www.google.com';
   1095 j.setCookie(cookie, url);
   1096 request({url: url, jar: j}, function () {
   1097   request('http://images.google.com')
   1098 })
   1099 ```
   1100 
   1101 To use a custom cookie store (such as a
   1102 [`FileCookieStore`](https://github.com/mitsuru/tough-cookie-filestore)
   1103 which supports saving to and restoring from JSON files), pass it as a parameter
   1104 to `request.jar()`:
   1105 
   1106 ```js
   1107 const FileCookieStore = require('tough-cookie-filestore');
   1108 // NOTE - currently the 'cookies.json' file must already exist!
   1109 const j = request.jar(new FileCookieStore('cookies.json'));
   1110 request = request.defaults({ jar : j })
   1111 request('http://www.google.com', function() {
   1112   request('http://images.google.com')
   1113 })
   1114 ```
   1115 
   1116 The cookie store must be a
   1117 [`tough-cookie`](https://github.com/SalesforceEng/tough-cookie)
   1118 store and it must support synchronous operations; see the
   1119 [`CookieStore` API docs](https://github.com/SalesforceEng/tough-cookie#api)
   1120 for details.
   1121 
   1122 To inspect your cookie jar after a request:
   1123 
   1124 ```js
   1125 const j = request.jar()
   1126 request({url: 'http://www.google.com', jar: j}, function () {
   1127   const cookie_string = j.getCookieString(url); // "key1=value1; key2=value2; ..."
   1128   const cookies = j.getCookies(url);
   1129   // [{key: 'key1', value: 'value1', domain: "www.google.com", ...}, ...]
   1130 })
   1131 ```
   1132 
   1133 [back to top](#table-of-contents)