@wiajs/request 3.0.0 → 3.0.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.
- package/.github/ISSUE_TEMPLATE.md +56 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- package/.github/stale.yml +19 -0
- package/.swcrc +57 -0
- package/.travis.yml +21 -0
- package/CHANGELOG.md +717 -0
- package/CONTRIBUTING.md +81 -0
- package/biome.json +44 -0
- package/codecov.yml +2 -0
- package/disabled.appveyor.yml +36 -0
- package/dist/request.cjs +1476 -0
- package/dist/request.mjs +1474 -0
- package/examples/README.md +135 -0
- package/gulpfile.js +71 -0
- package/package.json +1 -2
- package/release.sh +45 -0
- package/tests/browser/karma.conf.js +57 -0
- package/tests/browser/ssl/ca.crt +14 -0
- package/tests/browser/ssl/server.crt +14 -0
- package/tests/browser/ssl/server.key +15 -0
- package/tests/browser/start.js +37 -0
- package/tests/browser/test.js +34 -0
- package/tests/fixtures/har.json +158 -0
- package/tests/googledoodle.jpg +0 -0
- package/tests/server.js +142 -0
- package/tests/squid.conf +76 -0
- package/tests/ssl/ca/README.md +8 -0
- package/tests/ssl/ca/ca.cnf +20 -0
- package/tests/ssl/ca/ca.crl +0 -0
- package/tests/ssl/ca/ca.crt +17 -0
- package/tests/ssl/ca/ca.csr +13 -0
- package/tests/ssl/ca/ca.key +18 -0
- package/tests/ssl/ca/ca.srl +1 -0
- package/tests/ssl/ca/client-enc.key +30 -0
- package/tests/ssl/ca/client.cnf +20 -0
- package/tests/ssl/ca/client.crt +20 -0
- package/tests/ssl/ca/client.csr +18 -0
- package/tests/ssl/ca/client.key +27 -0
- package/tests/ssl/ca/gen-all-certs.sh +6 -0
- package/tests/ssl/ca/gen-client.sh +25 -0
- package/tests/ssl/ca/gen-localhost.sh +22 -0
- package/tests/ssl/ca/gen-server.sh +18 -0
- package/tests/ssl/ca/localhost.cnf +20 -0
- package/tests/ssl/ca/localhost.crt +20 -0
- package/tests/ssl/ca/localhost.csr +18 -0
- package/tests/ssl/ca/localhost.js +33 -0
- package/tests/ssl/ca/localhost.key +27 -0
- package/tests/ssl/ca/server.cnf +19 -0
- package/tests/ssl/ca/server.crt +25 -0
- package/tests/ssl/ca/server.csr +29 -0
- package/tests/ssl/ca/server.js +34 -0
- package/tests/ssl/ca/server.key +51 -0
- package/tests/ssl/npm-ca.crt +16 -0
- package/tests/ssl/test.crt +15 -0
- package/tests/ssl/test.key +15 -0
- package/tests/test-agent.js +102 -0
- package/tests/test-agentOptions.js +51 -0
- package/tests/test-api.js +33 -0
- package/tests/test-aws.js +123 -0
- package/tests/test-baseUrl.js +133 -0
- package/tests/test-basic-auth.js +221 -0
- package/tests/test-bearer-auth.js +187 -0
- package/tests/test-body.js +154 -0
- package/tests/test-cookies.js +130 -0
- package/tests/test-defaults.js +340 -0
- package/tests/test-digest-auth.js +232 -0
- package/tests/test-emptyBody.js +56 -0
- package/tests/test-errors.js +108 -0
- package/tests/test-event-forwarding.js +39 -0
- package/tests/test-follow-all-303.js +45 -0
- package/tests/test-follow-all.js +57 -0
- package/tests/test-form-data-error.js +85 -0
- package/tests/test-form-data.js +133 -0
- package/tests/test-form-urlencoded.js +73 -0
- package/tests/test-form.js +101 -0
- package/tests/test-gzip.js +296 -0
- package/tests/test-har.js +175 -0
- package/tests/test-hawk.js +187 -0
- package/tests/test-headers.js +305 -0
- package/tests/test-http-signature.js +110 -0
- package/tests/test-httpModule.js +112 -0
- package/tests/test-https.js +116 -0
- package/tests/test-isUrl.js +120 -0
- package/tests/test-json-request.js +117 -0
- package/tests/test-localAddress.js +49 -0
- package/tests/test-multipart-encoding.js +147 -0
- package/tests/test-multipart.js +129 -0
- package/tests/test-node-debug.js +95 -0
- package/tests/test-oauth.js +721 -0
- package/tests/test-onelineproxy.js +61 -0
- package/tests/test-option-reuse.js +54 -0
- package/tests/test-options-convenience-method.js +52 -0
- package/tests/test-params.js +101 -0
- package/tests/test-piped-redirect.js +55 -0
- package/tests/test-pipes.js +383 -0
- package/tests/test-pool.js +148 -0
- package/tests/test-promise.js +53 -0
- package/tests/test-proxy-connect.js +80 -0
- package/tests/test-proxy.js +304 -0
- package/tests/test-qs.js +135 -0
- package/tests/test-redirect-auth.js +131 -0
- package/tests/test-redirect-complex.js +93 -0
- package/tests/test-redirect.js +449 -0
- package/tests/test-rfc3986.js +106 -0
- package/tests/test-stream.js +36 -0
- package/tests/test-timeout.js +260 -0
- package/tests/test-timing.js +147 -0
- package/tests/test-toJSON.js +45 -0
- package/tests/test-tunnel.js +466 -0
- package/tests/test-unix.js +74 -0
- package/tests/unicycle.jpg +0 -0
- package/request.js +0 -1553
- package/src/ZlibTransform.js +0 -27
- package/src/caseless.js +0 -118
- package/src/index.js +0 -122
- package/src/request.js +0 -967
- package/src/utils.js +0 -274
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var http = require('http')
|
|
4
|
+
var request = require('../index')
|
|
5
|
+
var tape = require('tape')
|
|
6
|
+
|
|
7
|
+
var s = http.createServer(function (req, res) {
|
|
8
|
+
res.statusCode = 200
|
|
9
|
+
res.end('ok')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
tape('setup', function (t) {
|
|
13
|
+
s.listen(0, function () {
|
|
14
|
+
s.port = this.address().port
|
|
15
|
+
s.url = 'http://localhost:' + s.port
|
|
16
|
+
t.end()
|
|
17
|
+
})
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
tape('lowercase', function (t) {
|
|
21
|
+
request(s.url, function (err, resp, body) {
|
|
22
|
+
t.equal(err, null)
|
|
23
|
+
t.equal(body, 'ok')
|
|
24
|
+
t.end()
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
tape('uppercase', function (t) {
|
|
29
|
+
request(s.url.replace('http', 'HTTP'), function (err, resp, body) {
|
|
30
|
+
t.equal(err, null)
|
|
31
|
+
t.equal(body, 'ok')
|
|
32
|
+
t.end()
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
tape('mixedcase', function (t) {
|
|
37
|
+
request(s.url.replace('http', 'HtTp'), function (err, resp, body) {
|
|
38
|
+
t.equal(err, null)
|
|
39
|
+
t.equal(body, 'ok')
|
|
40
|
+
t.end()
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
tape('hostname and port', function (t) {
|
|
45
|
+
request({
|
|
46
|
+
uri: {
|
|
47
|
+
protocol: 'http:',
|
|
48
|
+
hostname: 'localhost',
|
|
49
|
+
port: s.port
|
|
50
|
+
}
|
|
51
|
+
}, function (err, res, body) {
|
|
52
|
+
t.equal(err, null)
|
|
53
|
+
t.equal(body, 'ok')
|
|
54
|
+
t.end()
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
tape('hostname and port 1', function (t) {
|
|
59
|
+
request({
|
|
60
|
+
uri: {
|
|
61
|
+
protocol: 'http:',
|
|
62
|
+
hostname: 'localhost',
|
|
63
|
+
port: s.port
|
|
64
|
+
}
|
|
65
|
+
}, function (err, res, body) {
|
|
66
|
+
t.equal(err, null)
|
|
67
|
+
t.equal(body, 'ok')
|
|
68
|
+
t.end()
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
tape('hostname and port 2', function (t) {
|
|
73
|
+
request({
|
|
74
|
+
protocol: 'http:',
|
|
75
|
+
hostname: 'localhost',
|
|
76
|
+
port: s.port
|
|
77
|
+
}, {
|
|
78
|
+
// need this empty options object, otherwise request thinks no uri was set
|
|
79
|
+
}, function (err, res, body) {
|
|
80
|
+
t.equal(err, null)
|
|
81
|
+
t.equal(body, 'ok')
|
|
82
|
+
t.end()
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
tape('hostname and port 3', function (t) {
|
|
87
|
+
request({
|
|
88
|
+
protocol: 'http:',
|
|
89
|
+
hostname: 'localhost',
|
|
90
|
+
port: s.port
|
|
91
|
+
}, function (err, res, body) {
|
|
92
|
+
t.notEqual(err, null)
|
|
93
|
+
t.equal(err.message, 'options.uri is a required argument')
|
|
94
|
+
t.equal(body, undefined)
|
|
95
|
+
t.end()
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
tape('hostname and query string', function (t) {
|
|
100
|
+
request({
|
|
101
|
+
uri: {
|
|
102
|
+
protocol: 'http:',
|
|
103
|
+
hostname: 'localhost',
|
|
104
|
+
port: s.port
|
|
105
|
+
},
|
|
106
|
+
qs: {
|
|
107
|
+
test: 'test'
|
|
108
|
+
}
|
|
109
|
+
}, function (err, res, body) {
|
|
110
|
+
t.equal(err, null)
|
|
111
|
+
t.equal(body, 'ok')
|
|
112
|
+
t.end()
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
tape('cleanup', function (t) {
|
|
117
|
+
s.close(function () {
|
|
118
|
+
t.end()
|
|
119
|
+
})
|
|
120
|
+
})
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var server = require('./server')
|
|
4
|
+
var request = require('../index')
|
|
5
|
+
var tape = require('tape')
|
|
6
|
+
|
|
7
|
+
var s = server.createServer()
|
|
8
|
+
|
|
9
|
+
tape('setup', function (t) {
|
|
10
|
+
s.listen(0, function () {
|
|
11
|
+
t.end()
|
|
12
|
+
})
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
function testJSONValue (testId, value) {
|
|
16
|
+
tape('test ' + testId, function (t) {
|
|
17
|
+
var testUrl = '/' + testId
|
|
18
|
+
s.on(testUrl, server.createPostJSONValidator(value, 'application/json'))
|
|
19
|
+
var opts = {
|
|
20
|
+
method: 'PUT',
|
|
21
|
+
uri: s.url + testUrl,
|
|
22
|
+
json: true,
|
|
23
|
+
body: value
|
|
24
|
+
}
|
|
25
|
+
request(opts, function (err, resp, body) {
|
|
26
|
+
t.equal(err, null)
|
|
27
|
+
t.equal(resp.statusCode, 200)
|
|
28
|
+
t.deepEqual(body, value)
|
|
29
|
+
t.end()
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function testJSONValueReviver (testId, value, reviver, revivedValue) {
|
|
35
|
+
tape('test ' + testId, function (t) {
|
|
36
|
+
var testUrl = '/' + testId
|
|
37
|
+
s.on(testUrl, server.createPostJSONValidator(value, 'application/json'))
|
|
38
|
+
var opts = {
|
|
39
|
+
method: 'PUT',
|
|
40
|
+
uri: s.url + testUrl,
|
|
41
|
+
json: true,
|
|
42
|
+
jsonReviver: reviver,
|
|
43
|
+
body: value
|
|
44
|
+
}
|
|
45
|
+
request(opts, function (err, resp, body) {
|
|
46
|
+
t.equal(err, null)
|
|
47
|
+
t.equal(resp.statusCode, 200)
|
|
48
|
+
t.deepEqual(body, revivedValue)
|
|
49
|
+
t.end()
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function testJSONValueReplacer (testId, value, replacer, replacedValue) {
|
|
55
|
+
tape('test ' + testId, function (t) {
|
|
56
|
+
var testUrl = '/' + testId
|
|
57
|
+
s.on(testUrl, server.createPostJSONValidator(replacedValue, 'application/json'))
|
|
58
|
+
var opts = {
|
|
59
|
+
method: 'PUT',
|
|
60
|
+
uri: s.url + testUrl,
|
|
61
|
+
json: true,
|
|
62
|
+
jsonReplacer: replacer,
|
|
63
|
+
body: value
|
|
64
|
+
}
|
|
65
|
+
request(opts, function (err, resp, body) {
|
|
66
|
+
t.equal(err, null)
|
|
67
|
+
t.equal(resp.statusCode, 200)
|
|
68
|
+
t.deepEqual(body, replacedValue)
|
|
69
|
+
t.end()
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
testJSONValue('jsonNull', null)
|
|
75
|
+
testJSONValue('jsonTrue', true)
|
|
76
|
+
testJSONValue('jsonFalse', false)
|
|
77
|
+
testJSONValue('jsonNumber', -289365.2938)
|
|
78
|
+
testJSONValue('jsonString', 'some string')
|
|
79
|
+
testJSONValue('jsonArray', ['value1', 2, null, 8925.53289, true, false, ['array'], { object: 'property' }])
|
|
80
|
+
testJSONValue('jsonObject', {
|
|
81
|
+
trueProperty: true,
|
|
82
|
+
falseProperty: false,
|
|
83
|
+
numberProperty: -98346.34698,
|
|
84
|
+
stringProperty: 'string',
|
|
85
|
+
nullProperty: null,
|
|
86
|
+
arrayProperty: ['array'],
|
|
87
|
+
objectProperty: { object: 'property' }
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
testJSONValueReviver('jsonReviver', -48269.592, function (k, v) {
|
|
91
|
+
return v * -1
|
|
92
|
+
}, 48269.592)
|
|
93
|
+
testJSONValueReviver('jsonReviverInvalid', -48269.592, 'invalid reviver', -48269.592)
|
|
94
|
+
|
|
95
|
+
testJSONValueReplacer('jsonReplacer', -48269.592, function (k, v) {
|
|
96
|
+
return v * -1
|
|
97
|
+
}, 48269.592)
|
|
98
|
+
testJSONValueReplacer('jsonReplacerInvalid', -48269.592, 'invalid replacer', -48269.592)
|
|
99
|
+
testJSONValueReplacer('jsonReplacerObject', {foo: 'bar'}, function (k, v) {
|
|
100
|
+
return v.toUpperCase ? v.toUpperCase() : v
|
|
101
|
+
}, {foo: 'BAR'})
|
|
102
|
+
|
|
103
|
+
tape('missing body', function (t) {
|
|
104
|
+
s.on('/missing-body', function (req, res) {
|
|
105
|
+
t.equal(req.headers['content-type'], undefined)
|
|
106
|
+
res.end()
|
|
107
|
+
})
|
|
108
|
+
request({url: s.url + '/missing-body', json: true}, function () {
|
|
109
|
+
t.end()
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
tape('cleanup', function (t) {
|
|
114
|
+
s.close(function () {
|
|
115
|
+
t.end()
|
|
116
|
+
})
|
|
117
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
var request = require('../index')
|
|
3
|
+
var tape = require('tape')
|
|
4
|
+
|
|
5
|
+
tape('bind to invalid address', function (t) {
|
|
6
|
+
request.get({
|
|
7
|
+
uri: 'http://www.google.com',
|
|
8
|
+
localAddress: '1.2.3.4'
|
|
9
|
+
}, function (err, res) {
|
|
10
|
+
t.notEqual(err, null)
|
|
11
|
+
t.equal(true, /bind EADDRNOTAVAIL/.test(err.message))
|
|
12
|
+
t.equal(res, undefined)
|
|
13
|
+
t.end()
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
tape('bind to local address', function (t) {
|
|
18
|
+
request.get({
|
|
19
|
+
uri: 'http://www.google.com',
|
|
20
|
+
localAddress: '127.0.0.1'
|
|
21
|
+
}, function (err, res) {
|
|
22
|
+
t.notEqual(err, null)
|
|
23
|
+
t.equal(res, undefined)
|
|
24
|
+
t.end()
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
tape('bind to local address on redirect', function (t) {
|
|
29
|
+
var os = require('os')
|
|
30
|
+
var localInterfaces = os.networkInterfaces()
|
|
31
|
+
var localIPS = []
|
|
32
|
+
Object.keys(localInterfaces).forEach(function (ifname) {
|
|
33
|
+
localInterfaces[ifname].forEach(function (iface) {
|
|
34
|
+
if (iface.family !== 'IPv4' || iface.internal !== false) {
|
|
35
|
+
// skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
localIPS.push(iface.address)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
request.get({
|
|
42
|
+
uri: 'http://google.com', // redirects to 'http://google.com'
|
|
43
|
+
localAddress: localIPS[0]
|
|
44
|
+
}, function (err, res) {
|
|
45
|
+
t.equal(err, null)
|
|
46
|
+
t.equal(res.request.localAddress, localIPS[0])
|
|
47
|
+
t.end()
|
|
48
|
+
})
|
|
49
|
+
})
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var http = require('http')
|
|
4
|
+
var path = require('path')
|
|
5
|
+
var request = require('../index')
|
|
6
|
+
var fs = require('fs')
|
|
7
|
+
var tape = require('tape')
|
|
8
|
+
|
|
9
|
+
var localFile = path.join(__dirname, 'unicycle.jpg')
|
|
10
|
+
var cases = {
|
|
11
|
+
// based on body type
|
|
12
|
+
'+array -stream': {
|
|
13
|
+
options: {
|
|
14
|
+
multipart: [{name: 'field', body: 'value'}]
|
|
15
|
+
},
|
|
16
|
+
expected: {chunked: false}
|
|
17
|
+
},
|
|
18
|
+
'+array +stream': {
|
|
19
|
+
options: {
|
|
20
|
+
multipart: [{name: 'file', body: null}]
|
|
21
|
+
},
|
|
22
|
+
expected: {chunked: true}
|
|
23
|
+
},
|
|
24
|
+
// encoding overrides body value
|
|
25
|
+
'+array +encoding': {
|
|
26
|
+
options: {
|
|
27
|
+
headers: {'transfer-encoding': 'chunked'},
|
|
28
|
+
multipart: [{name: 'field', body: 'value'}]
|
|
29
|
+
},
|
|
30
|
+
expected: {chunked: true}
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// based on body type
|
|
34
|
+
'+object -stream': {
|
|
35
|
+
options: {
|
|
36
|
+
multipart: {data: [{name: 'field', body: 'value'}]}
|
|
37
|
+
},
|
|
38
|
+
expected: {chunked: false}
|
|
39
|
+
},
|
|
40
|
+
'+object +stream': {
|
|
41
|
+
options: {
|
|
42
|
+
multipart: {data: [{name: 'file', body: null}]}
|
|
43
|
+
},
|
|
44
|
+
expected: {chunked: true}
|
|
45
|
+
},
|
|
46
|
+
// encoding overrides body value
|
|
47
|
+
'+object +encoding': {
|
|
48
|
+
options: {
|
|
49
|
+
headers: {'transfer-encoding': 'chunked'},
|
|
50
|
+
multipart: {data: [{name: 'field', body: 'value'}]}
|
|
51
|
+
},
|
|
52
|
+
expected: {chunked: true}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
// based on body type
|
|
56
|
+
'+object -chunked -stream': {
|
|
57
|
+
options: {
|
|
58
|
+
multipart: {chunked: false, data: [{name: 'field', body: 'value'}]}
|
|
59
|
+
},
|
|
60
|
+
expected: {chunked: false}
|
|
61
|
+
},
|
|
62
|
+
'+object -chunked +stream': {
|
|
63
|
+
options: {
|
|
64
|
+
multipart: {chunked: false, data: [{name: 'file', body: null}]}
|
|
65
|
+
},
|
|
66
|
+
expected: {chunked: true}
|
|
67
|
+
},
|
|
68
|
+
// chunked overrides body value
|
|
69
|
+
'+object +chunked -stream': {
|
|
70
|
+
options: {
|
|
71
|
+
multipart: {chunked: true, data: [{name: 'field', body: 'value'}]}
|
|
72
|
+
},
|
|
73
|
+
expected: {chunked: true}
|
|
74
|
+
},
|
|
75
|
+
// encoding overrides chunked
|
|
76
|
+
'+object +encoding -chunked': {
|
|
77
|
+
options: {
|
|
78
|
+
headers: {'transfer-encoding': 'chunked'},
|
|
79
|
+
multipart: {chunked: false, data: [{name: 'field', body: 'value'}]}
|
|
80
|
+
},
|
|
81
|
+
expected: {chunked: true}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function runTest (t, test) {
|
|
86
|
+
var server = http.createServer(function (req, res) {
|
|
87
|
+
t.ok(req.headers['content-type'].match(/^multipart\/related; boundary=[^\s;]+$/))
|
|
88
|
+
|
|
89
|
+
if (test.expected.chunked) {
|
|
90
|
+
t.ok(req.headers['transfer-encoding'] === 'chunked')
|
|
91
|
+
t.notOk(req.headers['content-length'])
|
|
92
|
+
} else {
|
|
93
|
+
t.ok(req.headers['content-length'])
|
|
94
|
+
t.notOk(req.headers['transfer-encoding'])
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// temp workaround
|
|
98
|
+
var data = ''
|
|
99
|
+
req.setEncoding('utf8')
|
|
100
|
+
|
|
101
|
+
req.on('data', function (d) {
|
|
102
|
+
data += d
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
req.on('end', function () {
|
|
106
|
+
// check for the fields traces
|
|
107
|
+
if (test.expected.chunked && data.indexOf('name: file') !== -1) {
|
|
108
|
+
// file
|
|
109
|
+
t.ok(data.indexOf('name: file') !== -1)
|
|
110
|
+
// check for unicycle.jpg traces
|
|
111
|
+
t.ok(data.indexOf('2005:06:21 01:44:12') !== -1)
|
|
112
|
+
} else {
|
|
113
|
+
// field
|
|
114
|
+
t.ok(data.indexOf('name: field') !== -1)
|
|
115
|
+
var parts = test.options.multipart.data || test.options.multipart
|
|
116
|
+
t.ok(data.indexOf(parts[0].body) !== -1)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
res.writeHead(200)
|
|
120
|
+
res.end()
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
server.listen(0, function () {
|
|
125
|
+
var url = 'http://localhost:' + this.address().port
|
|
126
|
+
// @NOTE: multipartData properties must be set here
|
|
127
|
+
// so that file read stream does not leak in node v0.8
|
|
128
|
+
var parts = test.options.multipart.data || test.options.multipart
|
|
129
|
+
if (parts[0].name === 'file') {
|
|
130
|
+
parts[0].body = fs.createReadStream(localFile)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
request.post(url, test.options, function (err, res, body) {
|
|
134
|
+
t.equal(err, null)
|
|
135
|
+
t.equal(res.statusCode, 200)
|
|
136
|
+
server.close(function () {
|
|
137
|
+
t.end()
|
|
138
|
+
})
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
Object.keys(cases).forEach(function (name) {
|
|
144
|
+
tape('multipart-encoding ' + name, function (t) {
|
|
145
|
+
runTest(t, cases[name])
|
|
146
|
+
})
|
|
147
|
+
})
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var http = require('http')
|
|
4
|
+
var path = require('path')
|
|
5
|
+
var request = require('../index')
|
|
6
|
+
var fs = require('fs')
|
|
7
|
+
var tape = require('tape')
|
|
8
|
+
|
|
9
|
+
function runTest (t, a) {
|
|
10
|
+
var remoteFile = path.join(__dirname, 'googledoodle.jpg')
|
|
11
|
+
var localFile = path.join(__dirname, 'unicycle.jpg')
|
|
12
|
+
var multipartData = []
|
|
13
|
+
|
|
14
|
+
var server = http.createServer(function (req, res) {
|
|
15
|
+
if (req.url === '/file') {
|
|
16
|
+
res.writeHead(200, {'content-type': 'image/jpg'})
|
|
17
|
+
res.end(fs.readFileSync(remoteFile), 'binary')
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (a.header) {
|
|
22
|
+
if (a.header.indexOf('mixed') !== -1) {
|
|
23
|
+
t.ok(req.headers['content-type'].match(/^multipart\/mixed; boundary=[^\s;]+$/))
|
|
24
|
+
} else {
|
|
25
|
+
t.ok(req.headers['content-type']
|
|
26
|
+
.match(/^multipart\/related; boundary=XXX; type=text\/xml; start="<root>"$/))
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
t.ok(req.headers['content-type'].match(/^multipart\/related; boundary=[^\s;]+$/))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// temp workaround
|
|
33
|
+
var data = ''
|
|
34
|
+
req.setEncoding('utf8')
|
|
35
|
+
|
|
36
|
+
req.on('data', function (d) {
|
|
37
|
+
data += d
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
req.on('end', function () {
|
|
41
|
+
// check for the fields traces
|
|
42
|
+
|
|
43
|
+
// my_field
|
|
44
|
+
t.ok(data.indexOf('name: my_field') !== -1)
|
|
45
|
+
t.ok(data.indexOf(multipartData[0].body) !== -1)
|
|
46
|
+
|
|
47
|
+
// my_number
|
|
48
|
+
t.ok(data.indexOf('name: my_number') !== -1)
|
|
49
|
+
t.ok(data.indexOf(multipartData[1].body) !== -1)
|
|
50
|
+
|
|
51
|
+
// my_buffer
|
|
52
|
+
t.ok(data.indexOf('name: my_buffer') !== -1)
|
|
53
|
+
t.ok(data.indexOf(multipartData[2].body) !== -1)
|
|
54
|
+
|
|
55
|
+
// my_file
|
|
56
|
+
t.ok(data.indexOf('name: my_file') !== -1)
|
|
57
|
+
// check for unicycle.jpg traces
|
|
58
|
+
t.ok(data.indexOf('2005:06:21 01:44:12') !== -1)
|
|
59
|
+
|
|
60
|
+
// remote_file
|
|
61
|
+
t.ok(data.indexOf('name: remote_file') !== -1)
|
|
62
|
+
// check for http://localhost:nnnn/file traces
|
|
63
|
+
t.ok(data.indexOf('Photoshop ICC') !== -1)
|
|
64
|
+
|
|
65
|
+
if (a.header && a.header.indexOf('boundary=XXX') !== -1) {
|
|
66
|
+
t.ok(data.indexOf('--XXX') !== -1)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
res.writeHead(200)
|
|
70
|
+
res.end(a.json ? JSON.stringify({status: 'done'}) : 'done')
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
server.listen(0, function () {
|
|
75
|
+
var url = 'http://localhost:' + this.address().port
|
|
76
|
+
// @NOTE: multipartData properties must be set here so that my_file read stream does not leak in node v0.8
|
|
77
|
+
multipartData = [
|
|
78
|
+
{name: 'my_field', body: 'my_value'},
|
|
79
|
+
{name: 'my_number', body: 1000},
|
|
80
|
+
{name: 'my_buffer', body: Buffer.from([1, 2, 3])},
|
|
81
|
+
{name: 'my_file', body: fs.createReadStream(localFile)},
|
|
82
|
+
{name: 'remote_file', body: request(url + '/file')}
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
var reqOptions = {
|
|
86
|
+
url: url + '/upload',
|
|
87
|
+
multipart: multipartData
|
|
88
|
+
}
|
|
89
|
+
if (a.header) {
|
|
90
|
+
reqOptions.headers = {
|
|
91
|
+
'content-type': a.header
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (a.json) {
|
|
95
|
+
reqOptions.json = true
|
|
96
|
+
}
|
|
97
|
+
request[a.method](reqOptions, function (err, res, body) {
|
|
98
|
+
t.equal(err, null)
|
|
99
|
+
t.equal(res.statusCode, 200)
|
|
100
|
+
t.deepEqual(body, a.json ? {status: 'done'} : 'done')
|
|
101
|
+
server.close(function () {
|
|
102
|
+
t.end()
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
var testHeaders = [
|
|
109
|
+
null,
|
|
110
|
+
'multipart/mixed',
|
|
111
|
+
'multipart/related; boundary=XXX; type=text/xml; start="<root>"'
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
var methods = ['post', 'get']
|
|
115
|
+
methods.forEach(function (method) {
|
|
116
|
+
testHeaders.forEach(function (header) {
|
|
117
|
+
[true, false].forEach(function (json) {
|
|
118
|
+
var name = [
|
|
119
|
+
'multipart-related', method.toUpperCase(),
|
|
120
|
+
(header || 'default'),
|
|
121
|
+
(json ? '+' : '-') + 'json'
|
|
122
|
+
].join(' ')
|
|
123
|
+
|
|
124
|
+
tape(name, function (t) {
|
|
125
|
+
runTest(t, {method: method, header: header, json: json})
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
})
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var request = require('../index')
|
|
4
|
+
var http = require('http')
|
|
5
|
+
var tape = require('tape')
|
|
6
|
+
|
|
7
|
+
var s = http.createServer(function (req, res) {
|
|
8
|
+
res.statusCode = 200
|
|
9
|
+
res.end('')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
var stderr = []
|
|
13
|
+
var prevStderrLen = 0
|
|
14
|
+
|
|
15
|
+
tape('setup', function (t) {
|
|
16
|
+
process.stderr._oldWrite = process.stderr.write
|
|
17
|
+
process.stderr.write = function (string, encoding, fd) {
|
|
18
|
+
stderr.push(string)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
s.listen(0, function () {
|
|
22
|
+
s.url = 'http://localhost:' + this.address().port
|
|
23
|
+
t.end()
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
tape('a simple request should not fail with debugging enabled', function (t) {
|
|
28
|
+
request.debug = true
|
|
29
|
+
t.equal(request.Request.debug, true, 'request.debug sets request.Request.debug')
|
|
30
|
+
t.equal(request.debug, true, 'request.debug gets request.Request.debug')
|
|
31
|
+
stderr = []
|
|
32
|
+
|
|
33
|
+
request(s.url, function (err, res, body) {
|
|
34
|
+
t.ifError(err, 'the request did not fail')
|
|
35
|
+
t.ok(res, 'the request did not fail')
|
|
36
|
+
|
|
37
|
+
t.ok(stderr.length, 'stderr has some messages')
|
|
38
|
+
var url = s.url.replace(/\//g, '\\/')
|
|
39
|
+
var patterns = [
|
|
40
|
+
/^REQUEST { uri: /,
|
|
41
|
+
new RegExp('^REQUEST make request ' + url + '/\n$'),
|
|
42
|
+
/^REQUEST onRequestResponse /,
|
|
43
|
+
/^REQUEST finish init /,
|
|
44
|
+
/^REQUEST response end /,
|
|
45
|
+
/^REQUEST end event /,
|
|
46
|
+
/^REQUEST emitting complete /
|
|
47
|
+
]
|
|
48
|
+
patterns.forEach(function (pattern) {
|
|
49
|
+
var found = false
|
|
50
|
+
stderr.forEach(function (msg) {
|
|
51
|
+
if (pattern.test(msg)) {
|
|
52
|
+
found = true
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
t.ok(found, 'a log message matches ' + pattern)
|
|
56
|
+
})
|
|
57
|
+
prevStderrLen = stderr.length
|
|
58
|
+
t.end()
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
tape('there should be no further lookups on process.env', function (t) {
|
|
63
|
+
process.env.NODE_DEBUG = ''
|
|
64
|
+
stderr = []
|
|
65
|
+
|
|
66
|
+
request(s.url, function (err, res, body) {
|
|
67
|
+
t.ifError(err, 'the request did not fail')
|
|
68
|
+
t.ok(res, 'the request did not fail')
|
|
69
|
+
t.equal(stderr.length, prevStderrLen, 'env.NODE_DEBUG is not retested')
|
|
70
|
+
t.end()
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
tape('it should be possible to disable debugging at runtime', function (t) {
|
|
75
|
+
request.debug = false
|
|
76
|
+
t.equal(request.Request.debug, false, 'request.debug sets request.Request.debug')
|
|
77
|
+
t.equal(request.debug, false, 'request.debug gets request.Request.debug')
|
|
78
|
+
stderr = []
|
|
79
|
+
|
|
80
|
+
request(s.url, function (err, res, body) {
|
|
81
|
+
t.ifError(err, 'the request did not fail')
|
|
82
|
+
t.ok(res, 'the request did not fail')
|
|
83
|
+
t.equal(stderr.length, 0, 'debugging can be disabled')
|
|
84
|
+
t.end()
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
tape('cleanup', function (t) {
|
|
89
|
+
process.stderr.write = process.stderr._oldWrite
|
|
90
|
+
delete process.stderr._oldWrite
|
|
91
|
+
|
|
92
|
+
s.close(function () {
|
|
93
|
+
t.end()
|
|
94
|
+
})
|
|
95
|
+
})
|