1 | var _ = require('underscore');
|
2 | var xhr = require('xhr');
|
3 | var qs = require('qs');
|
4 |
|
5 |
|
6 |
|
7 | var urlError = function () {
|
8 | throw new Error('A "url" property or function must be specified');
|
9 | };
|
10 |
|
11 |
|
12 | module.exports = function (method, model, options) {
|
13 | var type = methodMap[method];
|
14 | var headers = {};
|
15 |
|
16 |
|
17 | _.defaults(options || (options = {}), {
|
18 | emulateHTTP: false,
|
19 | emulateJSON: false
|
20 | });
|
21 |
|
22 |
|
23 | var params = {type: type};
|
24 |
|
25 |
|
26 | if (!options.url) {
|
27 | params.url = _.result(model, 'url') || urlError();
|
28 | }
|
29 |
|
30 |
|
31 | if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
|
32 | params.json = options.attrs || model.toJSON(options);
|
33 | }
|
34 |
|
35 |
|
36 | if (options.data && type === 'GET') {
|
37 |
|
38 | params.url += _.contains(params.url, '?') ? '&' : '?';
|
39 | params.url += qs.stringify(options.data);
|
40 | }
|
41 |
|
42 |
|
43 | if (options.emulateJSON) {
|
44 | headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
45 | params.body = params.json ? {model: params.json} : {};
|
46 | delete params.json;
|
47 | }
|
48 |
|
49 |
|
50 |
|
51 | if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
|
52 | params.type = 'POST';
|
53 | if (options.emulateJSON) params.body._method = type;
|
54 | headers['X-HTTP-Method-Override'] = type;
|
55 | }
|
56 |
|
57 |
|
58 |
|
59 | if (options.emulateJSON) {
|
60 | params.body = qs.stringify(params.body);
|
61 | }
|
62 |
|
63 |
|
64 | var ajaxConfig = (_.result(model, 'ajaxConfig') || {});
|
65 |
|
66 |
|
67 | if (ajaxConfig.headers) {
|
68 | _.extend(headers, ajaxConfig.headers);
|
69 | }
|
70 | params.headers = headers;
|
71 |
|
72 |
|
73 | if (ajaxConfig.useXDR) {
|
74 | params.useXDR = true;
|
75 | }
|
76 |
|
77 |
|
78 | if (ajaxConfig.xhrFields) {
|
79 | var beforeSend = ajaxConfig.beforeSend;
|
80 | params.beforeSend = function (req) {
|
81 | for (var key in ajaxConfig.xhrFields) {
|
82 | req[key] = ajaxConfig.xhrFields[key];
|
83 | }
|
84 | if (beforeSend) return beforeSend.apply(this, arguments);
|
85 | };
|
86 | params.xhrFields = ajaxConfig.xhrFields;
|
87 | }
|
88 |
|
89 |
|
90 | params.method = params.type;
|
91 |
|
92 | var ajaxSettings = _.extend(params, options);
|
93 |
|
94 |
|
95 |
|
96 | var request = options.xhr = xhr(ajaxSettings, function (err, resp, body) {
|
97 | if (err && options.error) return options.error(resp, 'error', err.message);
|
98 |
|
99 |
|
100 | if (body && typeof body === 'string') {
|
101 | try {
|
102 | body = JSON.parse(body);
|
103 | } catch (e) {}
|
104 | }
|
105 | if (options.success) return options.success(body, 'success', resp);
|
106 | });
|
107 | model.trigger('request', model, request, options, ajaxSettings);
|
108 | request.ajaxSettings = ajaxSettings;
|
109 | return request;
|
110 | };
|
111 |
|
112 |
|
113 | var methodMap = {
|
114 | 'create': 'POST',
|
115 | 'update': 'PUT',
|
116 | 'patch': 'PATCH',
|
117 | 'delete': 'DELETE',
|
118 | 'read': 'GET'
|
119 | };
|