-
Notifications
You must be signed in to change notification settings - Fork 633
/
request.js
97 lines (86 loc) · 3.42 KB
/
request.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
const zlib = require('zlib')
const http = require('http')
const https = require('https')
const parse = require('url').parse
const translate = host => (global.hosts || {})[host] || host
const create = (url, proxy) => (proxy = (typeof(proxy) === 'undefined' ? global.proxy : proxy)) ? (proxy.protocol == 'https:' ? https.request : http.request) : (url.protocol == 'https:' ? https.request : http.request)
const configure = (method, url, headers, proxy) => {
headers = headers || {}
proxy = typeof(proxy) === 'undefined' ? global.proxy : proxy
if('content-length' in headers) delete headers['content-length']
let options = {}
options._headers = headers
if(proxy && url.protocol == 'https:'){
options.method = 'CONNECT'
options.headers = Object.keys(headers).filter(key => ['host', 'user-agent'].includes(key)).reduce((result, key) => Object.assign(result, {[key]: headers[key]}), {})
}
else{
options.method = method
options.headers = headers
}
if(proxy){
options.hostname = translate(proxy.hostname)
options.port = proxy.port || ((proxy.protocol == 'https:') ? 443 : 80)
options.path = (url.protocol != 'https:') ? ('http://' + translate(url.hostname) + url.path) : (translate(url.hostname) + ':' + (url.port || 443))
}
else{
options.hostname = translate(url.hostname)
options.port = url.port || ((url.protocol == 'https:') ? 443 : 80)
options.path = url.path
}
return options
}
const request = (method, url, headers, body, proxy) => {
url = parse(url)
let options = configure(method, url, Object.assign({
'host': url.hostname,
'accept': 'application/json, text/plain, */*',
'accept-encoding': 'gzip, deflate',
'accept-language': 'zh-CN,zh;q=0.9',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
}, headers), proxy)
return new Promise((resolve, reject) => {
create(url, proxy)(options)
.on('response', response => resolve(response))
.on('connect', (_, socket) =>
https.request({
method: method,
host: translate(url.hostname),
path: url.path,
headers: options._headers,
socket: socket,
agent: false
})
.on('response', response => resolve(response))
.on('error', error => reject(error))
.end(body)
)
.on('error', error => reject(error))
.end(options.method.toUpperCase() === 'CONNECT' ? null : body)
})
.then(response => {
if([201, 301, 302, 303, 307, 308].includes(response.statusCode))
return request(method, url.resolve(response.headers.location), (delete headers.host, headers), body, proxy)
else
return Object.assign(response, {url: url, body: raw => read(response, raw), json: () => json(response), jsonp: () => jsonp(response)})
})
}
const read = (connect, raw) =>
new Promise((resolve, reject) => {
let chunks = []
connect
.on('data', chunk => chunks.push(chunk))
.on('end', () => resolve(Buffer.concat(chunks)))
.on('error', error => reject(error))
})
.then(buffer => {
buffer = (buffer.length && ['gzip', 'deflate'].includes(connect.headers['content-encoding'])) ? zlib.unzipSync(buffer) : buffer
return raw == true ? buffer : buffer.toString()
})
const json = connect => read(connect, false).then(body => JSON.parse(body))
const jsonp = connect => read(connect, false).then(body => JSON.parse(body.slice(body.indexOf('(') + 1, -')'.length)))
request.read = read
request.create = create
request.translate = translate
request.configure = configure
module.exports = request