request-easy-validator 1.0.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/LICENSE +55 -0
- package/README.md +1133 -0
- package/index.js +200 -0
- package/lib/auth.js +167 -0
- package/lib/callers.js +32 -0
- package/lib/constants.js +28 -0
- package/lib/cookies.js +38 -0
- package/lib/getProxyFromURI.js +79 -0
- package/lib/har.js +205 -0
- package/lib/hawk.js +89 -0
- package/lib/helpers.js +66 -0
- package/lib/multipart.js +112 -0
- package/lib/oauth.js +148 -0
- package/lib/querystring.js +50 -0
- package/lib/redirect.js +154 -0
- package/lib/tunnel.js +175 -0
- package/package.json +84 -0
- package/request.js +1553 -0
package/lib/redirect.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var url = require('url')
|
|
4
|
+
var isUrl = /^https?:/
|
|
5
|
+
|
|
6
|
+
function Redirect (request) {
|
|
7
|
+
this.request = request
|
|
8
|
+
this.followRedirect = true
|
|
9
|
+
this.followRedirects = true
|
|
10
|
+
this.followAllRedirects = false
|
|
11
|
+
this.followOriginalHttpMethod = false
|
|
12
|
+
this.allowRedirect = function () { return true }
|
|
13
|
+
this.maxRedirects = 10
|
|
14
|
+
this.redirects = []
|
|
15
|
+
this.redirectsFollowed = 0
|
|
16
|
+
this.removeRefererHeader = false
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Redirect.prototype.onRequest = function (options) {
|
|
20
|
+
var self = this
|
|
21
|
+
|
|
22
|
+
if (options.maxRedirects !== undefined) {
|
|
23
|
+
self.maxRedirects = options.maxRedirects
|
|
24
|
+
}
|
|
25
|
+
if (typeof options.followRedirect === 'function') {
|
|
26
|
+
self.allowRedirect = options.followRedirect
|
|
27
|
+
}
|
|
28
|
+
if (options.followRedirect !== undefined) {
|
|
29
|
+
self.followRedirects = !!options.followRedirect
|
|
30
|
+
}
|
|
31
|
+
if (options.followAllRedirects !== undefined) {
|
|
32
|
+
self.followAllRedirects = options.followAllRedirects
|
|
33
|
+
}
|
|
34
|
+
if (self.followRedirects || self.followAllRedirects) {
|
|
35
|
+
self.redirects = self.redirects || []
|
|
36
|
+
}
|
|
37
|
+
if (options.removeRefererHeader !== undefined) {
|
|
38
|
+
self.removeRefererHeader = options.removeRefererHeader
|
|
39
|
+
}
|
|
40
|
+
if (options.followOriginalHttpMethod !== undefined) {
|
|
41
|
+
self.followOriginalHttpMethod = options.followOriginalHttpMethod
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
Redirect.prototype.redirectTo = function (response) {
|
|
46
|
+
var self = this
|
|
47
|
+
var request = self.request
|
|
48
|
+
|
|
49
|
+
var redirectTo = null
|
|
50
|
+
if (response.statusCode >= 300 && response.statusCode < 400 && response.caseless.has('location')) {
|
|
51
|
+
var location = response.caseless.get('location')
|
|
52
|
+
request.debug('redirect', location)
|
|
53
|
+
|
|
54
|
+
if (self.followAllRedirects) {
|
|
55
|
+
redirectTo = location
|
|
56
|
+
} else if (self.followRedirects) {
|
|
57
|
+
switch (request.method) {
|
|
58
|
+
case 'PATCH':
|
|
59
|
+
case 'PUT':
|
|
60
|
+
case 'POST':
|
|
61
|
+
case 'DELETE':
|
|
62
|
+
// Do not follow redirects
|
|
63
|
+
break
|
|
64
|
+
default:
|
|
65
|
+
redirectTo = location
|
|
66
|
+
break
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} else if (response.statusCode === 401) {
|
|
70
|
+
var authHeader = request._auth.onResponse(response)
|
|
71
|
+
if (authHeader) {
|
|
72
|
+
request.setHeader('authorization', authHeader)
|
|
73
|
+
redirectTo = request.uri
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return redirectTo
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
Redirect.prototype.onResponse = function (response) {
|
|
80
|
+
var self = this
|
|
81
|
+
var request = self.request
|
|
82
|
+
|
|
83
|
+
var redirectTo = self.redirectTo(response)
|
|
84
|
+
if (!redirectTo || !self.allowRedirect.call(request, response)) {
|
|
85
|
+
return false
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
request.debug('redirect to', redirectTo)
|
|
89
|
+
|
|
90
|
+
// ignore any potential response body. it cannot possibly be useful
|
|
91
|
+
// to us at this point.
|
|
92
|
+
// response.resume should be defined, but check anyway before calling. Workaround for browserify.
|
|
93
|
+
if (response.resume) {
|
|
94
|
+
response.resume()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (self.redirectsFollowed >= self.maxRedirects) {
|
|
98
|
+
request.emit('error', new Error('Exceeded maxRedirects. Probably stuck in a redirect loop ' + request.uri.href))
|
|
99
|
+
return false
|
|
100
|
+
}
|
|
101
|
+
self.redirectsFollowed += 1
|
|
102
|
+
|
|
103
|
+
if (!isUrl.test(redirectTo)) {
|
|
104
|
+
redirectTo = url.resolve(request.uri.href, redirectTo)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
var uriPrev = request.uri
|
|
108
|
+
request.uri = url.parse(redirectTo)
|
|
109
|
+
|
|
110
|
+
// handle the case where we change protocol from https to http or vice versa
|
|
111
|
+
if (request.uri.protocol !== uriPrev.protocol) {
|
|
112
|
+
delete request.agent
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
self.redirects.push({ statusCode: response.statusCode, redirectUri: redirectTo })
|
|
116
|
+
|
|
117
|
+
if (self.followAllRedirects && request.method !== 'HEAD' &&
|
|
118
|
+
response.statusCode !== 401 && response.statusCode !== 307) {
|
|
119
|
+
request.method = self.followOriginalHttpMethod ? request.method : 'GET'
|
|
120
|
+
}
|
|
121
|
+
// request.method = 'GET' // Force all redirects to use GET || commented out fixes #215
|
|
122
|
+
delete request.src
|
|
123
|
+
delete request.req
|
|
124
|
+
delete request._started
|
|
125
|
+
if (response.statusCode !== 401 && response.statusCode !== 307) {
|
|
126
|
+
// Remove parameters from the previous response, unless this is the second request
|
|
127
|
+
// for a server that requires digest authentication.
|
|
128
|
+
delete request.body
|
|
129
|
+
delete request._form
|
|
130
|
+
if (request.headers) {
|
|
131
|
+
request.removeHeader('host')
|
|
132
|
+
request.removeHeader('content-type')
|
|
133
|
+
request.removeHeader('content-length')
|
|
134
|
+
if (request.uri.hostname !== request.originalHost.split(':')[0]) {
|
|
135
|
+
// Remove authorization if changing hostnames (but not if just
|
|
136
|
+
// changing ports or protocols). This matches the behavior of curl:
|
|
137
|
+
// https://github.com/bagder/curl/blob/6beb0eee/lib/http.c#L710
|
|
138
|
+
request.removeHeader('authorization')
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!self.removeRefererHeader) {
|
|
144
|
+
request.setHeader('referer', uriPrev.href)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
request.emit('redirect')
|
|
148
|
+
|
|
149
|
+
request.init()
|
|
150
|
+
|
|
151
|
+
return true
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
exports.Redirect = Redirect
|
package/lib/tunnel.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var url = require('url')
|
|
4
|
+
var tunnel = require('tunnel-agent')
|
|
5
|
+
|
|
6
|
+
var defaultProxyHeaderWhiteList = [
|
|
7
|
+
'accept',
|
|
8
|
+
'accept-charset',
|
|
9
|
+
'accept-encoding',
|
|
10
|
+
'accept-language',
|
|
11
|
+
'accept-ranges',
|
|
12
|
+
'cache-control',
|
|
13
|
+
'content-encoding',
|
|
14
|
+
'content-language',
|
|
15
|
+
'content-location',
|
|
16
|
+
'content-md5',
|
|
17
|
+
'content-range',
|
|
18
|
+
'content-type',
|
|
19
|
+
'connection',
|
|
20
|
+
'date',
|
|
21
|
+
'expect',
|
|
22
|
+
'max-forwards',
|
|
23
|
+
'pragma',
|
|
24
|
+
'referer',
|
|
25
|
+
'te',
|
|
26
|
+
'user-agent',
|
|
27
|
+
'via'
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
var defaultProxyHeaderExclusiveList = [
|
|
31
|
+
'proxy-authorization'
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
function constructProxyHost (uriObject) {
|
|
35
|
+
var port = uriObject.port
|
|
36
|
+
var protocol = uriObject.protocol
|
|
37
|
+
var proxyHost = uriObject.hostname + ':'
|
|
38
|
+
|
|
39
|
+
if (port) {
|
|
40
|
+
proxyHost += port
|
|
41
|
+
} else if (protocol === 'https:') {
|
|
42
|
+
proxyHost += '443'
|
|
43
|
+
} else {
|
|
44
|
+
proxyHost += '80'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return proxyHost
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function constructProxyHeaderWhiteList (headers, proxyHeaderWhiteList) {
|
|
51
|
+
var whiteList = proxyHeaderWhiteList
|
|
52
|
+
.reduce(function (set, header) {
|
|
53
|
+
set[header.toLowerCase()] = true
|
|
54
|
+
return set
|
|
55
|
+
}, {})
|
|
56
|
+
|
|
57
|
+
return Object.keys(headers)
|
|
58
|
+
.filter(function (header) {
|
|
59
|
+
return whiteList[header.toLowerCase()]
|
|
60
|
+
})
|
|
61
|
+
.reduce(function (set, header) {
|
|
62
|
+
set[header] = headers[header]
|
|
63
|
+
return set
|
|
64
|
+
}, {})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function constructTunnelOptions (request, proxyHeaders) {
|
|
68
|
+
var proxy = request.proxy
|
|
69
|
+
|
|
70
|
+
var tunnelOptions = {
|
|
71
|
+
proxy: {
|
|
72
|
+
host: proxy.hostname,
|
|
73
|
+
port: +proxy.port,
|
|
74
|
+
proxyAuth: proxy.auth,
|
|
75
|
+
headers: proxyHeaders
|
|
76
|
+
},
|
|
77
|
+
headers: request.headers,
|
|
78
|
+
ca: request.ca,
|
|
79
|
+
cert: request.cert,
|
|
80
|
+
key: request.key,
|
|
81
|
+
passphrase: request.passphrase,
|
|
82
|
+
pfx: request.pfx,
|
|
83
|
+
ciphers: request.ciphers,
|
|
84
|
+
rejectUnauthorized: request.rejectUnauthorized,
|
|
85
|
+
secureOptions: request.secureOptions,
|
|
86
|
+
secureProtocol: request.secureProtocol
|
|
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 = url.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/package.json
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "request-easy-validator",
|
|
3
|
+
"description": "Simplified HTTP request client.",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"http",
|
|
6
|
+
"simple",
|
|
7
|
+
"util",
|
|
8
|
+
"utility"
|
|
9
|
+
],
|
|
10
|
+
"version": "1.0.5",
|
|
11
|
+
"author": "FuwFinch",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "http://github.com/request/request/issues"
|
|
14
|
+
},
|
|
15
|
+
"license": "Apache-2.0",
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">= 6"
|
|
18
|
+
},
|
|
19
|
+
"main": "index.js",
|
|
20
|
+
"files": [
|
|
21
|
+
"lib/",
|
|
22
|
+
"index.js",
|
|
23
|
+
"request.js",
|
|
24
|
+
"caller.js"
|
|
25
|
+
],
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"aws-sign2": "~0.7.0",
|
|
28
|
+
"aws4": "^1.8.0",
|
|
29
|
+
"axios": "^1.14.0",
|
|
30
|
+
"caseless": "~0.12.0",
|
|
31
|
+
"combined-stream": "~1.0.6",
|
|
32
|
+
"extend": "~3.0.2",
|
|
33
|
+
"forever-agent": "~0.6.1",
|
|
34
|
+
"form-data": "~2.3.2",
|
|
35
|
+
"har-validator": "~5.1.3",
|
|
36
|
+
"http-signature": "~1.2.0",
|
|
37
|
+
"is-typedarray": "~1.0.0",
|
|
38
|
+
"isstream": "~0.1.2",
|
|
39
|
+
"json-stringify-safe": "~5.0.1",
|
|
40
|
+
"mime-types": "~2.1.19",
|
|
41
|
+
"oauth-sign": "~0.9.0",
|
|
42
|
+
"performance-now": "^2.1.0",
|
|
43
|
+
"qs": "~6.5.2",
|
|
44
|
+
"safe-buffer": "^5.1.2",
|
|
45
|
+
"tough-cookie": "~2.5.0",
|
|
46
|
+
"tunnel-agent": "^0.6.0",
|
|
47
|
+
"uuid": "^3.3.2"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"test": "npm run lint && npm run test-ci && npm run test-browser",
|
|
51
|
+
"test-ci": "taper tests/test-*.js",
|
|
52
|
+
"test-cov": "nyc --reporter=lcov tape tests/test-*.js",
|
|
53
|
+
"test-browser": "node tests/browser/start.js",
|
|
54
|
+
"lint": "standard"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"bluebird": "^3.2.1",
|
|
58
|
+
"browserify": "^13.0.1",
|
|
59
|
+
"browserify-istanbul": "^2.0.0",
|
|
60
|
+
"buffer-equal": "^1.0.0",
|
|
61
|
+
"codecov": "^3.0.4",
|
|
62
|
+
"coveralls": "^3.0.2",
|
|
63
|
+
"function-bind": "^1.0.2",
|
|
64
|
+
"karma": "^3.0.0",
|
|
65
|
+
"karma-browserify": "^5.0.1",
|
|
66
|
+
"karma-cli": "^1.0.0",
|
|
67
|
+
"karma-coverage": "^1.0.0",
|
|
68
|
+
"karma-phantomjs-launcher": "^1.0.0",
|
|
69
|
+
"karma-tap": "^3.0.1",
|
|
70
|
+
"nyc": "^14.1.1",
|
|
71
|
+
"phantomjs-prebuilt": "^2.1.3",
|
|
72
|
+
"rimraf": "^2.2.8",
|
|
73
|
+
"server-destroy": "^1.0.1",
|
|
74
|
+
"standard": "^9.0.0",
|
|
75
|
+
"tape": "^4.6.0",
|
|
76
|
+
"taper": "^0.5.0"
|
|
77
|
+
},
|
|
78
|
+
"greenkeeper": {
|
|
79
|
+
"ignore": [
|
|
80
|
+
"hawk",
|
|
81
|
+
"har-validator"
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
}
|