superagent 3.8.1 → 4.0.0-beta.5
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.
- package/.travis.yml +5 -2
- package/.zuul.yml +5 -2
- package/History.md +35 -0
- package/Makefile +10 -1
- package/Readme.md +10 -6
- package/docs/index.md +133 -69
- package/docs/test.html +6 -6
- package/dump.js +1 -0
- package/lib/agent-base.js +5 -5
- package/lib/client.js +80 -79
- package/lib/node/http2wrapper.js +188 -0
- package/lib/node/index.js +189 -52
- package/lib/node/parsers/text.js +1 -1
- package/lib/node/parsers/urlencoded.js +1 -1
- package/lib/node/response.js +1 -1
- package/lib/node/unzip.js +2 -2
- package/lib/request-base.js +29 -28
- package/lib/response-base.js +8 -6
- package/lib/utils.js +16 -22
- package/package.json +18 -15
- package/superagent.js +231 -209
- package/test.js +7 -0
- package/yarn.lock +1774 -1080
package/.travis.yml
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
sudo: false
|
|
2
2
|
language: node_js
|
|
3
3
|
node_js:
|
|
4
|
+
- "10"
|
|
4
5
|
- "8"
|
|
5
6
|
- "6"
|
|
6
|
-
- "4"
|
|
7
7
|
|
|
8
8
|
env:
|
|
9
9
|
global:
|
|
@@ -12,5 +12,8 @@ env:
|
|
|
12
12
|
|
|
13
13
|
matrix:
|
|
14
14
|
include:
|
|
15
|
-
- node_js: "
|
|
15
|
+
- node_js: "9"
|
|
16
16
|
env: BROWSER=1
|
|
17
|
+
include:
|
|
18
|
+
- node_js: "10"
|
|
19
|
+
env: HTTP2_TEST=1
|
package/.zuul.yml
CHANGED
package/History.md
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
# 4.0.0
|
|
2
|
+
|
|
3
|
+
## Breaking changes
|
|
4
|
+
|
|
5
|
+
* Node.js v4 has reached it's end of life, so we no longer support it. It's v6+ or later. We recommend Node.js 10.
|
|
6
|
+
* We now use ES6 in the browser code, too.
|
|
7
|
+
* If you're using Browserify or Webpack to package code for Internet Explorer, you will also have to use Babel.
|
|
8
|
+
* The pre-built node_modules/superagent.js is still ES5-compatible.
|
|
9
|
+
* `.end(…)` returns `undefined` instead of the request. If you need the request object after calling `.end()` (and you probably don't), save it in a variable and call `request.end(…)`. Consider not using `.end()` at all, and migrating to promises by calling `.then()` instead.
|
|
10
|
+
* In Node, responses with unknown MIME type are buffered by default. To get old behavior, if you use custom *unbuffered* parsers, add `.buffer(false)` to requests or set `superagent.buffer[yourMimeType] = false`.
|
|
11
|
+
* Invalid uses of `.pipe()` throw.
|
|
12
|
+
|
|
13
|
+
## Minor changes
|
|
14
|
+
|
|
15
|
+
* Throw if `req.abort().end()` is called
|
|
16
|
+
* Throw if using unsupported mix of send and field
|
|
17
|
+
* Reject `.end()` promise on all error events (Kornel Lesiński)
|
|
18
|
+
* Set `https.servername` from the `Host` header (Kornel Lesiński)
|
|
19
|
+
* Leave backticks unencoded in query strings where possible (Ethan Resnick)
|
|
20
|
+
* Update node-mime to 2.x (Alexey Kucherenko)
|
|
21
|
+
* Allow default buffer settings based on response-type (shrey)
|
|
22
|
+
* `response.buffered` is more accurate.
|
|
23
|
+
|
|
24
|
+
# 3.8.3 (2018-04-29)
|
|
25
|
+
|
|
26
|
+
* Add flags for 201 & 422 responses (Nikhil Fadnis)
|
|
27
|
+
* Emit progress event while uploading Node `Buffer` via send method (Sergey Akhalkov)
|
|
28
|
+
* Fixed setting correct cookies for redirects (Damien Clark)
|
|
29
|
+
* Replace .catch with ['catch'] for IE9 Support (Miguel Stevens)
|
|
30
|
+
|
|
31
|
+
# 3.8.2 (2017-12-09)
|
|
32
|
+
|
|
33
|
+
* Fixed handling of exceptions thrown from callbacks
|
|
34
|
+
* Stricter matching of `+json` MIME types.
|
|
35
|
+
|
|
1
36
|
# 3.8.1 (2017-11-08)
|
|
2
37
|
|
|
3
38
|
* Clear authorization header on cross-domain redirect
|
package/Makefile
CHANGED
|
@@ -11,9 +11,17 @@ test:
|
|
|
11
11
|
test-node:
|
|
12
12
|
@NODE_ENV=test NODE_TLS_REJECT_UNAUTHORIZED=0 ./node_modules/.bin/mocha \
|
|
13
13
|
--require should \
|
|
14
|
+
--trace-warnings \
|
|
15
|
+
--reporter $(REPORTER) \
|
|
16
|
+
--timeout 5000 \
|
|
17
|
+
$(NODETESTS)
|
|
18
|
+
|
|
19
|
+
test-node-http2:
|
|
20
|
+
@NODE_ENV=test HTTP2_TEST=1 NODE_TLS_REJECT_UNAUTHORIZED=0 node ./node_modules/.bin/mocha \
|
|
21
|
+
--require should \
|
|
22
|
+
--trace-warnings \
|
|
14
23
|
--reporter $(REPORTER) \
|
|
15
24
|
--timeout 5000 \
|
|
16
|
-
--growl \
|
|
17
25
|
$(NODETESTS)
|
|
18
26
|
|
|
19
27
|
test-cov: lib-cov
|
|
@@ -30,6 +38,7 @@ lib-cov:
|
|
|
30
38
|
|
|
31
39
|
superagent.js: lib/node/*.js lib/node/parsers/*.js
|
|
32
40
|
@./node_modules/.bin/browserify \
|
|
41
|
+
-t [ babelify --presets [ "babel-preset-es2015" --loose true ] ] \
|
|
33
42
|
--standalone superagent \
|
|
34
43
|
--outfile superagent.js .
|
|
35
44
|
|
package/Readme.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://saucelabs.com/u/shtylman-superagent)
|
|
4
4
|
|
|
5
|
-
SuperAgent is a small progressive __client-side__ HTTP request library, and __Node.js__ module with the same API, sporting many high-level HTTP client features. View the [docs](
|
|
5
|
+
SuperAgent is a small progressive __client-side__ HTTP request library, and __Node.js__ module with the same API, sporting many high-level HTTP client features. View the [docs](https://visionmedia.github.io/superagent/).
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
@@ -35,7 +35,7 @@ Tested browsers:
|
|
|
35
35
|
- Latest Android, iPhone
|
|
36
36
|
- IE10 through latest. IE9 with polyfills. Even though IE9 is supported, a polyfill for `window.FormData` is required for `.field()`.
|
|
37
37
|
|
|
38
|
-
Node
|
|
38
|
+
Node 6 or later is required.
|
|
39
39
|
|
|
40
40
|
## Plugins
|
|
41
41
|
|
|
@@ -63,13 +63,13 @@ Existing plugins:
|
|
|
63
63
|
* [superagent-mock](https://github.com/M6Web/superagent-mock) - simulate HTTP calls by returning data fixtures based on the requested URL
|
|
64
64
|
* [superagent-mocker](https://github.com/shuvalov-anton/superagent-mocker) — simulate REST API
|
|
65
65
|
* [superagent-cache](https://github.com/jpodwys/superagent-cache) - A global SuperAgent patch with built-in, flexible caching
|
|
66
|
-
|
|
66
|
+
* [superagent-cache-plugin](https://github.com/jpodwys/superagent-cache-plugin) - A SuperAgent plugin with built-in, flexible caching
|
|
67
67
|
* [superagent-jsonapify](https://github.com/alex94puchades/superagent-jsonapify) - A lightweight [json-api](http://jsonapi.org/format/) client addon for superagent
|
|
68
68
|
* [superagent-serializer](https://github.com/zzarcon/superagent-serializer) - Converts server payload into different cases
|
|
69
|
-
* [superagent-use](https://github.com/koenpunt/superagent-use) - A client addon to apply plugins to all requests.
|
|
70
69
|
* [superagent-httpbackend](https://www.npmjs.com/package/superagent-httpbackend) - stub out requests using AngularJS' $httpBackend syntax
|
|
71
70
|
* [superagent-throttle](https://github.com/leviwheatcroft/superagent-throttle) - queues and intelligently throttles requests
|
|
72
71
|
* [superagent-charset](https://github.com/magicdawn/superagent-charset) - add charset support for node's SuperAgent
|
|
72
|
+
* [superagent-verbose-errors](https://github.com/jcoreio/superagent-verbose-errors) - include response body in error messages for failed requests
|
|
73
73
|
|
|
74
74
|
Please prefix your plugin with `superagent-*` so that it can easily be found by others.
|
|
75
75
|
|
|
@@ -79,15 +79,19 @@ For SuperAgent extensions such as couchdb and oauth visit the [wiki](https://git
|
|
|
79
79
|
|
|
80
80
|
Our breaking changes are mostly in rarely used functionality and from stricter error handling.
|
|
81
81
|
|
|
82
|
+
* [3.x to 4.x](https://github.com/visionmedia/superagent/releases/tag/v4.0.0-alpha.1):
|
|
83
|
+
- Ensure you're running Node 6 or later. We've dropped support for Node 4.
|
|
84
|
+
- We've started using ES6 and for compatibility with Internet Explorer you may need to use Babel.
|
|
85
|
+
- We suggest migrating from `.end()` callbacks to `.then()` or `await`.
|
|
82
86
|
* [2.x to 3.x](https://github.com/visionmedia/superagent/releases/tag/v3.0.0):
|
|
83
|
-
- Ensure you're running Node 4 or later. We dropped support for Node 0.x.
|
|
87
|
+
- Ensure you're running Node 4 or later. We've dropped support for Node 0.x.
|
|
84
88
|
- Test code that calls `.send()` multiple times. Invalid calls to `.send()` will now throw instead of sending garbage.
|
|
85
89
|
* [1.x to 2.x](https://github.com/visionmedia/superagent/releases/tag/v2.0.0):
|
|
86
90
|
- If you use `.parse()` in the *browser* version, rename it to `.serialize()`.
|
|
87
91
|
- If you rely on `undefined` in query-string values being sent literally as the text "undefined", switch to checking for missing value instead. `?key=undefined` is now `?key` (without a value).
|
|
88
92
|
- If you use `.then()` in Internet Explorer, ensure that you have a polyfill that adds a global `Promise` object.
|
|
89
93
|
* 0.x to 1.x:
|
|
90
|
-
-
|
|
94
|
+
- Instead of 1-argument callback `.end(function(res){})` use `.then(res => {})`.
|
|
91
95
|
|
|
92
96
|
## Running node tests
|
|
93
97
|
|
package/docs/index.md
CHANGED
|
@@ -8,51 +8,52 @@ SuperAgent is light-weight progressive ajax API crafted for flexibility, readabi
|
|
|
8
8
|
.send({ name: 'Manny', species: 'cat' })
|
|
9
9
|
.set('X-API-Key', 'foobar')
|
|
10
10
|
.set('Accept', 'application/json')
|
|
11
|
-
.
|
|
12
|
-
|
|
13
|
-
alert('Oh no! error');
|
|
14
|
-
} else {
|
|
15
|
-
alert('yay got ' + JSON.stringify(res.body));
|
|
16
|
-
}
|
|
11
|
+
.then(res => {
|
|
12
|
+
alert('yay got ' + JSON.stringify(res.body));
|
|
17
13
|
});
|
|
18
14
|
|
|
19
15
|
## Test documentation
|
|
20
16
|
|
|
21
|
-
The following [test documentation](docs/test.html) was generated with [Mocha's](
|
|
17
|
+
The following [test documentation](docs/test.html) was generated with [Mocha's](https://mochajs.org/) "doc" reporter, and directly reflects the test suite. This provides an additional source of documentation.
|
|
22
18
|
|
|
23
19
|
## Request basics
|
|
24
20
|
|
|
25
|
-
A request can be initiated by invoking the appropriate method on the `request` object, then calling `.end()` to send the request. For example a simple __GET__ request:
|
|
21
|
+
A request can be initiated by invoking the appropriate method on the `request` object, then calling `.then()` (or `.end()` [or `await`](#promise-and-generator-support)) to send the request. For example a simple __GET__ request:
|
|
26
22
|
|
|
27
23
|
request
|
|
28
24
|
.get('/search')
|
|
29
|
-
.
|
|
30
|
-
|
|
25
|
+
.then(res => {
|
|
26
|
+
// res.body, res.headers, res.status
|
|
27
|
+
})
|
|
28
|
+
.catch(err => {
|
|
29
|
+
// err.message, err.response
|
|
31
30
|
});
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
HTTP method may also be passed as a string:
|
|
34
33
|
|
|
35
|
-
request('GET', '/search').
|
|
34
|
+
request('GET', '/search').then(success, failure);
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
Old-style callbacks are also supported, but not recommended. *Instead of* `.then()` you can call `.end()`:
|
|
38
37
|
|
|
39
|
-
request('GET', '/search').
|
|
38
|
+
request('GET', '/search').end(function(err, res){
|
|
39
|
+
if (res.ok) {}
|
|
40
|
+
});
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
Absolute URLs can be used. In web browsers absolute URLs work only if the server implements [CORS](#cors).
|
|
42
43
|
|
|
43
44
|
request
|
|
44
|
-
.get('
|
|
45
|
-
.
|
|
45
|
+
.get('https://example.com/search')
|
|
46
|
+
.then(res => {
|
|
46
47
|
|
|
47
48
|
});
|
|
48
49
|
|
|
49
|
-
The __Node__ client supports making requests to [Unix Domain Sockets](
|
|
50
|
+
The __Node__ client supports making requests to [Unix Domain Sockets](https://en.wikipedia.org/wiki/Unix_domain_socket):
|
|
50
51
|
|
|
51
52
|
// pattern: https?+unix://SOCKET_PATH/REQUEST_PATH
|
|
52
53
|
// Use `%2F` as `/` in SOCKET_PATH
|
|
53
54
|
request
|
|
54
55
|
.get('http+unix://%2Fabsolute%2Fpath%2Fto%2Funix.sock/search')
|
|
55
|
-
.
|
|
56
|
+
.then(res => {
|
|
56
57
|
|
|
57
58
|
});
|
|
58
59
|
|
|
@@ -60,15 +61,15 @@ __DELETE__, __HEAD__, __PATCH__, __POST__, and __PUT__ requests can also be used
|
|
|
60
61
|
|
|
61
62
|
request
|
|
62
63
|
.head('/favicon.ico')
|
|
63
|
-
.
|
|
64
|
+
.then(res => {
|
|
64
65
|
|
|
65
66
|
});
|
|
66
67
|
|
|
67
68
|
__DELETE__ can be also called as `.del()` for compatibility with old IE where `delete` is a reserved word.
|
|
68
69
|
|
|
69
|
-
|
|
70
|
+
The HTTP method defaults to __GET__, so if you wish, the following is valid:
|
|
70
71
|
|
|
71
|
-
request('/search',
|
|
72
|
+
request('/search', (err, res) => {
|
|
72
73
|
|
|
73
74
|
});
|
|
74
75
|
|
|
@@ -80,14 +81,14 @@ Setting header fields is simple, invoke `.set()` with a field name and value:
|
|
|
80
81
|
.get('/search')
|
|
81
82
|
.set('API-Key', 'foobar')
|
|
82
83
|
.set('Accept', 'application/json')
|
|
83
|
-
.
|
|
84
|
+
.then(callback);
|
|
84
85
|
|
|
85
86
|
You may also pass an object to set several fields in a single call:
|
|
86
87
|
|
|
87
88
|
request
|
|
88
89
|
.get('/search')
|
|
89
90
|
.set({ 'API-Key': 'foobar', Accept: 'application/json' })
|
|
90
|
-
.
|
|
91
|
+
.then(callback);
|
|
91
92
|
|
|
92
93
|
## `GET` requests
|
|
93
94
|
|
|
@@ -98,7 +99,7 @@ The `.query()` method accepts objects, which when used with the __GET__ method w
|
|
|
98
99
|
.query({ query: 'Manny' })
|
|
99
100
|
.query({ range: '1..5' })
|
|
100
101
|
.query({ order: 'desc' })
|
|
101
|
-
.
|
|
102
|
+
.then(res => {
|
|
102
103
|
|
|
103
104
|
});
|
|
104
105
|
|
|
@@ -107,7 +108,7 @@ Or as a single object:
|
|
|
107
108
|
request
|
|
108
109
|
.get('/search')
|
|
109
110
|
.query({ query: 'Manny', range: '1..5', order: 'desc' })
|
|
110
|
-
.
|
|
111
|
+
.then(res => {
|
|
111
112
|
|
|
112
113
|
});
|
|
113
114
|
|
|
@@ -116,7 +117,7 @@ The `.query()` method accepts strings as well:
|
|
|
116
117
|
request
|
|
117
118
|
.get('/querystring')
|
|
118
119
|
.query('search=Manny&range=1..5')
|
|
119
|
-
.
|
|
120
|
+
.then(res => {
|
|
120
121
|
|
|
121
122
|
});
|
|
122
123
|
|
|
@@ -126,7 +127,7 @@ Or joined:
|
|
|
126
127
|
.get('/querystring')
|
|
127
128
|
.query('search=Manny')
|
|
128
129
|
.query('range=1..5')
|
|
129
|
-
.
|
|
130
|
+
.then(res => {
|
|
130
131
|
|
|
131
132
|
});
|
|
132
133
|
|
|
@@ -137,7 +138,7 @@ You can also use the `.query()` method for HEAD requests. The following will pro
|
|
|
137
138
|
request
|
|
138
139
|
.head('/users')
|
|
139
140
|
.query({ email: 'joe@smith.com' })
|
|
140
|
-
.
|
|
141
|
+
.then(res => {
|
|
141
142
|
|
|
142
143
|
});
|
|
143
144
|
|
|
@@ -148,20 +149,20 @@ A typical JSON __POST__ request might look a little like the following, where we
|
|
|
148
149
|
request.post('/user')
|
|
149
150
|
.set('Content-Type', 'application/json')
|
|
150
151
|
.send('{"name":"tj","pet":"tobi"}')
|
|
151
|
-
.
|
|
152
|
+
.then(callback)
|
|
152
153
|
|
|
153
154
|
Since JSON is undoubtedly the most common, it's the _default_! The following example is equivalent to the previous.
|
|
154
155
|
|
|
155
156
|
request.post('/user')
|
|
156
157
|
.send({ name: 'tj', pet: 'tobi' })
|
|
157
|
-
.
|
|
158
|
+
.then(callback)
|
|
158
159
|
|
|
159
160
|
Or using multiple `.send()` calls:
|
|
160
161
|
|
|
161
162
|
request.post('/user')
|
|
162
163
|
.send({ name: 'tj' })
|
|
163
164
|
.send({ pet: 'tobi' })
|
|
164
|
-
.
|
|
165
|
+
.then(callback)
|
|
165
166
|
|
|
166
167
|
By default sending strings will set the `Content-Type` to `application/x-www-form-urlencoded`,
|
|
167
168
|
multiple calls will be concatenated with `&`, here resulting in `name=tj&pet=tobi`:
|
|
@@ -169,7 +170,7 @@ By default sending strings will set the `Content-Type` to `application/x-www-for
|
|
|
169
170
|
request.post('/user')
|
|
170
171
|
.send('name=tj')
|
|
171
172
|
.send('pet=tobi')
|
|
172
|
-
.
|
|
173
|
+
.then(callback);
|
|
173
174
|
|
|
174
175
|
SuperAgent formats are extensible, however by default "json" and "form" are supported. To send the data as `application/x-www-form-urlencoded` simply invoke `.type()` with "form", where the default is "json". This request will __POST__ the body "name=tj&pet=tobi".
|
|
175
176
|
|
|
@@ -177,13 +178,13 @@ SuperAgent formats are extensible, however by default "json" and "form" are supp
|
|
|
177
178
|
.type('form')
|
|
178
179
|
.send({ name: 'tj' })
|
|
179
180
|
.send({ pet: 'tobi' })
|
|
180
|
-
.
|
|
181
|
+
.then(callback)
|
|
181
182
|
|
|
182
183
|
Sending a [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData) object is also supported. The following example will __POST__ the content of the HTML form identified by id="myForm":
|
|
183
184
|
|
|
184
185
|
request.post('/user')
|
|
185
186
|
.send(new FormData(document.getElementById('myForm')))
|
|
186
|
-
.
|
|
187
|
+
.then(callback)
|
|
187
188
|
|
|
188
189
|
## Setting the `Content-Type`
|
|
189
190
|
|
|
@@ -207,8 +208,28 @@ simply the extension name such as "xml", "json", "png", etc:
|
|
|
207
208
|
|
|
208
209
|
## Serializing request body
|
|
209
210
|
|
|
210
|
-
SuperAgent will automatically serialize JSON and forms.
|
|
211
|
+
SuperAgent will automatically serialize JSON and forms.
|
|
212
|
+
You can setup automatic serialization for other types as well:
|
|
213
|
+
|
|
214
|
+
```js
|
|
215
|
+
request.serialize['application/xml'] = function (obj) {
|
|
216
|
+
return 'string generated from obj';
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// going forward, all requests with a Content-type of
|
|
220
|
+
// 'application/xml' will be automatically serialized
|
|
221
|
+
```
|
|
222
|
+
If you want to send the payload in a custom format, you can replace
|
|
223
|
+
the built-in serialization with the `.serialize()` method on a per-request basis:
|
|
211
224
|
|
|
225
|
+
```js
|
|
226
|
+
request
|
|
227
|
+
.post('/user')
|
|
228
|
+
.send({foo: 'bar'})
|
|
229
|
+
.serialize(obj => {
|
|
230
|
+
return 'string generated from obj';
|
|
231
|
+
});
|
|
232
|
+
```
|
|
212
233
|
## Retrying requests
|
|
213
234
|
|
|
214
235
|
When given the `.retry()` method, SuperAgent will automatically retry requests, if they fail in a way that is transient or could be due to a flaky Internet connection.
|
|
@@ -216,9 +237,10 @@ When given the `.retry()` method, SuperAgent will automatically retry requests,
|
|
|
216
237
|
This method has two optional arguments: number of retries (default 3) and a callback. It calls `callback(err, res)` before each retry. The callback may return `true`/`false` to control whether the request sould be retried (but the maximum number of retries is always applied).
|
|
217
238
|
|
|
218
239
|
request
|
|
219
|
-
.get('
|
|
220
|
-
.retry(2)
|
|
221
|
-
.
|
|
240
|
+
.get('https://example.com/search')
|
|
241
|
+
.retry(2) // or:
|
|
242
|
+
.retry(2, callback)
|
|
243
|
+
.then(finished);
|
|
222
244
|
|
|
223
245
|
Use `.retry()` only with requests that are *idempotent* (i.e. multiple requests reaching the server won't cause undesirable side effects like duplicate purchases).
|
|
224
246
|
|
|
@@ -248,7 +270,7 @@ If you are calling Facebook's API, be sure to send an `Accept: application/json`
|
|
|
248
270
|
.query({ format: 'json' })
|
|
249
271
|
.query({ dest: '/login' })
|
|
250
272
|
.send({ post: 'data', here: 'wahoo' })
|
|
251
|
-
.
|
|
273
|
+
.then(callback);
|
|
252
274
|
|
|
253
275
|
By default the query string is not assembled in any particular order. An asciibetically-sorted query string can be enabled with `req.sortQuery()`. You may also provide a custom sorting comparison function with `req.sortQuery(myComparisonFn)`. The comparison function should take 2 arguments and return a negative/zero/positive integer.
|
|
254
276
|
|
|
@@ -258,16 +280,14 @@ By default the query string is not assembled in any particular order. An asciibe
|
|
|
258
280
|
.query('name=Nick')
|
|
259
281
|
.query('search=Manny')
|
|
260
282
|
.sortQuery()
|
|
261
|
-
.
|
|
283
|
+
.then(callback)
|
|
262
284
|
|
|
263
285
|
// customized sort function
|
|
264
286
|
request.get('/user')
|
|
265
287
|
.query('name=Nick')
|
|
266
288
|
.query('search=Manny')
|
|
267
|
-
.sortQuery(
|
|
268
|
-
|
|
269
|
-
})
|
|
270
|
-
.end(callback)
|
|
289
|
+
.sortQuery((a, b) => a.length - b.length)
|
|
290
|
+
.then(callback)
|
|
271
291
|
```
|
|
272
292
|
|
|
273
293
|
## TLS options
|
|
@@ -289,7 +309,7 @@ request
|
|
|
289
309
|
.post('/client-auth')
|
|
290
310
|
.key(key)
|
|
291
311
|
.cert(cert)
|
|
292
|
-
.
|
|
312
|
+
.then(callback);
|
|
293
313
|
```
|
|
294
314
|
|
|
295
315
|
```js
|
|
@@ -298,12 +318,32 @@ var ca = fs.readFileSync('ca.cert.pem');
|
|
|
298
318
|
request
|
|
299
319
|
.post('https://localhost/private-ca-server')
|
|
300
320
|
.ca(ca)
|
|
301
|
-
.
|
|
321
|
+
.then(res => {});
|
|
302
322
|
```
|
|
303
323
|
|
|
304
324
|
## Parsing response bodies
|
|
305
325
|
|
|
306
|
-
SuperAgent will parse known response-body data for you,
|
|
326
|
+
SuperAgent will parse known response-body data for you,
|
|
327
|
+
currently supporting `application/x-www-form-urlencoded`,
|
|
328
|
+
`application/json`, and `multipart/form-data`. You can setup
|
|
329
|
+
automatic parsing for other response-body data as well:
|
|
330
|
+
|
|
331
|
+
```js
|
|
332
|
+
//browser
|
|
333
|
+
request.parse['application/xml'] = function (str) {
|
|
334
|
+
return {'object': 'parsed from str'};
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
//node
|
|
338
|
+
request.parse['application/xml'] = function (res, cb) {
|
|
339
|
+
//parse response text and set res.body here
|
|
340
|
+
|
|
341
|
+
cb(null, res);
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
//going forward, responses of type 'application/xml'
|
|
345
|
+
//will be parsed automatically
|
|
346
|
+
```
|
|
307
347
|
|
|
308
348
|
You can set a custom parser (that takes precedence over built-in parsers) with the `.buffer(true).parse(fn)` method. If response buffering is not enabled (`.buffer(false)`) then the `response` event will be emitted without waiting for the body parser to finish, so `response.body` won't be available.
|
|
309
349
|
|
|
@@ -341,7 +381,7 @@ In browsers, you may use `.responseType('blob')` to request handling of binary r
|
|
|
341
381
|
```js
|
|
342
382
|
req.get('/binary.data')
|
|
343
383
|
.responseType('blob')
|
|
344
|
-
.
|
|
384
|
+
.then(res => {
|
|
345
385
|
// res.body will be a browser native Blob type here
|
|
346
386
|
});
|
|
347
387
|
```
|
|
@@ -402,11 +442,11 @@ To abort requests simply invoke the `req.abort()` method.
|
|
|
402
442
|
|
|
403
443
|
Sometimes networks and servers get "stuck" and never respond after accepting a request. Set timeouts to avoid requests waiting forever.
|
|
404
444
|
|
|
405
|
-
* `req.timeout({deadline:ms})` or `req.timeout(ms)` (where `ms` is a number of milliseconds > 0) sets a deadline for the entire request (including all redirects) to complete. If the response isn't fully downloaded within that time, the request will be aborted.
|
|
445
|
+
* `req.timeout({deadline:ms})` or `req.timeout(ms)` (where `ms` is a number of milliseconds > 0) sets a deadline for the entire request (including all uploads, redirects, server processing time) to complete. If the response isn't fully downloaded within that time, the request will be aborted.
|
|
406
446
|
|
|
407
|
-
* `req.timeout({response:ms})` sets maximum time to wait for the first byte to arrive from the server, but it does not limit how long the entire download can take. Response timeout should be
|
|
447
|
+
* `req.timeout({response:ms})` sets maximum time to wait for the first byte to arrive from the server, but it does not limit how long the entire download can take. Response timeout should be at least few seconds longer than just the time it takes the server to respond, because it also includes time to make DNS lookup, TCP/IP and TLS connections, and time to upload request data.
|
|
408
448
|
|
|
409
|
-
You should use both `deadline` and `response` timeouts. This way you can use a short response timeout to detect unresponsive networks quickly, and a long deadline to give time for downloads on slow, but reliable, networks.
|
|
449
|
+
You should use both `deadline` and `response` timeouts. This way you can use a short response timeout to detect unresponsive networks quickly, and a long deadline to give time for downloads on slow, but reliable, networks. Note that both of these timers limit how long *uploads* of attached files are allowed to take. Use long timeouts if you're uploading files.
|
|
410
450
|
|
|
411
451
|
request
|
|
412
452
|
.get('/big-file?network=slow')
|
|
@@ -414,8 +454,10 @@ You should use both `deadline` and `response` timeouts. This way you can use a s
|
|
|
414
454
|
response: 5000, // Wait 5 seconds for the server to start sending,
|
|
415
455
|
deadline: 60000, // but allow 1 minute for the file to finish loading.
|
|
416
456
|
})
|
|
417
|
-
.
|
|
418
|
-
|
|
457
|
+
.then(res => {
|
|
458
|
+
/* responded in time */
|
|
459
|
+
}, err => {
|
|
460
|
+
if (err.timeout) { /* timed out! */ } else { /* other error */ }
|
|
419
461
|
});
|
|
420
462
|
|
|
421
463
|
Timeout errors have a `.timeout` property.
|
|
@@ -427,12 +469,12 @@ In both Node and browsers auth available via the `.auth()` method:
|
|
|
427
469
|
request
|
|
428
470
|
.get('http://local')
|
|
429
471
|
.auth('tobi', 'learnboost')
|
|
430
|
-
.
|
|
472
|
+
.then(callback);
|
|
431
473
|
|
|
432
474
|
|
|
433
475
|
In the _Node_ client Basic auth can be in the URL as "user:pass":
|
|
434
476
|
|
|
435
|
-
request.get('http://tobi:learnboost@local').
|
|
477
|
+
request.get('http://tobi:learnboost@local').then(callback);
|
|
436
478
|
|
|
437
479
|
By default only `Basic` auth is used. In browser you can add `{type:'auto'}` to enable all methods built-in in the browser (Digest, NTLM, etc.):
|
|
438
480
|
|
|
@@ -445,7 +487,7 @@ By default up to 5 redirects will be followed, however you may specify this with
|
|
|
445
487
|
request
|
|
446
488
|
.get('/some.png')
|
|
447
489
|
.redirects(2)
|
|
448
|
-
.
|
|
490
|
+
.then(callback);
|
|
449
491
|
|
|
450
492
|
## Agents for global state
|
|
451
493
|
|
|
@@ -464,7 +506,7 @@ In browsers cookies are managed automatically by the browser, so the `.agent()`
|
|
|
464
506
|
|
|
465
507
|
### Default options for multiple requests
|
|
466
508
|
|
|
467
|
-
Regular request methods
|
|
509
|
+
Regular request methods called on the agent will be used as defaults for all requests made by that agent.
|
|
468
510
|
|
|
469
511
|
const agent = request.agent()
|
|
470
512
|
.use(plugin)
|
|
@@ -473,9 +515,13 @@ Regular request methods (`.use()`, `.set()`, `.auth()`) called on the agent will
|
|
|
473
515
|
await agent.get('/with-plugin-and-auth');
|
|
474
516
|
await agent.get('/also-with-plugin-and-auth');
|
|
475
517
|
|
|
518
|
+
The complete list of methods that the agent can use to set defaults is: `use`, `on`, `once`, `set`, `query`, `type`, `accept`, `auth`, `withCredentials`, `sortQuery`, `retry`, `ok`, `redirects`, `timeout`, `buffer`, `serialize`, `parse`, `ca`, `key`, `pfx`, `cert`.
|
|
519
|
+
|
|
476
520
|
## Piping data
|
|
477
521
|
|
|
478
|
-
The Node client allows you to pipe data to and from the request.
|
|
522
|
+
The Node client allows you to pipe data to and from the request. Please note that `.pipe()` is used **instead of** `.end()`/`.then()` methods.
|
|
523
|
+
|
|
524
|
+
For example piping a file's contents as the request:
|
|
479
525
|
|
|
480
526
|
const request = require('superagent');
|
|
481
527
|
const fs = require('fs');
|
|
@@ -493,6 +539,22 @@ Or piping the response to a file:
|
|
|
493
539
|
const req = request.get('/some.json');
|
|
494
540
|
req.pipe(stream);
|
|
495
541
|
|
|
542
|
+
It's not possible to mix pipes and callbacks or promises. Note that you should **NOT** attempt to pipe the result of `.end()` or the `Response` object:
|
|
543
|
+
|
|
544
|
+
// Don't do either of these:
|
|
545
|
+
const stream = getAWritableStream();
|
|
546
|
+
const req = request
|
|
547
|
+
.get('/some.json')
|
|
548
|
+
// BAD: this pipes garbage to the stream and fails in unexpected ways
|
|
549
|
+
.end((err, this_does_not_work) => this_does_not_work.pipe(stream))
|
|
550
|
+
const req = request
|
|
551
|
+
.get('/some.json')
|
|
552
|
+
.end()
|
|
553
|
+
// BAD: this is also unsupported, .pipe calls .end for you.
|
|
554
|
+
.pipe(nope_its_too_late);
|
|
555
|
+
|
|
556
|
+
In a [future version](https://github.com/visionmedia/superagent/issues/1188) of superagent, improper calls to `pipe()` will fail.
|
|
557
|
+
|
|
496
558
|
## Multipart requests
|
|
497
559
|
|
|
498
560
|
SuperAgent is also great for _building_ multipart requests for which it provides methods `.attach()` and `.field()`.
|
|
@@ -503,7 +565,7 @@ When you use `.field()` or `.attach()` you can't use `.send()` and you *must not
|
|
|
503
565
|
|
|
504
566
|
To send a file use `.attach(name, [file], [options])`. You can attach multiple files by calling `.attach` multiple times. The arguments are:
|
|
505
567
|
|
|
506
|
-
* `name` —
|
|
568
|
+
* `name` — field name in the form.
|
|
507
569
|
* `file` — either string with file path or `Blob`/`Buffer` object.
|
|
508
570
|
* `options` — (optional) either string with custom file name or `{filename: string}` object. In Node also `{contentType: 'mime/type'}` is supported. In browser create a `Blob` with an appropriate type instead.
|
|
509
571
|
|
|
@@ -514,7 +576,7 @@ To send a file use `.attach(name, [file], [options])`. You can attach multiple f
|
|
|
514
576
|
.attach('image1', 'path/to/felix.jpeg')
|
|
515
577
|
.attach('image2', imageBuffer, 'luna.jpeg')
|
|
516
578
|
.field('caption', 'My cats')
|
|
517
|
-
.
|
|
579
|
+
.then(callback);
|
|
518
580
|
|
|
519
581
|
### Field values
|
|
520
582
|
|
|
@@ -526,7 +588,7 @@ Much like form fields in HTML, you can set field values with `.field(name, value
|
|
|
526
588
|
.field('user[email]', 'tobi@learnboost.com')
|
|
527
589
|
.field('friends[]', ['loki', 'jane'])
|
|
528
590
|
.attach('image', 'path/to/tobi.png')
|
|
529
|
-
.
|
|
591
|
+
.then(callback);
|
|
530
592
|
|
|
531
593
|
## Compression
|
|
532
594
|
|
|
@@ -545,9 +607,9 @@ For security reasons, browsers will block cross-origin requests unless the serve
|
|
|
545
607
|
The `.withCredentials()` method enables the ability to send cookies from the origin, however only when `Access-Control-Allow-Origin` is _not_ a wildcard ("*"), and `Access-Control-Allow-Credentials` is "true".
|
|
546
608
|
|
|
547
609
|
request
|
|
548
|
-
.get('
|
|
610
|
+
.get('https://api.example.com:4001/')
|
|
549
611
|
.withCredentials()
|
|
550
|
-
.then(
|
|
612
|
+
.then(res => {
|
|
551
613
|
assert.equal(200, res.status);
|
|
552
614
|
assert.equal('tobi', res.text);
|
|
553
615
|
})
|
|
@@ -559,7 +621,7 @@ Your callback function will always be passed two arguments: error and response.
|
|
|
559
621
|
request
|
|
560
622
|
.post('/upload')
|
|
561
623
|
.attach('image', 'path/to/tobi.png')
|
|
562
|
-
.
|
|
624
|
+
.then(res => {
|
|
563
625
|
|
|
564
626
|
});
|
|
565
627
|
|
|
@@ -569,7 +631,7 @@ An "error" event is also emitted, with you can listen for:
|
|
|
569
631
|
.post('/upload')
|
|
570
632
|
.attach('image', 'path/to/tobi.png')
|
|
571
633
|
.on('error', handle)
|
|
572
|
-
.
|
|
634
|
+
.then(res => {
|
|
573
635
|
|
|
574
636
|
});
|
|
575
637
|
|
|
@@ -609,11 +671,13 @@ SuperAgent fires `progress` events on upload and download of large files.
|
|
|
609
671
|
loaded: // bytes downloaded or uploaded so far
|
|
610
672
|
} */
|
|
611
673
|
})
|
|
612
|
-
.
|
|
674
|
+
.then()
|
|
613
675
|
|
|
614
676
|
## Promise and Generator support
|
|
615
677
|
|
|
616
|
-
SuperAgent's request is a "thenable" object that's compatible with JavaScript promises and `async`/`await` syntax.
|
|
678
|
+
SuperAgent's request is a "thenable" object that's compatible with JavaScript promises and `async`/`await` syntax.
|
|
679
|
+
|
|
680
|
+
If you're using promises, **do not** call `.end()` or `.pipe()`. Any use of `.then()` or `await` disables all other ways of using the request.
|
|
617
681
|
|
|
618
682
|
Libraries like [co](https://github.com/tj/co) or a web framework like [koa](https://github.com/koajs/koa) can `yield` on any SuperAgent method:
|
|
619
683
|
|
|
@@ -632,4 +696,4 @@ If want to use WebPack to compile code for Node.JS, you *must* specify [node tar
|
|
|
632
696
|
|
|
633
697
|
### Using browser version in electron
|
|
634
698
|
|
|
635
|
-
[Electron](
|
|
699
|
+
[Electron](https://electron.atom.io/) developers report if you would prefer to use the browser version of SuperAgent instead of the Node version, you can `require('superagent/superagent')`. Your requests will now show up in the Chrome developer tools Network tab. Note this environment is not covered by automated test suite and not officially supported.
|