Skip to content

Instantly share code, notes, and snippets.

@remixz
Created June 26, 2014 20:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save remixz/46b07c961f0cc3e10ad7 to your computer and use it in GitHub Desktop.
Save remixz/46b07c961f0cc3e10ad7 to your computer and use it in GitHub Desktop.
var _ = require('underscore');
var xhr = require('xhr');
var qs = require('qs');
// Throw an error when a URL is needed, and none is supplied.
var urlError = function () {
throw new Error('A "url" property or function must be specified');
};
module.exports = function (method, model, options) {
var type = methodMap[method];
var headers = {};
// Default options, unless specified.
_.defaults(options || (options = {}), {
emulateHTTP: false,
emulateJSON: false
});
// Default request options.
var params = {type: type, responseType: 'json'};
// Ensure that we have a URL.
if (!options.url) {
params.url = _.result(model, 'url') || urlError();
}
// Ensure that we have the appropriate request data.
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
params.json = options.attrs || model.toJSON(options);
}
// For older servers, emulate JSON by encoding the request into an HTML-form.
if (options.emulateJSON) {
headers['Content-Type'] = 'application/x-www-form-urlencoded';
params.body = params.json ? {model: params.json} : {};
if (params.json) delete params.json;
}
// For older servers, emulate HTTP by mimicking the HTTP method with `_method`
// And an `X-HTTP-Method-Override` header.
if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
params.type = 'POST';
if (options.emulateJSON) params.body._method = type;
headers['X-HTTP-Method-Override'] = type;
}
// When emulating JSON, we turn the body into a querystring.
// We do this later to let the emulateHTTP run its course.
if (options.emulateJSON) {
params.body = qs.stringify(params.body);
}
// Combine generated headers with user's headers.
if (options.headers) _.extend(headers, options.headers);
// Turn a jQuery.ajax formatted request into xhr compatible
params.method = params.type;
var ajaxSettings = _.extend(params, options);
// Make the request. The callback executes functions that are compatible
// With jQuery.ajax's syntax.
var _xhr = options.xhr = xhr(ajaxSettings, function (err, resp, body) {
if (err && options.error) return options.error(resp, 'error', err.message);
if (body && options.success) return options.success(body, 'success', resp);
});
model.trigger('request', model, _xhr, options, ajaxSettings);
return _xhr;
};
// Map from CRUD to HTTP for our default `Backbone.sync` implementation.
var methodMap = {
'create': 'POST',
'update': 'PUT',
'patch': 'PATCH',
'delete': 'DELETE',
'read': 'GET'
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment