-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhttp.js
160 lines (116 loc) · 3.07 KB
/
http.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
var mime = require('./mime.js');
function toBase64(str) {
return window.btoa(str);
}
function createXhr(cors) {
if (!window.XMLHttpRequest) {
throw new Error('This browser does not support XMLHttpRequest');
}
var xhr = new window.XMLHttpRequest();
if (!cors) {
return xhr;
}
if ('withCredentials' in xhr) {
// XHR is CORS compatible (not supported by IE)
return xhr;
}
if (window.XDomainRequest) {
// XDomainRequest for IE.
return new window.XDomainRequest();
}
throw new Error('This browser is not compatible with cross domain origin requests');
}
function send(xhr, url, options, cb) {
var cors = options.cors;
var timeout = options.timeout;
var timer;
var aborting = false;
function onLoad() {
if (aborting || !cb) {
return;
}
if (timer) {
clearTimeout(timer);
timer = null;
}
var code = xhr.status;
if (!code && code !== 0) {
code = 200; // default to 200 since there is no status property on XDomainRequest
}
var contentType = mime.parse(xhr.contentType || xhr.getResponseHeader('content-type'));
var response = {
code: code,
data: xhr.responseText,
contentType: contentType.type,
charset: contentType.charset
};
// HTTP status codes:
// 0 is a network issue
// 100-199 is informational, we should not get these
// 200-299 is success
// 300-399 is redirection which XHR handles before returning
// 400-499 is client/request error which we must deal with
// 500-599 is server error which we must deal with
if (code === 0) {
// network error
return cb(new Error('Network issue'), response);
}
if (code >= 400 && code <= 499) {
// client/request error
return cb(new Error('Request failed'), response);
}
if (code >= 500 && code <= 599) {
// server error
if (code === 503) {
return cb(new Error('Server in maintenance'), response);
}
return cb(new Error('Server error'), response);
}
// success
return cb(null, response);
}
function onTimeout() {
timer = null;
aborting = true;
xhr.abort();
if (cb) {
cb(new Error('Request timed out'));
cb = null;
}
}
// PhantomJS cannot be trusted with onload, so we try onreadystatechange first
if ('onreadystatechange' in xhr) {
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
onLoad();
}
};
} else if ('onload' in xhr) {
xhr.onload = onLoad;
} else {
return cb(new Error('XHR object exposes no load-event or readystatechange-event'));
}
if (timeout) {
timer = setTimeout(onTimeout, timeout);
}
xhr.open('GET', url, true);
if (cors && cors.credentials && 'withCredentials' in xhr) {
xhr.withCredentials = true;
}
if ('setRequestHeader' in xhr) {
xhr.setRequestHeader('Cache-Control', 'no-cache');
// add basic auth if provided
var m = url.match(/^[a-z]+:(\/\/)([^:]+:[^:]+)@/i);
if (m) {
xhr.setRequestHeader('Authorization', 'Basic ' + toBase64(m[2]));
}
}
xhr.send(null);
}
exports.createRequest = function (url, options) {
options = options || {};
var xhr = createXhr(options.cors);
return function (cb) {
send(xhr, url, options, cb);
};
};