httpism
Version:
HTTP client with middleware and good defaults
115 lines (92 loc) • 2.75 kB
JavaScript
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
})