http-browser
Version:
http jstool example
244 lines (195 loc) • 6.33 kB
JavaScript
// 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;