UNPKG

2.71 kBJavaScriptView Raw
1var middleware = require('./middleware')
2
3function toUpperCase (x) {
4 return x.toUpperCase()
5}
6
7function formatHeaderName (name) {
8 return name.replace(/^([a-z])/, toUpperCase).replace(/-([a-z])/g, toUpperCase)
9}
10
11function setHeaders (headers, xhr) {
12 var headerNames = Object.keys(headers)
13
14 for (var n = 0; n < headerNames.length; n++) {
15 var key = headerNames[n]
16 var headerName = formatHeaderName(key)
17 xhr.setRequestHeader(headerName, headers[key])
18 }
19}
20
21function isCrossDomain (url) {
22 return /^https?:\/\//.test(url)
23}
24
25function responseUrl (xhr, requestUrl) {
26 var origin = window.location.origin
27 var responseUrl = xhr.responseURL
28
29 if (responseUrl) {
30 if (responseUrl.substring(0, origin.length) === origin) {
31 return responseUrl.substring(origin.length)
32 } else {
33 return responseUrl
34 }
35 } else {
36 return requestUrl
37 }
38}
39
40function parseHeaders (headers) {
41 var object = {}
42 var lines = headers.split('\n')
43
44 for (var n = 0; n < lines.length; n++) {
45 var line = lines[n]
46 var match = /^(.*?):(.*)/.exec(line)
47
48 if (match) {
49 object[match[1].toLowerCase()] = match[2].trim()
50 }
51 }
52
53 return object
54}
55
56function addAbortToPromise (promise, abort) {
57 var then = promise.then
58 promise.then = function () {
59 var p = then.apply(this, arguments)
60 p.abort = abort
61 addAbortToPromise(p, abort)
62 return p
63 }
64}
65
66module.exports = middleware('xhr', function (request) {
67 var Xhr = request.options.xhr || window.XMLHttpRequest
68 var xhr = new Xhr()
69 var rejectPromise
70
71 var promise = new Promise(function (resolve, reject) {
72 rejectPromise = reject
73 xhr.open(request.method, request.url, true)
74 xhr.onload = function () {
75 var statusCode = xhr.status
76
77 var response = {
78 body: statusCode === 204 ? undefined : xhr.responseText,
79 headers: parseHeaders(xhr.getAllResponseHeaders()),
80 statusCode: statusCode,
81 url: responseUrl(xhr, request.url),
82 xhr: xhr,
83 statusText: xhr.statusText
84 }
85
86 resolve(response)
87 }
88
89 xhr.onerror = function () {
90 rejectPromise(new Error('failed to connect to ' + request.method + ' ' + request.url))
91 }
92
93 if (!isCrossDomain(request.url) && !request.headers['x-requested-with']) {
94 request.headers['x-requested-with'] = 'XMLHttpRequest'
95 }
96
97 setHeaders(request.headers, xhr)
98 xhr.withCredentials = !!request.options.withCredentials
99
100 xhr.send(request.body)
101 })
102
103 function abort () {
104 xhr.abort()
105 var error = new Error('aborted connection to ' + request.method + ' ' + request.url)
106 error.aborted = true
107 rejectPromise(error)
108 }
109 addAbortToPromise(promise, abort)
110
111 return promise
112})