@datanimbus/postman-request 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/LICENSE +55 -0
- package/README.md +1315 -0
- package/index.js +166 -0
- package/lib/auth.js +167 -0
- package/lib/autohttp/agent.js +206 -0
- package/lib/autohttp/headerValidations.js +40 -0
- package/lib/autohttp/index.js +8 -0
- package/lib/autohttp/request.js +192 -0
- package/lib/autohttp/requestName.js +86 -0
- package/lib/cookies.js +20 -0
- package/lib/getProxyFromURI.js +79 -0
- package/lib/har.js +200 -0
- package/lib/hawk.js +89 -0
- package/lib/helpers.js +91 -0
- package/lib/http2/agent.js +92 -0
- package/lib/http2/index.js +8 -0
- package/lib/http2/request.js +369 -0
- package/lib/inflate.js +64 -0
- package/lib/multipart.js +112 -0
- package/lib/oauth.js +147 -0
- package/lib/querystring.js +50 -0
- package/lib/redirect.js +218 -0
- package/lib/socks.js +45 -0
- package/lib/tunnel.js +175 -0
- package/lib/url-parse.js +187 -0
- package/package.json +77 -0
- package/request.js +2098 -0
package/lib/tunnel.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var tunnel = require('@postman/tunnel-agent')
|
|
4
|
+
|
|
5
|
+
var defaultProxyHeaderWhiteList = [
|
|
6
|
+
'accept',
|
|
7
|
+
'accept-charset',
|
|
8
|
+
'accept-encoding',
|
|
9
|
+
'accept-language',
|
|
10
|
+
'accept-ranges',
|
|
11
|
+
'cache-control',
|
|
12
|
+
'content-encoding',
|
|
13
|
+
'content-language',
|
|
14
|
+
'content-location',
|
|
15
|
+
'content-md5',
|
|
16
|
+
'content-range',
|
|
17
|
+
'content-type',
|
|
18
|
+
'connection',
|
|
19
|
+
'date',
|
|
20
|
+
'expect',
|
|
21
|
+
'max-forwards',
|
|
22
|
+
'pragma',
|
|
23
|
+
'referer',
|
|
24
|
+
'te',
|
|
25
|
+
'user-agent',
|
|
26
|
+
'via'
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
var defaultProxyHeaderExclusiveList = [
|
|
30
|
+
'proxy-authorization'
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
function constructProxyHost (uriObject) {
|
|
34
|
+
var port = uriObject.port
|
|
35
|
+
var protocol = uriObject.protocol
|
|
36
|
+
var proxyHost = uriObject.hostname + ':'
|
|
37
|
+
|
|
38
|
+
if (port) {
|
|
39
|
+
proxyHost += port
|
|
40
|
+
} else if (protocol === 'https:') {
|
|
41
|
+
proxyHost += '443'
|
|
42
|
+
} else {
|
|
43
|
+
proxyHost += '80'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return proxyHost
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function constructProxyHeaderWhiteList (headers, proxyHeaderWhiteList) {
|
|
50
|
+
var whiteList = proxyHeaderWhiteList
|
|
51
|
+
.reduce(function (set, header) {
|
|
52
|
+
set[header.toLowerCase()] = true
|
|
53
|
+
return set
|
|
54
|
+
}, {})
|
|
55
|
+
|
|
56
|
+
return Object.keys(headers)
|
|
57
|
+
.filter(function (header) {
|
|
58
|
+
return whiteList[header.toLowerCase()]
|
|
59
|
+
})
|
|
60
|
+
.reduce(function (set, header) {
|
|
61
|
+
set[header] = headers[header]
|
|
62
|
+
return set
|
|
63
|
+
}, {})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function constructTunnelOptions (request, proxyHeaders) {
|
|
67
|
+
var proxy = request.proxy
|
|
68
|
+
|
|
69
|
+
var tunnelOptions = {
|
|
70
|
+
proxy: {
|
|
71
|
+
host: proxy.hostname,
|
|
72
|
+
port: +proxy.port,
|
|
73
|
+
proxyAuth: proxy.auth,
|
|
74
|
+
headers: proxyHeaders
|
|
75
|
+
},
|
|
76
|
+
headers: request.headers,
|
|
77
|
+
ca: request.ca,
|
|
78
|
+
cert: request.cert,
|
|
79
|
+
key: request.key,
|
|
80
|
+
passphrase: request.passphrase,
|
|
81
|
+
pfx: request.pfx,
|
|
82
|
+
ciphers: request.ciphers,
|
|
83
|
+
rejectUnauthorized: request.rejectUnauthorized,
|
|
84
|
+
secureOptions: request.secureOptions,
|
|
85
|
+
secureProtocol: request.secureProtocol,
|
|
86
|
+
extraCA: request.extraCA
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return tunnelOptions
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function constructTunnelFnName (uri, proxy) {
|
|
93
|
+
var uriProtocol = (uri.protocol === 'https:' ? 'https' : 'http')
|
|
94
|
+
var proxyProtocol = (proxy.protocol === 'https:' ? 'Https' : 'Http')
|
|
95
|
+
return [uriProtocol, proxyProtocol].join('Over')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function getTunnelFn (request) {
|
|
99
|
+
var uri = request.uri
|
|
100
|
+
var proxy = request.proxy
|
|
101
|
+
var tunnelFnName = constructTunnelFnName(uri, proxy)
|
|
102
|
+
return tunnel[tunnelFnName]
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function Tunnel (request) {
|
|
106
|
+
this.request = request
|
|
107
|
+
this.proxyHeaderWhiteList = defaultProxyHeaderWhiteList
|
|
108
|
+
this.proxyHeaderExclusiveList = []
|
|
109
|
+
if (typeof request.tunnel !== 'undefined') {
|
|
110
|
+
this.tunnelOverride = request.tunnel
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
Tunnel.prototype.isEnabled = function () {
|
|
115
|
+
var self = this
|
|
116
|
+
var request = self.request
|
|
117
|
+
// Tunnel HTTPS by default. Allow the user to override this setting.
|
|
118
|
+
|
|
119
|
+
// If self.tunnelOverride is set (the user specified a value), use it.
|
|
120
|
+
if (typeof self.tunnelOverride !== 'undefined') {
|
|
121
|
+
return self.tunnelOverride
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// If the destination is HTTPS, tunnel.
|
|
125
|
+
if (request.uri.protocol === 'https:') {
|
|
126
|
+
return true
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Otherwise, do not use tunnel.
|
|
130
|
+
return false
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
Tunnel.prototype.setup = function (options) {
|
|
134
|
+
var self = this
|
|
135
|
+
var request = self.request
|
|
136
|
+
|
|
137
|
+
options = options || {}
|
|
138
|
+
|
|
139
|
+
if (typeof request.proxy === 'string') {
|
|
140
|
+
request.proxy = request.urlParser.parse(request.proxy)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!request.proxy || !request.tunnel) {
|
|
144
|
+
return false
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Setup Proxy Header Exclusive List and White List
|
|
148
|
+
if (options.proxyHeaderWhiteList) {
|
|
149
|
+
self.proxyHeaderWhiteList = options.proxyHeaderWhiteList
|
|
150
|
+
}
|
|
151
|
+
if (options.proxyHeaderExclusiveList) {
|
|
152
|
+
self.proxyHeaderExclusiveList = options.proxyHeaderExclusiveList
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
var proxyHeaderExclusiveList = self.proxyHeaderExclusiveList.concat(defaultProxyHeaderExclusiveList)
|
|
156
|
+
var proxyHeaderWhiteList = self.proxyHeaderWhiteList.concat(proxyHeaderExclusiveList)
|
|
157
|
+
|
|
158
|
+
// Setup Proxy Headers and Proxy Headers Host
|
|
159
|
+
// Only send the Proxy White Listed Header names
|
|
160
|
+
var proxyHeaders = constructProxyHeaderWhiteList(request.headers, proxyHeaderWhiteList)
|
|
161
|
+
proxyHeaders.host = constructProxyHost(request.uri)
|
|
162
|
+
|
|
163
|
+
proxyHeaderExclusiveList.forEach(request.removeHeader, request)
|
|
164
|
+
|
|
165
|
+
// Set Agent from Tunnel Data
|
|
166
|
+
var tunnelFn = getTunnelFn(request)
|
|
167
|
+
var tunnelOptions = constructTunnelOptions(request, proxyHeaders)
|
|
168
|
+
request.agent = tunnelFn(tunnelOptions)
|
|
169
|
+
|
|
170
|
+
return true
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
Tunnel.defaultProxyHeaderWhiteList = defaultProxyHeaderWhiteList
|
|
174
|
+
Tunnel.defaultProxyHeaderExclusiveList = defaultProxyHeaderExclusiveList
|
|
175
|
+
exports.Tunnel = Tunnel
|
package/lib/url-parse.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
var url = require('url')
|
|
2
|
+
var EMPTY = ''
|
|
3
|
+
var ZERO = '0'
|
|
4
|
+
var PERCENT = '%'
|
|
5
|
+
var STRING = 'string'
|
|
6
|
+
var AMPERSAND = '&'
|
|
7
|
+
var EQUALS = '='
|
|
8
|
+
var QUESTION_MARK = '?'
|
|
9
|
+
var stringify
|
|
10
|
+
var parse
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Percent encode a character with given code.
|
|
14
|
+
*
|
|
15
|
+
* @param {Number} c - character code of the character to encode
|
|
16
|
+
* @returns {String} - percent encoding of given character
|
|
17
|
+
*/
|
|
18
|
+
var percentEncode = function (c) {
|
|
19
|
+
var hex = c.toString(16).toUpperCase()
|
|
20
|
+
hex.length === 1 && (hex = ZERO + hex)
|
|
21
|
+
return PERCENT + hex
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Checks if character with given code is valid hexadecimal digit or not.
|
|
26
|
+
*
|
|
27
|
+
* @param {Number} byte
|
|
28
|
+
* @returns {Boolean}
|
|
29
|
+
*/
|
|
30
|
+
var isPreEncodedCharacter = function (byte) {
|
|
31
|
+
return (byte >= 0x30 && byte <= 0x39) || // 0-9
|
|
32
|
+
(byte >= 0x41 && byte <= 0x46) || // A-F
|
|
33
|
+
(byte >= 0x61 && byte <= 0x66) // a-f
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Checks if character at given index in the buffer is already percent encoded or not.
|
|
38
|
+
*
|
|
39
|
+
* @param {Buffer} buffer
|
|
40
|
+
* @param {Number} i
|
|
41
|
+
* @returns {Boolean}
|
|
42
|
+
*/
|
|
43
|
+
var isPreEncoded = function (buffer, i) {
|
|
44
|
+
// If it is % check next two bytes for percent encode characters
|
|
45
|
+
// looking for pattern %00 - %FF
|
|
46
|
+
return (buffer[i] === 0x25 &&
|
|
47
|
+
(isPreEncodedCharacter(buffer[i + 1]) &&
|
|
48
|
+
isPreEncodedCharacter(buffer[i + 2]))
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Checks whether given character should be percent encoded or not for fixture.
|
|
54
|
+
*
|
|
55
|
+
* @param {Number} byte
|
|
56
|
+
* @returns {Boolean}
|
|
57
|
+
*/
|
|
58
|
+
var charactersToPercentEncode = function (byte) {
|
|
59
|
+
return (byte < 0x23 || byte > 0x7E || // Below # and after ~
|
|
60
|
+
byte === 0x3C || byte === 0x3E || // > and <
|
|
61
|
+
byte === 0x28 || byte === 0x29 || // ( and )
|
|
62
|
+
byte === 0x25 || // %
|
|
63
|
+
byte === 0x27 || // '
|
|
64
|
+
byte === 0x2A // *
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Percent encode a query string according to RFC 3986.
|
|
70
|
+
* Note: This function is supposed to be used on top of node's inbuilt url encoding
|
|
71
|
+
* to solve issue https://github.com/nodejs/node/issues/8321
|
|
72
|
+
*
|
|
73
|
+
* @param {String} value
|
|
74
|
+
* @returns {String}
|
|
75
|
+
*/
|
|
76
|
+
var encode = function (value) {
|
|
77
|
+
if (!value) { return EMPTY }
|
|
78
|
+
|
|
79
|
+
var buffer = Buffer.from(value)
|
|
80
|
+
var ret = EMPTY
|
|
81
|
+
var i
|
|
82
|
+
var ii
|
|
83
|
+
|
|
84
|
+
for (i = 0, ii = buffer.length; i < ii; ++i) {
|
|
85
|
+
if (charactersToPercentEncode(buffer[i]) && !isPreEncoded(buffer, i)) {
|
|
86
|
+
ret += percentEncode(buffer[i])
|
|
87
|
+
} else {
|
|
88
|
+
ret += String.fromCodePoint(buffer[i]) // Only works in ES6 (available in Node v4+)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return ret
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Parses a query string into an array, preserving parameter values
|
|
97
|
+
*
|
|
98
|
+
* @param string
|
|
99
|
+
* @returns {*}
|
|
100
|
+
*/
|
|
101
|
+
parse = function (string) {
|
|
102
|
+
var parts
|
|
103
|
+
if (typeof string === STRING) { // eslint-disable-line valid-typeof
|
|
104
|
+
parts = string.split(AMPERSAND)
|
|
105
|
+
return parts.map(function (param, idx) {
|
|
106
|
+
if (param === EMPTY && idx !== (parts.length - 1)) {
|
|
107
|
+
return { key: null, value: null }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
var index = (typeof param === STRING) ? param.indexOf(EQUALS) : -1 // eslint-disable-line valid-typeof
|
|
111
|
+
var paramObj = {}
|
|
112
|
+
|
|
113
|
+
// this means that there was no value for this key (not even blank, so we store this info) and the value is set
|
|
114
|
+
// to null
|
|
115
|
+
if (index < 0) {
|
|
116
|
+
paramObj.key = param.substr(0, param.length)
|
|
117
|
+
paramObj.value = null
|
|
118
|
+
} else {
|
|
119
|
+
paramObj.key = param.substr(0, index)
|
|
120
|
+
paramObj.value = param.substr(index + 1)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return paramObj
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
return []
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Stringifies a query string, from an array of parameters
|
|
131
|
+
*
|
|
132
|
+
* @param parameters
|
|
133
|
+
* @returns {string}
|
|
134
|
+
*/
|
|
135
|
+
stringify = function (parameters) {
|
|
136
|
+
return parameters ? parameters.map(function (param) {
|
|
137
|
+
var key = param.key
|
|
138
|
+
var value = param.value
|
|
139
|
+
|
|
140
|
+
if (value === undefined) {
|
|
141
|
+
return EMPTY
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (key === null) {
|
|
145
|
+
key = EMPTY
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (value === null) {
|
|
149
|
+
return encode(key)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return encode(key) + EQUALS + encode(value)
|
|
153
|
+
}).join(AMPERSAND) : EMPTY
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Correctly URL encodes query parameters in a URL and returns the final parsed URL.
|
|
158
|
+
*
|
|
159
|
+
* @param str
|
|
160
|
+
*/
|
|
161
|
+
module.exports = function (str) {
|
|
162
|
+
var parsed = url.parse(str)
|
|
163
|
+
var rawQs
|
|
164
|
+
var search
|
|
165
|
+
var path
|
|
166
|
+
var qs
|
|
167
|
+
|
|
168
|
+
rawQs = parsed.query
|
|
169
|
+
|
|
170
|
+
if (rawQs && rawQs.length) {
|
|
171
|
+
qs = stringify(parse(parsed.query))
|
|
172
|
+
search = QUESTION_MARK + qs
|
|
173
|
+
path = parsed.pathname + search
|
|
174
|
+
|
|
175
|
+
parsed.query = qs
|
|
176
|
+
parsed.search = search
|
|
177
|
+
parsed.path = path
|
|
178
|
+
|
|
179
|
+
str = url.format(parsed)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Parse again, because Node does not guarantee consistency of properties
|
|
183
|
+
return url.parse(str)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
module.exports.parse = parse
|
|
187
|
+
module.exports.stringify = stringify
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@datanimbus/postman-request",
|
|
3
|
+
"description": "Simplified HTTP request client.",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"http",
|
|
6
|
+
"simple",
|
|
7
|
+
"util",
|
|
8
|
+
"utility"
|
|
9
|
+
],
|
|
10
|
+
"version": "3.0.1",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/postmanlabs/postman-request.git"
|
|
14
|
+
},
|
|
15
|
+
"license": "Apache-2.0",
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">= 16"
|
|
18
|
+
},
|
|
19
|
+
"main": "index.js",
|
|
20
|
+
"files": [
|
|
21
|
+
"lib/",
|
|
22
|
+
"index.js",
|
|
23
|
+
"request.js"
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@postman/form-data": "~3.1.1",
|
|
27
|
+
"@postman/tough-cookie": "~4.1.3-postman.1",
|
|
28
|
+
"@postman/tunnel-agent": "^0.6.8",
|
|
29
|
+
"aws-sign2": "~0.7.0",
|
|
30
|
+
"aws4": "^1.12.0",
|
|
31
|
+
"caseless": "~0.12.0",
|
|
32
|
+
"combined-stream": "~1.0.6",
|
|
33
|
+
"extend": "~3.0.2",
|
|
34
|
+
"forever-agent": "~0.6.1",
|
|
35
|
+
"http-signature": "~1.4.0",
|
|
36
|
+
"is-typedarray": "~1.0.0",
|
|
37
|
+
"isstream": "~0.1.2",
|
|
38
|
+
"json-stringify-safe": "~5.0.1",
|
|
39
|
+
"mime-types": "^2.1.35",
|
|
40
|
+
"oauth-sign": "~0.9.0",
|
|
41
|
+
"qs": "~6.14.1",
|
|
42
|
+
"safe-buffer": "^5.1.2",
|
|
43
|
+
"socks-proxy-agent": "^8.0.5",
|
|
44
|
+
"stream-length": "^1.0.2",
|
|
45
|
+
"uuid": "^8.3.2"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"test": "npm run lint && npm run test-ci && npm run test-browser",
|
|
49
|
+
"test-ci": "taper tests/test-*.js",
|
|
50
|
+
"test-cov": "istanbul cover tape tests/test-*.js",
|
|
51
|
+
"test-browser": "node tests/browser/start.js",
|
|
52
|
+
"lint": "standard"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"bluebird": "^3.2.1",
|
|
56
|
+
"browserify": "^16.5.2",
|
|
57
|
+
"browserify-istanbul": "^3.0.0",
|
|
58
|
+
"buffer-equal": "^1.0.1",
|
|
59
|
+
"codecov": "^3.0.4",
|
|
60
|
+
"coveralls": "^3.0.2",
|
|
61
|
+
"function-bind": "^1.0.2",
|
|
62
|
+
"istanbul": "^0.4.0",
|
|
63
|
+
"karma": "^6.4.4",
|
|
64
|
+
"karma-browserify": "^8.1.0",
|
|
65
|
+
"karma-chrome-launcher": "^3.1.1",
|
|
66
|
+
"karma-cli": "^2.0.0",
|
|
67
|
+
"karma-coverage": "^2.2.1",
|
|
68
|
+
"karma-tap": "^4.2.0",
|
|
69
|
+
"postman-url-encoder": "^3.0.6",
|
|
70
|
+
"puppeteer": "^1.20.0",
|
|
71
|
+
"rimraf": "^2.2.8",
|
|
72
|
+
"server-destroy": "^1.0.1",
|
|
73
|
+
"standard": "^9.0.0",
|
|
74
|
+
"tape": "^4.6.0",
|
|
75
|
+
"taper": "^0.5.0"
|
|
76
|
+
}
|
|
77
|
+
}
|