-
Notifications
You must be signed in to change notification settings - Fork 2
/
xhr.js
114 lines (92 loc) · 2.69 KB
/
xhr.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
var middleware = require('./middleware')
function toUpperCase (x) {
return x.toUpperCase()
}
function formatHeaderName (name) {
return name.replace(/^([a-z])/, toUpperCase).replace(/-([a-z])/g, toUpperCase)
}
function setHeaders (headers, xhr) {
var headerNames = Object.keys(headers)
for (var n = 0; n < headerNames.length; n++) {
var key = headerNames[n]
var headerName = formatHeaderName(key)
xhr.setRequestHeader(headerName, headers[key])
}
}
function isCrossDomain (url) {
return /^https?:\/\//.test(url)
}
function responseUrl (xhr, requestUrl) {
var origin = window.location.origin
var responseUrl = xhr.responseURL
if (responseUrl) {
if (responseUrl.substring(0, origin.length) === origin) {
return responseUrl.substring(origin.length)
} else {
return responseUrl
}
} else {
return requestUrl
}
}
function parseHeaders (headers) {
var object = {}
var lines = headers.split('\n')
for (var n = 0; n < lines.length; n++) {
var line = lines[n]
var match = /^(.*?):(.*)/.exec(line)
if (match) {
object[match[1].toLowerCase()] = match[2].trim()
}
}
return object
}
function addAbortToPromise (promise, abort) {
var then = promise.then
promise.then = function () {
var p = then.apply(this, arguments)
p.abort = abort
addAbortToPromise(p, abort)
return p
}
}
module.exports = middleware('xhr', function (request) {
var Xhr = request.options.xhr || window.XMLHttpRequest
var xhr = new Xhr()
var rejectPromise
var promise = new Promise(function (resolve, reject) {
rejectPromise = reject
xhr.open(request.method, request.url, true)
xhr.onload = function () {
var statusCode = xhr.status
var body = statusCode === 204 ? undefined : xhr.responseText
var response = {
body: body,
stringBody: body,
headers: parseHeaders(xhr.getAllResponseHeaders()),
statusCode: statusCode,
url: responseUrl(xhr, request.url),
xhr: xhr,
statusText: xhr.statusText
}
resolve(response)
}
xhr.onerror = function () {
rejectPromise(new Error('failed to connect to ' + request.method + ' ' + request.url))
}
if (!isCrossDomain(request.url) && !request.headers['x-requested-with']) {
request.headers['x-requested-with'] = 'XMLHttpRequest'
}
setHeaders(request.headers, xhr)
xhr.withCredentials = !!request.options.withCredentials
xhr.send(request.body)
})
function abort () {
xhr.abort()
var error = new Error('aborted connection to ' + request.method + ' ' + request.url)
error.aborted = true
rejectPromise(error)
}
addAbortToPromise(promise, abort)
return promise
})