got 3.0.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +73 -41
  2. package/package.json +6 -7
  3. package/readme.md +41 -20
package/index.js CHANGED
@@ -13,7 +13,7 @@ var readAllStream = require('read-all-stream');
13
13
  var timedOut = require('timed-out');
14
14
  var prependHttp = require('prepend-http');
15
15
  var lowercaseKeys = require('lowercase-keys');
16
- var statuses = require('statuses');
16
+ var isRedirect = require('is-redirect');
17
17
  var NestedErrorStacks = require('nested-error-stacks');
18
18
 
19
19
  function GotError(message, nested) {
@@ -34,18 +34,36 @@ function got(url, opts, cb) {
34
34
  opts = {};
35
35
  }
36
36
 
37
- opts = objectAssign({}, opts);
37
+ opts = objectAssign(
38
+ {
39
+ protocol: 'http:'
40
+ },
41
+ typeof url === 'string' ? urlLib.parse(prependHttp(url)) : url,
42
+ opts
43
+ );
38
44
 
39
45
  opts.headers = objectAssign({
40
46
  'user-agent': 'https://github.com/sindresorhus/got',
41
47
  'accept-encoding': 'gzip,deflate'
42
48
  }, lowercaseKeys(opts.headers));
43
49
 
50
+ if (opts.pathname) {
51
+ opts.path = opts.pathname;
52
+ }
53
+
54
+ if (opts.query) {
55
+ if (typeof opts.query !== 'string') {
56
+ opts.query = querystring.stringify(opts.query);
57
+ }
58
+
59
+ opts.path = opts.pathname + '?' + opts.query;
60
+ delete opts.query;
61
+ }
62
+
44
63
  var encoding = opts.encoding;
45
64
  var body = opts.body;
46
65
  var json = opts.json;
47
66
  var timeout = opts.timeout;
48
- var query = opts.query;
49
67
  var proxy;
50
68
  var redirectCount = 0;
51
69
 
@@ -53,10 +71,22 @@ function got(url, opts, cb) {
53
71
  delete opts.body;
54
72
  delete opts.json;
55
73
  delete opts.timeout;
56
- delete opts.query;
74
+
75
+ if (json) {
76
+ opts.headers.accept = opts.headers.accept || 'application/json';
77
+ }
57
78
 
58
79
  if (body) {
80
+ if (typeof body !== 'string' && !Buffer.isBuffer(body) && !isStream.readable(body)) {
81
+ throw new GotError('options.body must be a ReadableStream, string or Buffer');
82
+ }
83
+
59
84
  opts.method = opts.method || 'POST';
85
+
86
+ if (!opts.headers['content-length'] && !opts.headers['transfer-encoding'] && !isStream.readable(body)) {
87
+ var length = typeof body === 'string' ? Buffer.byteLength(body) : body.length;
88
+ opts.headers['content-length'] = length;
89
+ }
60
90
  }
61
91
 
62
92
  opts.method = opts.method || 'GET';
@@ -67,8 +97,8 @@ function got(url, opts, cb) {
67
97
  proxy = duplexify();
68
98
 
69
99
  // forward errors on the stream
70
- cb = function (err) {
71
- proxy.emit('error', err);
100
+ cb = function (err, data, response) {
101
+ proxy.emit('error', err, data, response);
72
102
  };
73
103
  }
74
104
 
@@ -76,21 +106,13 @@ function got(url, opts, cb) {
76
106
  throw new GotError('got can not be used as stream when options.json is used');
77
107
  }
78
108
 
79
- if (body && !(typeof body === 'string' || Buffer.isBuffer(body) || isStream.readable(body))) {
80
- throw new GotError('options.body must be a ReadableStream, string or Buffer');
81
- }
82
-
83
- function get(url, opts, cb) {
84
- var parsedUrl = typeof url === 'string' ? urlLib.parse(prependHttp(url)) : url;
85
- var fn = parsedUrl.protocol === 'https:' ? https : http;
86
- var arg = objectAssign({}, parsedUrl, opts);
87
-
88
- url = typeof url === 'string' ? prependHttp(url) : urlLib.format(url);
109
+ function get(opts, cb) {
110
+ var fn = opts.protocol === 'https:' ? https : http;
111
+ var url = urlLib.format(opts);
89
112
 
90
- if (arg.agent === undefined) {
91
- arg.agent = infinityAgent[fn === https ? 'https' : 'http'].globalAgent;
113
+ if (opts.agent === undefined) {
114
+ opts.agent = infinityAgent[fn === https ? 'https' : 'http'].globalAgent;
92
115
 
93
- // TODO: remove this when Node 0.10 will be deprecated
94
116
  if (process.version.indexOf('v0.10') === 0 && fn === https && (
95
117
  typeof opts.ca !== 'undefined' ||
96
118
  typeof opts.cert !== 'undefined' ||
@@ -99,52 +121,58 @@ function got(url, opts, cb) {
99
121
  typeof opts.passphrase !== 'undefined' ||
100
122
  typeof opts.pfx !== 'undefined' ||
101
123
  typeof opts.rejectUnauthorized !== 'undefined')) {
102
- arg.agent = new (infinityAgent.https.Agent)(opts);
124
+ opts.agent = new infinityAgent.https.Agent({
125
+ ca: opts.ca,
126
+ cert: opts.cert,
127
+ ciphers: opts.ciphers,
128
+ key: opts.key,
129
+ passphrase: opts.passphrase,
130
+ pfx: opts.pfx,
131
+ rejectUnauthorized: opts.rejectUnauthorized
132
+ });
103
133
  }
104
134
  }
105
135
 
106
- if (query) {
107
- arg.path = (arg.path ? arg.path.split('?')[0] : '') + '?' + (typeof query === 'string' ? query : querystring.stringify(query));
108
- query = undefined;
109
- }
110
-
111
- var req = fn.request(arg, function (response) {
136
+ var req = fn.request(opts, function (response) {
112
137
  var statusCode = response.statusCode;
113
138
  var res = response;
114
139
 
115
- if (proxy) {
116
- proxy.emit('response', res);
117
- }
118
-
119
140
  // auto-redirect only for GET and HEAD methods
120
- if (statuses.redirect[statusCode] && 'location' in res.headers && (opts.method === 'GET' || opts.method === 'HEAD')) {
121
- res.resume(); // Discard response
141
+ if (isRedirect(statusCode) && 'location' in res.headers && (opts.method === 'GET' || opts.method === 'HEAD')) {
142
+ // discard response
143
+ res.resume();
122
144
 
123
145
  if (++redirectCount > 10) {
124
146
  cb(new GotError('Redirected 10 times. Aborting.'), undefined, res);
125
147
  return;
126
148
  }
127
149
 
128
- delete opts.host;
129
- delete opts.hostname;
130
- delete opts.port;
131
- delete opts.path;
150
+ var redirectUrl = urlLib.resolve(url, res.headers.location);
151
+ var redirectOpts = objectAssign({}, opts, urlLib.parse(redirectUrl));
152
+
153
+ if (opts.agent === infinityAgent.http.globalAgent && redirectOpts.protocol === 'https:' && opts.protocol === 'http:') {
154
+ redirectOpts.agent = undefined;
155
+ }
132
156
 
133
157
  if (proxy) {
134
- proxy.emit('redirect', res, opts);
158
+ proxy.emit('redirect', res, redirectOpts);
135
159
  }
136
160
 
137
- get(urlLib.resolve(url, res.headers.location), opts, cb);
161
+ get(redirectOpts, cb);
138
162
  return;
139
163
  }
140
164
 
165
+ if (proxy) {
166
+ proxy.emit('response', res);
167
+ }
168
+
141
169
  if (['gzip', 'deflate'].indexOf(res.headers['content-encoding']) !== -1) {
142
170
  res = res.pipe(zlib.createUnzip());
143
171
  }
144
172
 
145
173
  if (statusCode < 200 || statusCode > 299) {
146
174
  readAllStream(res, encoding, function (err, data) {
147
- err = new GotError(opts.method + ' ' + url + ' response code is ' + statusCode + ' (' + statuses[statusCode] + ')', err);
175
+ err = new GotError(opts.method + ' ' + url + ' response code is ' + statusCode + ' (' + http.STATUS_CODES[statusCode] + ')', err);
148
176
  err.code = statusCode;
149
177
 
150
178
  if (data && json) {
@@ -157,6 +185,7 @@ function got(url, opts, cb) {
157
185
 
158
186
  cb(err, data, response);
159
187
  });
188
+
160
189
  return;
161
190
  }
162
191
 
@@ -169,7 +198,9 @@ function got(url, opts, cb) {
169
198
  readAllStream(res, encoding, function (err, data) {
170
199
  if (err) {
171
200
  err = new GotError('Reading ' + url + ' response failed', err);
172
- } else if (json) {
201
+ } else if (json && statusCode !== 204) {
202
+ // only parse json if the option is enabled, and the response
203
+ // is not a 204 (empty reponse)
173
204
  try {
174
205
  data = JSON.parse(data);
175
206
  } catch (e) {
@@ -219,7 +250,8 @@ function got(url, opts, cb) {
219
250
  req.end();
220
251
  }
221
252
 
222
- get(url, opts, cb);
253
+ get(opts, cb);
254
+
223
255
  return proxy;
224
256
  }
225
257
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "got",
3
- "version": "3.0.0",
3
+ "version": "3.3.1",
4
4
  "description": "Simplified HTTP/HTTPS requests",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/got",
@@ -20,7 +20,7 @@
20
20
  "node": ">=0.10.0"
21
21
  },
22
22
  "scripts": {
23
- "test": "tape test/test-*.js | tap-dot",
23
+ "test": "tap test/test-*.js",
24
24
  "coverage": "istanbul cover tape --report html -- test/test-*.js"
25
25
  },
26
26
  "files": [
@@ -44,20 +44,19 @@
44
44
  "dependencies": {
45
45
  "duplexify": "^3.2.0",
46
46
  "infinity-agent": "^2.0.0",
47
+ "is-redirect": "^1.0.0",
47
48
  "is-stream": "^1.0.0",
48
49
  "lowercase-keys": "^1.0.0",
49
50
  "nested-error-stacks": "^1.0.0",
50
- "object-assign": "^2.0.0",
51
+ "object-assign": "^3.0.0",
51
52
  "prepend-http": "^1.0.0",
52
- "read-all-stream": "^2.0.0",
53
- "statuses": "^1.2.1",
53
+ "read-all-stream": "^3.0.0",
54
54
  "timed-out": "^2.0.0"
55
55
  },
56
56
  "devDependencies": {
57
57
  "from2-array": "0.0.3",
58
58
  "istanbul": "^0.3.13",
59
59
  "pem": "^1.4.4",
60
- "tap-dot": "^1.0.0",
61
- "tape": "^3.5.0"
60
+ "tap": "^1.0.0"
62
61
  }
63
62
  }
package/readme.md CHANGED
@@ -1,7 +1,15 @@
1
- # got [![Build Status](https://travis-ci.org/sindresorhus/got.svg?branch=master)](https://travis-ci.org/sindresorhus/got)
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>
2
8
 
3
9
  > Simplified HTTP/HTTPS requests
4
10
 
11
+ [![Build Status](https://travis-ci.org/sindresorhus/got.svg?branch=master)](https://travis-ci.org/sindresorhus/got)
12
+
5
13
  A nicer interface to the built-in [`http`](http://nodejs.org/api/http.html) module.
6
14
 
7
15
  It supports following redirects, streams, automagically handling gzip/deflate and some convenience options.
@@ -44,10 +52,12 @@ It's a `GET` request by default, but can be changed in `options`.
44
52
  ##### url
45
53
 
46
54
  *Required*
47
- Type: `string`, `Object`
55
+ Type: `string`, `object`
48
56
 
49
57
  The URL to request or bare [http.request options](https://nodejs.org/api/http.html#http_http_request_options_callback) object.
50
58
 
59
+ Properties from `options` will override properties in the parsed `url`.
60
+
51
61
  ##### options
52
62
 
53
63
  Type: `object`
@@ -58,31 +68,33 @@ Any of the [`http.request`](http://nodejs.org/api/http.html#http_http_request_op
58
68
 
59
69
  Type: `string`, `Buffer`, `ReadableStream`
60
70
 
61
- _This option and stream mode are mutually exclusive._
71
+ *This option and stream mode are mutually exclusive.*
62
72
 
63
- Body, that will be sent with `POST` request. If present in `options` and `options.method` is not set - `options.method` will be set to `POST`.
73
+ Body that will be sent with a `POST` request. If present in `options` and `options.method` is not set - `options.method` will be set to `POST`.
74
+
75
+ If `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.
64
76
 
65
77
  ###### encoding
66
78
 
67
79
  Type: `string`, `null`
68
80
  Default: `'utf8'`
69
81
 
70
- Encoding to be used on `setEncoding` of the response data. If null, the body is returned as a Buffer.
82
+ Encoding to be used on `setEncoding` of the response data. If `null`, the body is returned as a Buffer.
71
83
 
72
84
  ###### json
73
85
 
74
- Type: `Boolean`
86
+ Type: `boolean`
75
87
  Default: `false`
76
88
 
77
- _This option and stream mode are mutually exclusive._
89
+ *This option and stream mode are mutually exclusive.*
78
90
 
79
- If enabled, response body will be parsed with `JSON.parse`.
91
+ Parse response body with `JSON.parse` and set `accept` header to `application/json`.
80
92
 
81
93
  ###### query
82
94
 
83
- Type: `string`, `Object`
95
+ Type: `string`, `object`
84
96
 
85
- Query string object, that will be added to request url. This will override query string in `url`.
97
+ Query string object that will be added to the request URL. This will override the query string in `url`.
86
98
 
87
99
  ###### timeout
88
100
 
@@ -94,13 +106,13 @@ Milliseconds after which the request will be aborted and an error event with `ET
94
106
 
95
107
  [http.Agent](http://nodejs.org/api/http.html#http_class_http_agent) instance.
96
108
 
97
- If `undefined` - [`infinity-agent`](https://github.com/floatdrop/infinity-agent) will be used to backport Agent class from Node core.
109
+ If `undefined` - [`infinity-agent`](https://github.com/floatdrop/infinity-agent) will be used to backport Agent class from Node.js core.
98
110
 
99
- To use default [globalAgent](http://nodejs.org/api/http.html#http_http_globalagent) just pass `null` to this option.
111
+ To use default [globalAgent](http://nodejs.org/api/http.html#http_http_globalagent) just pass `null`.
100
112
 
101
- ##### callback(err, data, response)
113
+ ##### callback(error, data, response)
102
114
 
103
- ###### err
115
+ ###### error
104
116
 
105
117
  `Error` object with HTTP status code as `code` property.
106
118
 
@@ -112,17 +124,19 @@ The data you requested.
112
124
 
113
125
  The [response object](http://nodejs.org/api/http.html#http_http_incomingmessage).
114
126
 
115
-
116
127
  When in stream mode, you can listen for events:
117
128
 
118
129
  ##### .on('response', response)
119
130
 
120
- `response` event to get the response object.
131
+ `response` event to get the response object of the final request.
121
132
 
122
- ##### .on('redirect', response, nextOpts)
133
+ ##### .on('redirect', response, nextOptions)
123
134
 
124
- `redirect` event to get the response object of redirect. Second argument is options for next request to redirect location.
135
+ `redirect` event to get the response object of a redirect. Second argument is options for the next request to the redirect location.
125
136
 
137
+ ##### .on('error', error, body, response)
138
+
139
+ `error` event emitted in case of protocol error (like `ENOTFOUND` etc.) or status error (4xx or 5xx). Second argument is body of server response in case of status error. Third argument is response object.
126
140
 
127
141
  ###### response
128
142
 
@@ -173,8 +187,15 @@ got('todomvc.com', {
173
187
 
174
188
  ## Related
175
189
 
176
- * [`gh-got`](https://github.com/sindresorhus/gh-got) - Convenience wrapper for interacting with the GitHub API
177
- * [`got-promise`](https://github.com/floatdrop/got-promise) - Promise wrapper
190
+ - [gh-got](https://github.com/sindresorhus/gh-got) - Convenience wrapper for interacting with the GitHub API
191
+ - [got-promise](https://github.com/floatdrop/got-promise) - Promise wrapper
192
+
193
+
194
+ ## Created by
195
+
196
+ [![Sindre Sorhus](https://avatars.githubusercontent.com/u/170270?v=3&s=100)](http://sindresorhus.com) | [![Vsevolod Strukchinsky](https://avatars.githubusercontent.com/u/365089?v=3&s=100)](https://github.com/floatdrop)
197
+ ---|---
198
+ [Sindre Sorhus](http://sindresorhus.com) | [Vsevolod Strukchinsky](https://github.com/floatdrop)
178
199
 
179
200
 
180
201
  ## License