blob: b8045bf843e6dbf58b6da375b2a9fda5c81a9ad0 [file] [log] [blame]
import request from './request';
import jsExtend from 'js-extend'; var extend = jsExtend.extend;
import { generateErrorFromResponse } from 'pouchdb-errors';
import { clone } from 'pouchdb-utils';
import applyTypeToBuffer from './applyTypeToBuffer';
import defaultBody from './defaultBody';
function ajaxCore(options, callback) {
options = clone(options);
var defaultOptions = {
method : "GET",
headers: {},
json: true,
processData: true,
timeout: 10000,
cache: false
};
options = extend(defaultOptions, options);
function onSuccess(obj, resp, cb) {
if (!options.binary && options.json && typeof obj === 'string') {
try {
obj = JSON.parse(obj);
} catch (e) {
// Probably a malformed JSON from server
return cb(e);
}
}
if (Array.isArray(obj)) {
obj = obj.map(function (v) {
if (v.error || v.missing) {
return generateErrorFromResponse(v);
} else {
return v;
}
});
}
if (options.binary) {
applyTypeToBuffer(obj, resp);
}
cb(null, obj, resp);
}
function onError(err, cb) {
var errParsed, errObj;
if (err.code && err.status) {
var err2 = new Error(err.message || err.code);
err2.status = err.status;
return cb(err2);
}
if (err.message && err.message === 'ETIMEDOUT') {
return cb(err);
}
// We always get code && status in node
/* istanbul ignore next */
try {
errParsed = JSON.parse(err.responseText);
//would prefer not to have a try/catch clause
errObj = generateErrorFromResponse(errParsed);
} catch (e) {
errObj = generateErrorFromResponse(err);
}
/* istanbul ignore next */
cb(errObj);
}
if (options.json) {
if (!options.binary) {
options.headers.Accept = 'application/json';
}
options.headers['Content-Type'] = options.headers['Content-Type'] ||
'application/json';
}
if (options.binary) {
options.encoding = null;
options.json = false;
}
if (!options.processData) {
options.json = false;
}
return request(options, function (err, response, body) {
if (err) {
err.status = response ? response.statusCode : 400;
return onError(err, callback);
}
var error;
var content_type = response.headers && response.headers['content-type'];
var data = body || defaultBody();
// CouchDB doesn't always return the right content-type for JSON data, so
// we check for ^{ and }$ (ignoring leading/trailing whitespace)
if (!options.binary && (options.json || !options.processData) &&
typeof data !== 'object' &&
(/json/.test(content_type) ||
(/^[\s]*\{/.test(data) && /\}[\s]*$/.test(data)))) {
try {
data = JSON.parse(data.toString());
} catch (e) {}
}
if (response.statusCode >= 200 && response.statusCode < 300) {
onSuccess(data, response, callback);
} else {
error = generateErrorFromResponse(data);
error.status = response.statusCode;
callback(error);
}
});
}
export default ajaxCore;