UNPKG

http-browser

Version:
244 lines (195 loc) 6.33 kB
// factory http var Parole = require('parole'), _ = require('nitro-tools/extend'); function resolveFunctions (o, args, thisArg) { for( var key in o ) { if( o[key] instanceof Function ) { o[key] = o[key].apply(thisArg, args || []); } else if( typeof o[key] === 'object' && o[key] !== null ) { o[key] = resolveFunctions(o[key], args, thisArg); } } return o; } function headerToTitleSlug(text) { // console.log('headerToTitleSlug', text); var key = text.replace(/([a-z])([A-Z])/g, function (match, lower, upper) { return lower + '-' + upper; }); key = key[0].toUpperCase() + key.substr(1); return key; } function headerToCamelCase(text) { var key = text[0].toLowerCase() + text.substr(1); return key.replace(/([a-z])-([A-Z])/g, function (match, lower, upper) { return lower + upper; }); } var RE_contentType = /([^\/]+)\/([^+]+\+)?([^;]*)/; function parseContentType(contentType, text, xml) { var matches = contentType && contentType.match(RE_contentType); return matches && ( matches[3] === 'json' ? JSON.parse(text) : ( matches[3] === 'xml' ? xml : text ) ); } function _getHeaders (request) { var headers = {}; request.getAllResponseHeaders().replace(/\s*([^\:]+)\s*\:\s*([^\;\n]+)/g, function (match, key, value) { headers[headerToCamelCase(key)] = value.trim(); }); return headers; } function headersGetter (request) { var headersCache; return function () { if( !headersCache ) { headersCache = _getHeaders(request); } return headersCache; }; } function serializeParams (params) { var result = ''; for( var param in params ) { result += ( result ? '&' : '' ) + param + '=' + encodeURIComponent(params[param]); } return result; } function addHeadersToRequest (req, headers) { for( var key in headers ) { req.setRequestHeader( headerToTitleSlug(key), headers[key] ); } } var defaultSettings = {}; http.config = function (settings) { _.merge(defaultSettings, settings); return http; }; function http (url, config) { if( config === undefined && typeof url === 'object' && url !== null ) { config = url; url = config.url; } else { config = config || {}; config.url = url; } config = _.merge(_.copy(defaultSettings),_.copy(config)); config = resolveFunctions( config, [config], null ); config.method = ( config.method || 'GET').toUpperCase(); if( typeof config.url !== 'string' ) { throw new Error('url should be a string'); } return new Parole(function (resolve, reject) { var request = null; try { // Firefox, Opera 8.0+, Safari request = new XMLHttpRequest(); } catch (e) { // Internet Explorer try { request = new ActiveXObject('Msxml2.XMLHTTP'); } // jshint ignore:line catch (er) { request = new ActiveXObject('Microsoft.XMLHTTP'); } // jshint ignore:line } if( request === null ) { throw 'Browser does not support HTTP Request'; } if( config.params ) { url += ( /\?/.test(url) ? '&' : '?' ) + serializeParams( config.params ); } request.open( config.method, url ); if( config.withCredentials ) { request.withCredentials = true; } addHeadersToRequest(request, config.headers || {} ); request.config = config; config.start = new Date().getTime(); request.onreadystatechange = function(){ if( request.readyState === 'complete' || request.readyState === 4 ) { var response = { config: config, data: parseContentType(request.getResponseHeader('content-type'), request.responseText, request.responseXML), status: request.status, headers: headersGetter(request), xhr: request }; if( request.status >= 200 && request.status < 400 ) { resolve( response ); } else { reject( response ); } } }; if( config.contentType ) { if( config.data && config.contentType === 'application/json' && typeof config.data !== 'string' ) { config.data = JSON.stringify(config.data); } } else if( config.data instanceof FormData ) { config.contentType = 'multipart/form-data'; } else if( typeof config.data === 'object' && config.data !== null ) { config.contentType = 'application/json'; if( config.data ) { config.data = JSON.stringify(config.data); } } if( config.contentType ) { // addHeadersToRequest(request, { contentType: config.contentType }); request.setRequestHeader( 'Content-Type', config.contentType ); } request.send( config.data ); }); } http.serialize = serializeParams; http.noCache = function (url, config) { url += ( /\?/.test(url) ? '&' : '?' ) + 't=' + new Date().getTime(); return http(url, config); }; http.plainResponse = function (response) { return { config: response.config, data: response.data, status: response.status, headers: response.headers() }; }; ['get', 'delete'].forEach(function (method) { http[method] = function (url, config) { return http(url, _.extend(_.copy(config || {}), { method: method })); }; }); ['post', 'put', 'patch'].forEach(function (method) { http[method] = function (url, data, config) { return http(url, _.extend(_.copy(config || {}), { method: method, data: data || {} })); }; }); // basePath function basePath (bp) { if( /\/$/.test(bp) ) { bp = bp.replace(/\/$/,''); } return function (p) { if( !p ) { return bp; } return bp + ( /^\//.test(p) ? '' : '/' ) + p; }; } http.base = function (url, baseConfig) { var bp = basePath(url), based = function () { return based.get.apply(this, arguments); }; baseConfig = baseConfig || {}; ['get', 'delete'].forEach(function (method) { based[method] = function (p, _config ) { return http( bp(p), _.merge(_.copy(baseConfig), _config, { method: method })); }; }); ['post', 'put', 'patch'].forEach(function (method) { based[method] = function (p, data, _config ) { return http( bp(p), _.merge(_.copy(baseConfig), _config, { method: method, data: data }) ); }; }); return based; }; http.responseData = function (response) { return response.data; }; module.exports = http;