From 764fe2b61912c79214f2f49959817b91c23b2e3a Mon Sep 17 00:00:00 2001 From: QuenTine Date: Mon, 21 Sep 2015 18:27:54 +0800 Subject: [PATCH 01/61] Add "options" parameter to resource creator. --- src/resource.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resource.js b/src/resource.js index af747382..5f6282d5 100644 --- a/src/resource.js +++ b/src/resource.js @@ -4,7 +4,7 @@ module.exports = function (_) { - function Resource(url, params, actions) { + function Resource(url, params, actions, options) { var self = this, resource = {}; @@ -15,7 +15,7 @@ module.exports = function (_) { _.each(actions, function (action, name) { - action = _.extend(true, {url: url, params: params || {}}, action); + action = _.extend(true, {url: url, params: params || {}}, options, action); resource[name] = function () { return (self.$http || _.http)(opts(action, arguments)); From 9c3ce072275e714a3b35a7e311647d372f44c0a7 Mon Sep 17 00:00:00 2001 From: Malte Date: Mon, 5 Oct 2015 11:16:53 +0200 Subject: [PATCH 02/61] Implemented request/response transforms --- dist/vue-resource.js | 106 +++++++++++++++++++++++++++++---------- dist/vue-resource.min.js | 2 +- src/http.js | 59 +++++++++++++--------- src/lib/transforms.js | 38 ++++++++++++++ 4 files changed, 152 insertions(+), 53 deletions(-) create mode 100644 src/lib/transforms.js diff --git a/dist/vue-resource.js b/dist/vue-resource.js index 1f48b107..298ef40b 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -8,7 +8,7 @@ if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) - define(factory); + define([], factory); else if(typeof exports === 'object') exports["VueResource"] = factory(); else @@ -70,7 +70,7 @@ return /******/ (function(modules) { // webpackBootstrap Vue.url = __webpack_require__(2)(_); Vue.http = __webpack_require__(3)(_); - Vue.resource = __webpack_require__(7)(_); + Vue.resource = __webpack_require__(8)(_); Object.defineProperties(Vue.prototype, { @@ -361,6 +361,7 @@ return /******/ (function(modules) { // webpackBootstrap var xhr = __webpack_require__(4); var jsonp = __webpack_require__(6); var Promise = __webpack_require__(5); + var Transforms = __webpack_require__(7); module.exports = function (_) { @@ -368,8 +369,7 @@ return /******/ (function(modules) { // webpackBootstrap var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; function Http(url, options) { - - var promise; + var vm = this.vm; if (_.isPlainObject(url)) { options = url; @@ -381,6 +381,14 @@ return /******/ (function(modules) { // webpackBootstrap Http.options, this.options, options ); + var transformRequest = function (options) { + return transform(Http.transforms.request, options.transformRequest, options, vm); + }; + + var transformResponse = function (response) { + return transform(Http.transforms.response, options.transformResponse, response, vm); + }; + if (options.crossOrigin === null) { options.crossOrigin = crossOrigin(options.url); } @@ -407,26 +415,22 @@ return /******/ (function(modules) { // webpackBootstrap options.data = _.url.params(options.data); } - if (_.isObject(options.data) && /FormData/i.test(options.data.toString())) { - delete options.headers['Content-Type']; - } + return extendPromise(transformRequest(options).then(function (options) { - if (_.isPlainObject(options.data)) { - options.data = JSON.stringify(options.data); - } + var promise = (options.method == 'JSONP' ? jsonp : xhr).call(vm, _, options); + promise = extendPromise(promise.then(transformResponse, transformResponse), vm); - promise = (options.method == 'JSONP' ? jsonp : xhr).call(this.vm, _, options); - promise = extendPromise(promise.then(transformResponse, transformResponse), this.vm); + if (options.success) { + promise = promise.success(options.success); + } - if (options.success) { - promise = promise.success(options.success); - } + if (options.error) { + promise = promise.error(options.error); + } - if (options.error) { - promise = promise.error(options.error); - } + return promise; - return promise; + }), vm); } function extendPromise(promise, vm) { @@ -459,15 +463,16 @@ return /******/ (function(modules) { // webpackBootstrap return promise; } - function transformResponse(response) { - - try { - response.data = JSON.parse(response.responseText); - } catch (e) { - response.data = response.responseText; + function transform(transforms, custom, arg, vm) { + if (custom) { + transforms = transforms.concat(custom instanceof Array ? custom : [custom]); } - return response.ok ? response : Promise.reject(response); + return transforms.reduce(function (sequence, transform) { + return sequence.then(function (arg) { + return transform.call(vm, arg); + }); + }, Promise.resolve(arg)); } function crossOrigin(url) { @@ -477,6 +482,8 @@ return /******/ (function(modules) { // webpackBootstrap return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); } + Http.transforms = Transforms.call(this, _); + Http.options = { method: 'get', params: {}, @@ -486,7 +493,9 @@ return /******/ (function(modules) { // webpackBootstrap beforeSend: null, crossOrigin: null, emulateHTTP: false, - emulateJSON: false + emulateJSON: false, + transformRequest: null, + transformResponse: null }; Http.headers = { @@ -847,6 +856,49 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 7 */ +/***/ function(module, exports, __webpack_require__) { + + var Promise = __webpack_require__(5); + + module.exports = function (_) { + return { + + request: [ + + function (options) { + + if (_.isObject(options.data) && /FormData/i.test(options.data.toString())) { + delete options.headers['Content-Type']; + } + + if (_.isPlainObject(options.data)) { + options.data = JSON.stringify(options.data); + } + + return options; + } + + ], + + response: [ + + function (response) { + try { + response.data = JSON.parse(response.responseText); + } catch (e) { + response.data = response.responseText; + } + + return response.ok ? response : Promise.reject(response); + } + + ] + + } + }; + +/***/ }, +/* 8 */ /***/ function(module, exports) { /** diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index 88ec5e30..842fc093 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -4,4 +4,4 @@ * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(7)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return this._url||(this._url=e.options(t.url,this,this.$options.url))}},$http:{get:function(){return this._http||(this._http=e.options(t.http,this,this.$options.http))}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var a in r)o&&(n.isPlainObject(r[a])||n.isArray(r[a]))?(n.isPlainObject(r[a])&&!n.isPlainObject(t[a])&&(t[a]={}),n.isArray(r[a])&&!n.isArray(t[a])&&(t[a]=[]),e(t[a],r[a],o)):void 0!==r[a]&&(t[a]=r[a])}var n=t.util.extend({},t.util);return n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&a.status<300),(a.ok?n:r)(a)};a.onload=o,a.onabort=o,a.onerror=o,a.send(e.data)})}},function(t,e){function n(t){this.state=a,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,a=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){a[n]=r,o+=1,o===t.length&&e(a)}}var o=0,a=[];0===t.length&&e(a);for(var i=0;i=200&&a.status<300),(a.ok?n:r)(a)};a.onload=o,a.onabort=o,a.onerror=o,a.send(e.data)})}},function(t,e){function n(t){this.state=a,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,a=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){a[n]=r,o+=1,o===t.length&&e(a)}}var o=0,a=[];0===t.length&&e(a);for(var i=0;i Date: Mon, 5 Oct 2015 11:19:22 +0200 Subject: [PATCH 03/61] Implemented request/response transforms --- dist/vue-resource.js | 106 ++++++++++----------------------------- dist/vue-resource.min.js | 2 +- 2 files changed, 28 insertions(+), 80 deletions(-) diff --git a/dist/vue-resource.js b/dist/vue-resource.js index 298ef40b..1f48b107 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -8,7 +8,7 @@ if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) - define([], factory); + define(factory); else if(typeof exports === 'object') exports["VueResource"] = factory(); else @@ -70,7 +70,7 @@ return /******/ (function(modules) { // webpackBootstrap Vue.url = __webpack_require__(2)(_); Vue.http = __webpack_require__(3)(_); - Vue.resource = __webpack_require__(8)(_); + Vue.resource = __webpack_require__(7)(_); Object.defineProperties(Vue.prototype, { @@ -361,7 +361,6 @@ return /******/ (function(modules) { // webpackBootstrap var xhr = __webpack_require__(4); var jsonp = __webpack_require__(6); var Promise = __webpack_require__(5); - var Transforms = __webpack_require__(7); module.exports = function (_) { @@ -369,7 +368,8 @@ return /******/ (function(modules) { // webpackBootstrap var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; function Http(url, options) { - var vm = this.vm; + + var promise; if (_.isPlainObject(url)) { options = url; @@ -381,14 +381,6 @@ return /******/ (function(modules) { // webpackBootstrap Http.options, this.options, options ); - var transformRequest = function (options) { - return transform(Http.transforms.request, options.transformRequest, options, vm); - }; - - var transformResponse = function (response) { - return transform(Http.transforms.response, options.transformResponse, response, vm); - }; - if (options.crossOrigin === null) { options.crossOrigin = crossOrigin(options.url); } @@ -415,22 +407,26 @@ return /******/ (function(modules) { // webpackBootstrap options.data = _.url.params(options.data); } - return extendPromise(transformRequest(options).then(function (options) { + if (_.isObject(options.data) && /FormData/i.test(options.data.toString())) { + delete options.headers['Content-Type']; + } - var promise = (options.method == 'JSONP' ? jsonp : xhr).call(vm, _, options); - promise = extendPromise(promise.then(transformResponse, transformResponse), vm); + if (_.isPlainObject(options.data)) { + options.data = JSON.stringify(options.data); + } - if (options.success) { - promise = promise.success(options.success); - } + promise = (options.method == 'JSONP' ? jsonp : xhr).call(this.vm, _, options); + promise = extendPromise(promise.then(transformResponse, transformResponse), this.vm); - if (options.error) { - promise = promise.error(options.error); - } + if (options.success) { + promise = promise.success(options.success); + } - return promise; + if (options.error) { + promise = promise.error(options.error); + } - }), vm); + return promise; } function extendPromise(promise, vm) { @@ -463,16 +459,15 @@ return /******/ (function(modules) { // webpackBootstrap return promise; } - function transform(transforms, custom, arg, vm) { - if (custom) { - transforms = transforms.concat(custom instanceof Array ? custom : [custom]); + function transformResponse(response) { + + try { + response.data = JSON.parse(response.responseText); + } catch (e) { + response.data = response.responseText; } - return transforms.reduce(function (sequence, transform) { - return sequence.then(function (arg) { - return transform.call(vm, arg); - }); - }, Promise.resolve(arg)); + return response.ok ? response : Promise.reject(response); } function crossOrigin(url) { @@ -482,8 +477,6 @@ return /******/ (function(modules) { // webpackBootstrap return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); } - Http.transforms = Transforms.call(this, _); - Http.options = { method: 'get', params: {}, @@ -493,9 +486,7 @@ return /******/ (function(modules) { // webpackBootstrap beforeSend: null, crossOrigin: null, emulateHTTP: false, - emulateJSON: false, - transformRequest: null, - transformResponse: null + emulateJSON: false }; Http.headers = { @@ -856,49 +847,6 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 7 */ -/***/ function(module, exports, __webpack_require__) { - - var Promise = __webpack_require__(5); - - module.exports = function (_) { - return { - - request: [ - - function (options) { - - if (_.isObject(options.data) && /FormData/i.test(options.data.toString())) { - delete options.headers['Content-Type']; - } - - if (_.isPlainObject(options.data)) { - options.data = JSON.stringify(options.data); - } - - return options; - } - - ], - - response: [ - - function (response) { - try { - response.data = JSON.parse(response.responseText); - } catch (e) { - response.data = response.responseText; - } - - return response.ok ? response : Promise.reject(response); - } - - ] - - } - }; - -/***/ }, -/* 8 */ /***/ function(module, exports) { /** diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index 842fc093..88ec5e30 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -4,4 +4,4 @@ * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(8)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return this._url||(this._url=e.options(t.url,this,this.$options.url))}},$http:{get:function(){return this._http||(this._http=e.options(t.http,this,this.$options.http))}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var a in r)o&&(n.isPlainObject(r[a])||n.isArray(r[a]))?(n.isPlainObject(r[a])&&!n.isPlainObject(t[a])&&(t[a]={}),n.isArray(r[a])&&!n.isArray(t[a])&&(t[a]=[]),e(t[a],r[a],o)):void 0!==r[a]&&(t[a]=r[a])}var n=t.util.extend({},t.util);return n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&a.status<300),(a.ok?n:r)(a)};a.onload=o,a.onabort=o,a.onerror=o,a.send(e.data)})}},function(t,e){function n(t){this.state=a,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,a=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){a[n]=r,o+=1,o===t.length&&e(a)}}var o=0,a=[];0===t.length&&e(a);for(var i=0;i=200&&a.status<300),(a.ok?n:r)(a)};a.onload=o,a.onabort=o,a.onerror=o,a.send(e.data)})}},function(t,e){function n(t){this.state=a,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,a=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){a[n]=r,o+=1,o===t.length&&e(a)}}var o=0,a=[];0===t.length&&e(a);for(var i=0;i Date: Mon, 5 Oct 2015 11:49:54 +0200 Subject: [PATCH 04/61] Added deprecated warnings --- src/lib/jsonp.js | 5 +++++ src/lib/util.js | 4 ++++ src/lib/xhr.js | 8 +++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js index 3df41845..408ebe59 100644 --- a/src/lib/jsonp.js +++ b/src/lib/jsonp.js @@ -11,6 +11,11 @@ module.exports = function (_, options) { options.params[options.jsonp] = callback; if (_.isFunction(options.beforeSend)) { + + _.warn('beforeSend has been deprecated in vue-resource ^0.1.17. ' + + 'Use transformRequest instead.' + ); + options.beforeSend.call(this, {}, options); } diff --git a/src/lib/util.js b/src/lib/util.js index f9780a4b..790e97aa 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -60,6 +60,10 @@ module.exports = function (Vue) { return target; }; + if (!_.warn) { + _.warn = function () {}; + } + function extend(target, source, deep) { for (var key in source) { if (deep && (_.isPlainObject(source[key]) || _.isArray(source[key]))) { diff --git a/src/lib/xhr.js b/src/lib/xhr.js index 009bc7dd..fe0c037f 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -10,7 +10,8 @@ module.exports = function (_, options) { var request = new XMLHttpRequest(), promise; if (XDomain && options.crossOrigin) { - request = new XDomainRequest(); options.headers = {}; + request = new XDomainRequest(); + options.headers = {}; } if (_.isPlainObject(options.xhr)) { @@ -18,6 +19,11 @@ module.exports = function (_, options) { } if (_.isFunction(options.beforeSend)) { + + _.warn('beforeSend has been deprecated in vue-resource ^0.1.17. ' + + 'Use transformRequest or XHR options instead.' + ); + options.beforeSend.call(this, request, options); } From 248feeb1d8aa1e84e094432aab7275fe7cbfa67a Mon Sep 17 00:00:00 2001 From: Malte Date: Mon, 5 Oct 2015 12:11:19 +0200 Subject: [PATCH 05/61] updated transforms --- src/http.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/http.js b/src/http.js index aa98aadc..3c4cb93b 100644 --- a/src/http.js +++ b/src/http.js @@ -108,8 +108,10 @@ module.exports = function (_) { } function transform(transforms, custom, arg, vm) { - if (custom) { - transforms = transforms.concat(custom instanceof Array ? custom : [custom]); + if (custom && custom instanceof Array) { + transforms = custom; + } else if (custom) { + transforms = transforms.concat([custom]); } return transforms.reduce(function (sequence, transform) { From 24e70436c3d0eae93bb3b3d793a9a001692d0af4 Mon Sep 17 00:00:00 2001 From: Malte-Christian Scharenberg Date: Mon, 5 Oct 2015 14:05:11 +0200 Subject: [PATCH 06/61] Update README.md --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e2b9d190..c4e09dfa 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,14 @@ Set default values using the global configuration. ```javascript Vue.http.options.root = '/root'; Vue.http.headers.common['Authorization'] = 'Basic YXBpOnBhc3N3b3Jk'; + +Vue.http.transforms.request.push(function (options) { + return options; +}); + +Vue.http.transforms.response.push(function (response) { + return response; +}); ``` Set default values inside your Vue component options. @@ -62,11 +70,12 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt * **headers** - `Object` - Headers object to be sent as HTTP request headers * **success** - `function(data, status, request)` - Callback function to be called when the request finishes * **error** - `function(data, status, request)` - Callback function to be called when the request fails -* **beforeSend** - `function(request, options)` - Callback function to modify the request object before it is sent * **emulateHTTP** - `boolean` - Send PUT, PATCH and DELETE requests with a HTTP POST and set the `X-HTTP-Method-Override` header * **emulateJSON** - `boolean` - Send request data as `application/x-www-form-urlencoded` content type * **xhr** - `Object` - Parameters object to be set on the native XHR object * **jsonp** - `string` - Callback function name in a JSONP request +* **transformRequest** - `function(options)|array` - Callback function to modify the request options before it is sent. If an array is passed, the default transformations are overwritten. +* **transformResponse** - `function(options)|array` - Callback function to modify the response before it is passed to the handler functions. If an array is passed, the default transformations are overwritten. ### Example From 98607d6b866b52ecedf06bae51a28353c07cb7b4 Mon Sep 17 00:00:00 2001 From: Malte Date: Mon, 5 Oct 2015 14:27:08 +0200 Subject: [PATCH 07/61] added XHR timeout --- src/http.js | 17 +++++++++-------- src/lib/xhr.js | 3 +++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/http.js b/src/http.js index 3c4cb93b..f50081c2 100644 --- a/src/http.js +++ b/src/http.js @@ -25,14 +25,6 @@ module.exports = function (_) { Http.options, this.options, options ); - var transformRequest = function (options) { - return transform(Http.transforms.request, options.transformRequest, options, vm); - }; - - var transformResponse = function (response) { - return transform(Http.transforms.response, options.transformResponse, response, vm); - }; - if (options.crossOrigin === null) { options.crossOrigin = crossOrigin(options.url); } @@ -59,6 +51,14 @@ module.exports = function (_) { options.data = _.url.params(options.data); } + var transformRequest = function (options) { + return transform(Http.transforms.request, options.transformRequest, options, vm); + }; + + var transformResponse = function (response) { + return transform(Http.transforms.response, options.transformResponse, response, vm); + }; + return extendPromise(transformRequest(options).then(function (options) { var promise = (options.method == 'JSONP' ? jsonp : xhr).call(vm, _, options); @@ -140,6 +140,7 @@ module.exports = function (_) { crossOrigin: null, emulateHTTP: false, emulateJSON: false, + timeout: 0, transformRequest: null, transformResponse: null }; diff --git a/src/lib/xhr.js b/src/lib/xhr.js index fe0c037f..571b4a40 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -18,6 +18,8 @@ module.exports = function (_, options) { _.extend(request, options.xhr); } + request.timeout = options.timeout; + if (_.isFunction(options.beforeSend)) { _.warn('beforeSend has been deprecated in vue-resource ^0.1.17. ' + @@ -49,6 +51,7 @@ module.exports = function (_, options) { request.onload = handler; request.onabort = handler; request.onerror = handler; + request.ontimeout = handler; request.send(options.data); }); From bce53fca399f0f3bcbd97ada42a3511e7696ed5f Mon Sep 17 00:00:00 2001 From: Malte Date: Mon, 5 Oct 2015 14:55:41 +0200 Subject: [PATCH 08/61] updated warnings --- src/lib/jsonp.js | 2 +- src/lib/util.js | 12 +++++++----- src/lib/xhr.js | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js index 408ebe59..cdb2e2a9 100644 --- a/src/lib/jsonp.js +++ b/src/lib/jsonp.js @@ -12,7 +12,7 @@ module.exports = function (_, options) { if (_.isFunction(options.beforeSend)) { - _.warn('beforeSend has been deprecated in vue-resource ^0.1.17. ' + + _.warn('beforeSend has been deprecated in ^0.1.17. ' + 'Use transformRequest instead.' ); diff --git a/src/lib/util.js b/src/lib/util.js index 790e97aa..a6a58458 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -4,7 +4,13 @@ module.exports = function (Vue) { - var _ = Vue.util.extend({}, Vue.util); + var _ = Vue.util.extend({}, Vue.util), config = Vue.config; + + _.warn = function (msg) { + if (window.console && (!config.silent || config.debug)) { + console.warn('[VueResource warn]: ' + msg); + } + }; _.isString = function (value) { return typeof value === 'string'; @@ -60,10 +66,6 @@ module.exports = function (Vue) { return target; }; - if (!_.warn) { - _.warn = function () {}; - } - function extend(target, source, deep) { for (var key in source) { if (deep && (_.isPlainObject(source[key]) || _.isArray(source[key]))) { diff --git a/src/lib/xhr.js b/src/lib/xhr.js index 571b4a40..698f3008 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -22,7 +22,7 @@ module.exports = function (_, options) { if (_.isFunction(options.beforeSend)) { - _.warn('beforeSend has been deprecated in vue-resource ^0.1.17. ' + + _.warn('beforeSend has been deprecated in ^0.1.17. ' + 'Use transformRequest or XHR options instead.' ); From 4ac25820769b5ae8eca603cded83477d362a3110 Mon Sep 17 00:00:00 2001 From: Malte Date: Mon, 5 Oct 2015 15:18:07 +0200 Subject: [PATCH 09/61] added JSONP timeout --- src/lib/jsonp.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js index cdb2e2a9..b17efa5f 100644 --- a/src/lib/jsonp.js +++ b/src/lib/jsonp.js @@ -49,6 +49,14 @@ module.exports = function (_, options) { script.onload = handler; script.onerror = handler; + if (options.timeout) { + setTimeout(function () { + + reject(new Event('timeout')); + + }, options.timeout); + } + document.body.appendChild(script); }); From aa65df882f86dacc42bb043e7101df2d669f06fb Mon Sep 17 00:00:00 2001 From: Malte-Christian Scharenberg Date: Mon, 5 Oct 2015 15:22:19 +0200 Subject: [PATCH 10/61] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c4e09dfa..8a61a54b 100644 --- a/README.md +++ b/README.md @@ -74,8 +74,9 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt * **emulateJSON** - `boolean` - Send request data as `application/x-www-form-urlencoded` content type * **xhr** - `Object` - Parameters object to be set on the native XHR object * **jsonp** - `string` - Callback function name in a JSONP request -* **transformRequest** - `function(options)|array` - Callback function to modify the request options before it is sent. If an array is passed, the default transformations are overwritten. -* **transformResponse** - `function(options)|array` - Callback function to modify the response before it is passed to the handler functions. If an array is passed, the default transformations are overwritten. +* **timeout** - `unsigned long` - Request timeout in milliseconds (`0` means no timeout) +* **transformRequest** - `function(options)|array` - Callback function to modify the request options before it is sent (if an array is passed, the default transformations are overwritten) +* **transformResponse** - `function(options)|array` - Callback function to modify the response before it is passed to the handler functions (if an array is passed, the default transformations are overwritten) ### Example From 1091d78a97091475299046d32aa830bc67d8abb1 Mon Sep 17 00:00:00 2001 From: Malte Date: Mon, 5 Oct 2015 17:49:18 +0200 Subject: [PATCH 11/61] updated timeout and transforms --- src/http.js | 6 ++++-- src/lib/jsonp.js | 10 +++++++++- src/lib/xhr.js | 3 ++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/http.js b/src/http.js index f50081c2..df4b9315 100644 --- a/src/http.js +++ b/src/http.js @@ -115,9 +115,11 @@ module.exports = function (_) { } return transforms.reduce(function (sequence, transform) { - return sequence.then(function (arg) { + var cb = function (arg) { return transform.call(vm, arg); - }); + }; + + return sequence.then(cb, cb); }, Promise.resolve(arg)); } diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js index b17efa5f..01f7bb34 100644 --- a/src/lib/jsonp.js +++ b/src/lib/jsonp.js @@ -42,6 +42,7 @@ module.exports = function (_, options) { response.ok = event.type !== 'error'; response.status = response.ok ? 200 : 404; response.responseText = body ? body : event.type; + response.headers = ""; (response.ok ? resolve : reject)(response); }; @@ -51,8 +52,15 @@ module.exports = function (_, options) { if (options.timeout) { setTimeout(function () { + var response = {}; - reject(new Event('timeout')); + response.ok = false; + response.type = 'timeout'; + response.status = 0; + response.headers = ""; + response.responseText = ''; + + reject(response); }, options.timeout); } diff --git a/src/lib/xhr.js b/src/lib/xhr.js index 698f3008..18bc00e3 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -18,7 +18,6 @@ module.exports = function (_, options) { _.extend(request, options.xhr); } - request.timeout = options.timeout; if (_.isFunction(options.beforeSend)) { @@ -32,6 +31,7 @@ module.exports = function (_, options) { promise = new Promise(function (resolve, reject) { request.open(options.method, _.url(options), true); + request.timeout = options.timeout; _.each(options.headers, function (value, header) { request.setRequestHeader(header, value); @@ -40,6 +40,7 @@ module.exports = function (_, options) { var handler = function (event) { request.ok = event.type === 'load'; + request.headers = request.getAllResponseHeaders(); if (request.ok && request.status) { request.ok = request.status >= 200 && request.status < 300; From 3a877ab7579d2eff3fe2cdd1914d028ae02c872d Mon Sep 17 00:00:00 2001 From: Malte Date: Tue, 6 Oct 2015 13:57:03 +0200 Subject: [PATCH 12/61] updated promise chaining --- src/http.js | 11 +++++++---- src/lib/jsonp.js | 4 ++-- src/lib/transforms.js | 6 ++++-- src/lib/xhr.js | 2 +- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/http.js b/src/http.js index df4b9315..a314dd45 100644 --- a/src/http.js +++ b/src/http.js @@ -56,7 +56,9 @@ module.exports = function (_) { }; var transformResponse = function (response) { - return transform(Http.transforms.response, options.transformResponse, response, vm); + return transform(Http.transforms.response, options.transformResponse, response, vm).then(function (response) { + return response.ok ? response : Promise.reject(response); + }); }; return extendPromise(transformRequest(options).then(function (options) { @@ -108,6 +110,7 @@ module.exports = function (_) { } function transform(transforms, custom, arg, vm) { + if (custom && custom instanceof Array) { transforms = custom; } else if (custom) { @@ -115,11 +118,11 @@ module.exports = function (_) { } return transforms.reduce(function (sequence, transform) { - var cb = function (arg) { + + return sequence.then(function (arg) { return transform.call(vm, arg); - }; + }); - return sequence.then(cb, cb); }, Promise.resolve(arg)); } diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js index 01f7bb34..4423cb4e 100644 --- a/src/lib/jsonp.js +++ b/src/lib/jsonp.js @@ -44,7 +44,7 @@ module.exports = function (_, options) { response.responseText = body ? body : event.type; response.headers = ""; - (response.ok ? resolve : reject)(response); + resolve(response); }; script.onload = handler; @@ -60,7 +60,7 @@ module.exports = function (_, options) { response.headers = ""; response.responseText = ''; - reject(response); + resolve(response); }, options.timeout); } diff --git a/src/lib/transforms.js b/src/lib/transforms.js index f24d0aed..62629149 100644 --- a/src/lib/transforms.js +++ b/src/lib/transforms.js @@ -1,4 +1,6 @@ -var Promise = require('./promise'); +/** + * Request/Response transforms. + */ module.exports = function (_) { return { @@ -29,7 +31,7 @@ module.exports = function (_) { response.data = response.responseText; } - return response.ok ? response : Promise.reject(response); + return response; } ] diff --git a/src/lib/xhr.js b/src/lib/xhr.js index 18bc00e3..bf320cb8 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -46,7 +46,7 @@ module.exports = function (_, options) { request.ok = request.status >= 200 && request.status < 300; } - (request.ok ? resolve : reject)(request); + resolve(request); }; request.onload = handler; From 041b69970e0b3fe9645bc1471381fafe2cf65ff2 Mon Sep 17 00:00:00 2001 From: Malte Date: Tue, 6 Oct 2015 14:22:29 +0200 Subject: [PATCH 13/61] cleanup --- src/http.js | 2 +- src/lib/jsonp.js | 2 +- src/lib/xhr.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/http.js b/src/http.js index a314dd45..734d16f4 100644 --- a/src/http.js +++ b/src/http.js @@ -111,7 +111,7 @@ module.exports = function (_) { function transform(transforms, custom, arg, vm) { - if (custom && custom instanceof Array) { + if (_.isArray(custom)) { transforms = custom; } else if (custom) { transforms = transforms.concat([custom]); diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js index 4423cb4e..2df10680 100644 --- a/src/lib/jsonp.js +++ b/src/lib/jsonp.js @@ -19,7 +19,7 @@ module.exports = function (_, options) { options.beforeSend.call(this, {}, options); } - return new Promise(function (resolve, reject) { + return new Promise(function (resolve) { script = document.createElement('script'); script.src = _.url(options); diff --git a/src/lib/xhr.js b/src/lib/xhr.js index bf320cb8..683cc84d 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -28,7 +28,7 @@ module.exports = function (_, options) { options.beforeSend.call(this, request, options); } - promise = new Promise(function (resolve, reject) { + promise = new Promise(function (resolve) { request.open(options.method, _.url(options), true); request.timeout = options.timeout; From 90d5efc748ccab2fe203041796d064e5b962bf73 Mon Sep 17 00:00:00 2001 From: Malte Date: Tue, 6 Oct 2015 19:10:02 +0200 Subject: [PATCH 14/61] use XMLHttpRequest for IE > 9 --- src/lib/xhr.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/lib/xhr.js b/src/lib/xhr.js index 683cc84d..4ffa475a 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -9,7 +9,8 @@ module.exports = function (_, options) { var request = new XMLHttpRequest(), promise; - if (XDomain && options.crossOrigin) { + if (XDomain && options.crossOrigin && !('withCredentials' in request)) { + request = new XDomainRequest(); options.headers = {}; } @@ -33,14 +34,16 @@ module.exports = function (_, options) { request.open(options.method, _.url(options), true); request.timeout = options.timeout; - _.each(options.headers, function (value, header) { - request.setRequestHeader(header, value); - }); + if ('setRequestHeader' in request) { + _.each(options.headers, function (value, header) { + request.setRequestHeader(header, value); + }); + } var handler = function (event) { request.ok = event.type === 'load'; - request.headers = request.getAllResponseHeaders(); + request.headers = 'getAllResponseHeaders' in request ? request.getAllResponseHeaders() : ''; if (request.ok && request.status) { request.ok = request.status >= 200 && request.status < 300; From 31a384bcdf25e1e23c45eb681ba681e9248a46b8 Mon Sep 17 00:00:00 2001 From: Malte Date: Tue, 6 Oct 2015 19:53:41 +0200 Subject: [PATCH 15/61] cleanup IE check --- src/lib/xhr.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/lib/xhr.js b/src/lib/xhr.js index 4ffa475a..3b747d83 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -3,13 +3,12 @@ */ var Promise = require('./promise'); -var XDomain = window.XDomainRequest; module.exports = function (_, options) { var request = new XMLHttpRequest(), promise; - if (XDomain && options.crossOrigin && !('withCredentials' in request)) { + if (options.crossOrigin && !('withCredentials' in request)) { request = new XDomainRequest(); options.headers = {}; @@ -34,11 +33,9 @@ module.exports = function (_, options) { request.open(options.method, _.url(options), true); request.timeout = options.timeout; - if ('setRequestHeader' in request) { - _.each(options.headers, function (value, header) { - request.setRequestHeader(header, value); - }); - } + _.each(options.headers, function (value, header) { + request.setRequestHeader(header, value); + }); var handler = function (event) { From 4571e66c9f821196dc286b3de7fbdef02f26d77c Mon Sep 17 00:00:00 2001 From: janschoenherr Date: Wed, 7 Oct 2015 09:23:53 +0200 Subject: [PATCH 16/61] Update index.js --- src/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index ad62bf61..d39d504a 100644 --- a/src/index.js +++ b/src/index.js @@ -14,13 +14,13 @@ function install(Vue) { $url: { get: function () { - return this._url || (this._url = _.options(Vue.url, this, this.$options.url)); + return _.options(Vue.url, this, this.$options.url); } }, $http: { get: function () { - return this._http || (this._http = _.options(Vue.http, this, this.$options.http)); + return _.options(Vue.http, this, this.$options.http); } }, @@ -37,4 +37,4 @@ if (window.Vue) { Vue.use(install); } -module.exports = install; \ No newline at end of file +module.exports = install; From c0de2c3da872f464a1b84c983368a93f2d3cfb6d Mon Sep 17 00:00:00 2001 From: Malte Date: Wed, 7 Oct 2015 11:14:09 +0200 Subject: [PATCH 17/61] add header shorhand --- src/lib/jsonp.js | 2 +- src/lib/xhr.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js index 2df10680..cfd06879 100644 --- a/src/lib/jsonp.js +++ b/src/lib/jsonp.js @@ -57,8 +57,8 @@ module.exports = function (_, options) { response.ok = false; response.type = 'timeout'; response.status = 0; - response.headers = ""; response.responseText = ''; + response.header = function () {return null}; resolve(response); diff --git a/src/lib/xhr.js b/src/lib/xhr.js index 3b747d83..80717d7b 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -40,7 +40,9 @@ module.exports = function (_, options) { var handler = function (event) { request.ok = event.type === 'load'; - request.headers = 'getAllResponseHeaders' in request ? request.getAllResponseHeaders() : ''; + request.header = function (name) { + return 'getResponseHeader' in this ? this.getResponseHeader(name) : null; + }; if (request.ok && request.status) { request.ok = request.status >= 200 && request.status < 300; From a43eea139c76a474b7fc8fe80caabab7b6d4d129 Mon Sep 17 00:00:00 2001 From: Malte Date: Wed, 7 Oct 2015 14:39:11 +0200 Subject: [PATCH 18/61] update jsonp --- src/lib/jsonp.js | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js index cfd06879..dca6c03f 100644 --- a/src/lib/jsonp.js +++ b/src/lib/jsonp.js @@ -32,39 +32,42 @@ module.exports = function (_, options) { var handler = function (event) { - delete window[callback]; - document.body.removeChild(script); + if (event.type === 'load') { + delete window[callback]; + document.body.removeChild(script); + } if (event.type === 'load' && !body) { event.type = 'error'; } - response.ok = event.type !== 'error'; - response.status = response.ok ? 200 : 404; - response.responseText = body ? body : event.type; - response.headers = ""; + switch (event.type) { + case 'load': + response.status = 200; + break; + case 'error': + response.status = 404; + break; + default: + response.status = 0; + } + + response.ok = event.type === 'load'; + response.responseText = body ? body : ''; + response.header = function () {return null}; resolve(response); }; - script.onload = handler; - script.onerror = handler; - if (options.timeout) { setTimeout(function () { - var response = {}; - - response.ok = false; - response.type = 'timeout'; - response.status = 0; - response.responseText = ''; - response.header = function () {return null}; - - resolve(response); - + handler({type: 'timeout'}); }, options.timeout); } + script.onload = handler; + script.onerror = handler; + document.body.appendChild(script); }); From 77590751c6035e27b476caa03d8b0994f0955a7f Mon Sep 17 00:00:00 2001 From: Malte Date: Wed, 7 Oct 2015 14:56:01 +0200 Subject: [PATCH 19/61] introduce `reject` property at response object --- src/http.js | 2 +- src/lib/jsonp.js | 1 + src/lib/xhr.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/http.js b/src/http.js index 734d16f4..8792ddf9 100644 --- a/src/http.js +++ b/src/http.js @@ -57,7 +57,7 @@ module.exports = function (_) { var transformResponse = function (response) { return transform(Http.transforms.response, options.transformResponse, response, vm).then(function (response) { - return response.ok ? response : Promise.reject(response); + return response.reject ? Promise.reject(response) : response; }); }; diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js index dca6c03f..b4b6292a 100644 --- a/src/lib/jsonp.js +++ b/src/lib/jsonp.js @@ -53,6 +53,7 @@ module.exports = function (_, options) { } response.ok = event.type === 'load'; + response.reject = !response.ok; response.responseText = body ? body : ''; response.header = function () {return null}; diff --git a/src/lib/xhr.js b/src/lib/xhr.js index 80717d7b..ca323896 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -47,6 +47,7 @@ module.exports = function (_, options) { if (request.ok && request.status) { request.ok = request.status >= 200 && request.status < 300; } + request.reject = !request.ok; resolve(request); }; From 81b24df78a5f46eec24a4049c61f52d69c18a3c7 Mon Sep 17 00:00:00 2001 From: Malte Date: Wed, 7 Oct 2015 15:46:26 +0200 Subject: [PATCH 20/61] transforms no longer async --- src/http.js | 46 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/src/http.js b/src/http.js index 8792ddf9..56944331 100644 --- a/src/http.js +++ b/src/http.js @@ -13,7 +13,7 @@ module.exports = function (_) { var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; function Http(url, options) { - var vm = this.vm; + var promise; if (_.isPlainObject(url)) { options = url; @@ -51,32 +51,24 @@ module.exports = function (_) { options.data = _.url.params(options.data); } - var transformRequest = function (options) { - return transform(Http.transforms.request, options.transformRequest, options, vm); - }; - - var transformResponse = function (response) { - return transform(Http.transforms.response, options.transformResponse, response, vm).then(function (response) { - return response.reject ? Promise.reject(response) : response; - }); - }; + options = transform(Http.transforms.request, options.transformRequest, options, this.vm); + promise = (options.method == 'JSONP' ? jsonp : xhr).call(this.vm, _, options); + promise = extendPromise(promise.then(function (response) { - return extendPromise(transformRequest(options).then(function (options) { + transform(Http.transforms.response, options.transformResponse, response, this); + return response.reject ? Promise.reject(response) : response; - var promise = (options.method == 'JSONP' ? jsonp : xhr).call(vm, _, options); - promise = extendPromise(promise.then(transformResponse, transformResponse), vm); + }.bind(this.vm)), this.vm); - if (options.success) { - promise = promise.success(options.success); - } - - if (options.error) { - promise = promise.error(options.error); - } + if (options.success) { + promise = promise.success(options.success); + } - return promise; + if (options.error) { + promise = promise.error(options.error); + } - }), vm); + return promise; } function extendPromise(promise, vm) { @@ -117,13 +109,9 @@ module.exports = function (_) { transforms = transforms.concat([custom]); } - return transforms.reduce(function (sequence, transform) { - - return sequence.then(function (arg) { - return transform.call(vm, arg); - }); - - }, Promise.resolve(arg)); + return transforms.reduce(function (arg, transform) { + return transform.call(vm, arg); + }, arg); } function crossOrigin(url) { From a1c5344935e4d255f3b971f8a56cdb6eaf0642c8 Mon Sep 17 00:00:00 2001 From: Malte Date: Wed, 7 Oct 2015 15:46:26 +0200 Subject: [PATCH 21/61] transforms no longer async --- src/http.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http.js b/src/http.js index 56944331..4b4b1377 100644 --- a/src/http.js +++ b/src/http.js @@ -55,7 +55,7 @@ module.exports = function (_) { promise = (options.method == 'JSONP' ? jsonp : xhr).call(this.vm, _, options); promise = extendPromise(promise.then(function (response) { - transform(Http.transforms.response, options.transformResponse, response, this); + response = transform(Http.transforms.response, options.transformResponse, response, this); return response.reject ? Promise.reject(response) : response; }.bind(this.vm)), this.vm); From 0a416f813c4b1885191be3552d73543b5a781eec Mon Sep 17 00:00:00 2001 From: Malte Date: Mon, 12 Oct 2015 17:27:01 +0200 Subject: [PATCH 22/61] revert transforms --- README.md | 11 +---------- src/http.js | 38 ++++++++++++++++---------------------- src/lib/jsonp.js | 5 ----- src/lib/transforms.js | 40 ---------------------------------------- src/lib/xhr.js | 5 ----- 5 files changed, 17 insertions(+), 82 deletions(-) delete mode 100644 src/lib/transforms.js diff --git a/README.md b/README.md index 8a61a54b..39514e1b 100644 --- a/README.md +++ b/README.md @@ -23,14 +23,6 @@ Set default values using the global configuration. ```javascript Vue.http.options.root = '/root'; Vue.http.headers.common['Authorization'] = 'Basic YXBpOnBhc3N3b3Jk'; - -Vue.http.transforms.request.push(function (options) { - return options; -}); - -Vue.http.transforms.response.push(function (response) { - return response; -}); ``` Set default values inside your Vue component options. @@ -70,13 +62,12 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt * **headers** - `Object` - Headers object to be sent as HTTP request headers * **success** - `function(data, status, request)` - Callback function to be called when the request finishes * **error** - `function(data, status, request)` - Callback function to be called when the request fails +* **beforeSend** - `function(request, options)` - Callback function to modify the request object before it is sent * **emulateHTTP** - `boolean` - Send PUT, PATCH and DELETE requests with a HTTP POST and set the `X-HTTP-Method-Override` header * **emulateJSON** - `boolean` - Send request data as `application/x-www-form-urlencoded` content type * **xhr** - `Object` - Parameters object to be set on the native XHR object * **jsonp** - `string` - Callback function name in a JSONP request * **timeout** - `unsigned long` - Request timeout in milliseconds (`0` means no timeout) -* **transformRequest** - `function(options)|array` - Callback function to modify the request options before it is sent (if an array is passed, the default transformations are overwritten) -* **transformResponse** - `function(options)|array` - Callback function to modify the response before it is passed to the handler functions (if an array is passed, the default transformations are overwritten) ### Example diff --git a/src/http.js b/src/http.js index 4b4b1377..7801650b 100644 --- a/src/http.js +++ b/src/http.js @@ -5,7 +5,6 @@ var xhr = require('./lib/xhr'); var jsonp = require('./lib/jsonp'); var Promise = require('./lib/promise'); -var Transforms = require('./lib/transforms'); module.exports = function (_) { @@ -51,14 +50,26 @@ module.exports = function (_) { options.data = _.url.params(options.data); } - options = transform(Http.transforms.request, options.transformRequest, options, this.vm); + if (_.isObject(options.data) && /FormData/i.test(options.data.toString())) { + delete options.headers['Content-Type']; + } + + if (_.isPlainObject(options.data)) { + options.data = JSON.stringify(options.data); + } + promise = (options.method == 'JSONP' ? jsonp : xhr).call(this.vm, _, options); promise = extendPromise(promise.then(function (response) { - response = transform(Http.transforms.response, options.transformResponse, response, this); + try { + response.data = JSON.parse(response.responseText); + } catch (e) { + response.data = response.responseText; + } + return response.reject ? Promise.reject(response) : response; - }.bind(this.vm)), this.vm); + }), this.vm); if (options.success) { promise = promise.success(options.success); @@ -101,19 +112,6 @@ module.exports = function (_) { return promise; } - function transform(transforms, custom, arg, vm) { - - if (_.isArray(custom)) { - transforms = custom; - } else if (custom) { - transforms = transforms.concat([custom]); - } - - return transforms.reduce(function (arg, transform) { - return transform.call(vm, arg); - }, arg); - } - function crossOrigin(url) { var requestUrl = _.url.parse(url); @@ -121,8 +119,6 @@ module.exports = function (_) { return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); } - Http.transforms = Transforms.call(this, _); - Http.options = { method: 'get', params: {}, @@ -133,9 +129,7 @@ module.exports = function (_) { crossOrigin: null, emulateHTTP: false, emulateJSON: false, - timeout: 0, - transformRequest: null, - transformResponse: null + timeout: 0 }; Http.headers = { diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js index b4b6292a..349a7305 100644 --- a/src/lib/jsonp.js +++ b/src/lib/jsonp.js @@ -11,11 +11,6 @@ module.exports = function (_, options) { options.params[options.jsonp] = callback; if (_.isFunction(options.beforeSend)) { - - _.warn('beforeSend has been deprecated in ^0.1.17. ' + - 'Use transformRequest instead.' - ); - options.beforeSend.call(this, {}, options); } diff --git a/src/lib/transforms.js b/src/lib/transforms.js deleted file mode 100644 index 62629149..00000000 --- a/src/lib/transforms.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Request/Response transforms. - */ - -module.exports = function (_) { - return { - - request: [ - - function (options) { - - if (_.isObject(options.data) && /FormData/i.test(options.data.toString())) { - delete options.headers['Content-Type']; - } - - if (_.isPlainObject(options.data)) { - options.data = JSON.stringify(options.data); - } - - return options; - } - - ], - - response: [ - - function (response) { - try { - response.data = JSON.parse(response.responseText); - } catch (e) { - response.data = response.responseText; - } - - return response; - } - - ] - - } -}; \ No newline at end of file diff --git a/src/lib/xhr.js b/src/lib/xhr.js index ca323896..bd11a3b7 100644 --- a/src/lib/xhr.js +++ b/src/lib/xhr.js @@ -20,11 +20,6 @@ module.exports = function (_, options) { if (_.isFunction(options.beforeSend)) { - - _.warn('beforeSend has been deprecated in ^0.1.17. ' + - 'Use transformRequest or XHR options instead.' - ); - options.beforeSend.call(this, request, options); } From a595a67aa77360cc35a4d0169e671fdce51f0fba Mon Sep 17 00:00:00 2001 From: Malte Date: Mon, 12 Oct 2015 19:48:08 +0200 Subject: [PATCH 23/61] implement interceptor (WIP) --- src/http.js | 95 +++++++++++++++++++++-------------------- src/interceptor/mime.js | 42 ++++++++++++++++++ src/lib/request.js | 46 ++++++++++++++++++++ 3 files changed, 136 insertions(+), 47 deletions(-) create mode 100644 src/interceptor/mime.js create mode 100644 src/lib/request.js diff --git a/src/http.js b/src/http.js index 7801650b..4c97303b 100644 --- a/src/http.js +++ b/src/http.js @@ -2,17 +2,22 @@ * Service for sending network requests. */ -var xhr = require('./lib/xhr'); -var jsonp = require('./lib/jsonp'); var Promise = require('./lib/promise'); module.exports = function (_) { - var originUrl = _.url.parse(location.href); + var request = require('./lib/request')(_); var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; + var defaultInterceptor = { + 'mime': require('./interceptor/mime.js')(_) + }; + function Http(url, options) { - var promise; + var chain, promise, + vm = this.vm, + requestInterceptor = [], + responseInterceptor = []; if (_.isPlainObject(url)) { options = url; @@ -24,52 +29,51 @@ module.exports = function (_) { Http.options, this.options, options ); - if (options.crossOrigin === null) { - options.crossOrigin = crossOrigin(options.url); - } + Http.interceptor.forEach(function (interceptor) { + var config = {}; - options.method = options.method.toUpperCase(); - options.headers = _.extend({}, Http.headers.common, - !options.crossOrigin ? Http.headers.custom : {}, - Http.headers[options.method.toLowerCase()], - options.headers - ); + if (_.isArray(interceptor)) { + interceptor = interceptor[0]; + config = interceptor[1]; + } - if (_.isPlainObject(options.data) && /^(GET|JSONP)$/i.test(options.method)) { - _.extend(options.params, options.data); - delete options.data; - } + if (_.isString(interceptor)) { + interceptor = defaultInterceptor[interceptor]; + } - if (options.emulateHTTP && !options.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(options.method)) { - options.headers['X-HTTP-Method-Override'] = options.method; - options.method = 'POST'; - } + if (_.isFunction(interceptor)) { + interceptor = interceptor.call(this, Promise); + } - if (options.emulateJSON && _.isPlainObject(options.data)) { - options.headers['Content-Type'] = 'application/x-www-form-urlencoded'; - options.data = _.url.params(options.data); - } + if (!_.isPlainObject(interceptor)) { + return; + } - if (_.isObject(options.data) && /FormData/i.test(options.data.toString())) { - delete options.headers['Content-Type']; - } + // TODO: Add config. + if (interceptor.request) { + requestInterceptor.push(interceptor.request); + } - if (_.isPlainObject(options.data)) { - options.data = JSON.stringify(options.data); - } + if (interceptor.response) { + responseInterceptor.push(interceptor.response); + } - promise = (options.method == 'JSONP' ? jsonp : xhr).call(this.vm, _, options); - promise = extendPromise(promise.then(function (response) { + }); - try { - response.data = JSON.parse(response.responseText); - } catch (e) { - response.data = response.responseText; - } + chain = requestInterceptor.concat([request], responseInterceptor); + promise = chain.reduce(function (sequence, segment) { - return response.reject ? Promise.reject(response) : response; + return sequence.then(function (carry) { + return segment.call(vm, carry); + }) + + }, Promise.resolve(options)); + + promise = extendPromise(promise.then(function (response) { - }), this.vm); + return response.ok ? response : Promise.reject(response); + + }), vm); if (options.success) { promise = promise.success(options.success); @@ -112,13 +116,6 @@ module.exports = function (_) { return promise; } - function crossOrigin(url) { - - var requestUrl = _.url.parse(url); - - return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); - } - Http.options = { method: 'get', params: {}, @@ -132,6 +129,10 @@ module.exports = function (_) { timeout: 0 }; + Http.interceptor = [ + 'mime' + ]; + Http.headers = { put: jsonType, post: jsonType, diff --git a/src/interceptor/mime.js b/src/interceptor/mime.js new file mode 100644 index 00000000..d9ed4f16 --- /dev/null +++ b/src/interceptor/mime.js @@ -0,0 +1,42 @@ +/** + * Mime Interceptor. + */ + +module.exports = function (_) { + + return { + + request: function (options) { + + if (options.emulateJSON && _.isPlainObject(options.data)) { + options.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + options.data = _.url.params(options.data); + } + + if (_.isObject(options.data) && /FormData/i.test(options.data.toString())) { + delete options.headers['Content-Type']; + } + + if (_.isPlainObject(options.data)) { + options.data = JSON.stringify(options.data); + } + + return options; + + }, + + response: function (response) { + + try { + response.data = JSON.parse(response.responseText); + } catch (e) { + response.data = response.responseText; + } + + return response; + + } + + }; + +} \ No newline at end of file diff --git a/src/lib/request.js b/src/lib/request.js new file mode 100644 index 00000000..372d00a0 --- /dev/null +++ b/src/lib/request.js @@ -0,0 +1,46 @@ +/** + * Request. + */ + +var xhr = require('./xhr'); +var jsonp = require('./jsonp'); + +module.exports = function (_) { + + var originUrl = _.url.parse(location.href); + + return function (options) { + + if (options.crossOrigin === null) { + options.crossOrigin = crossOrigin(options.url); + } + + options.method = options.method.toUpperCase(); + options.headers = _.extend({}, _.http.headers.common, + !options.crossOrigin ? _.http.headers.custom : {}, + _.http.headers[options.method.toLowerCase()], + options.headers + ); + + if (_.isPlainObject(options.data) && /^(GET|JSONP)$/i.test(options.method)) { + _.extend(options.params, options.data); + delete options.data; + } + + if (options.emulateHTTP && !options.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(options.method)) { + options.headers['X-HTTP-Method-Override'] = options.method; + options.method = 'POST'; + } + + return (options.method == 'JSONP' ? jsonp : xhr).call(this.vm, _, options); + + }; + + function crossOrigin(url) { + + var requestUrl = _.url.parse(url); + + return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); + } + +}; \ No newline at end of file From 29b37dde77e2010fba3e28e3f836826f133591e6 Mon Sep 17 00:00:00 2001 From: Malte-Christian Date: Fri, 23 Oct 2015 18:56:02 +0200 Subject: [PATCH 24/61] update interceptors (WIP) --- README.md | 35 ++++++++++++++++++++++++ src/http.js | 57 ++++++--------------------------------- src/interceptor/option.js | 42 +++++++++++++++++++++++++++++ src/lib/interceptor.js | 56 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 49 deletions(-) create mode 100644 src/interceptor/option.js create mode 100644 src/lib/interceptor.js diff --git a/README.md b/README.md index 39514e1b..1f86d248 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,41 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt * **jsonp** - `string` - Callback function name in a JSONP request * **timeout** - `unsigned long` - Request timeout in milliseconds (`0` means no timeout) +### Interceptors + +```javascript +Vue.http.interceptor.push({ + + request: function (options) { + return options; + }, + + response: function (response) { + return response; + } + +}); +``` + +#### Interceptor Factory + +```javascript +Vue.http.interceptor.push(function (Promise) { + return { + request: function (options) { + + + return Promise.reject(); + }, + response: function (response) { + + + return Promise.reject(); + } + }; +}); +``` + ### Example ```javascript diff --git a/src/http.js b/src/http.js index 4c97303b..bb050652 100644 --- a/src/http.js +++ b/src/http.js @@ -6,18 +6,12 @@ var Promise = require('./lib/promise'); module.exports = function (_) { - var request = require('./lib/request')(_); var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; - var defaultInterceptor = { - 'mime': require('./interceptor/mime.js')(_) - }; + var request = require('./lib/request')(_); + var interceptorFactory = require('./lib/interceptor')(_); function Http(url, options) { - var chain, promise, - vm = this.vm, - requestInterceptor = [], - responseInterceptor = []; if (_.isPlainObject(url)) { options = url; @@ -29,51 +23,15 @@ module.exports = function (_) { Http.options, this.options, options ); - Http.interceptor.forEach(function (interceptor) { - var config = {}; - - if (_.isArray(interceptor)) { - interceptor = interceptor[0]; - config = interceptor[1]; - } - - if (_.isString(interceptor)) { - interceptor = defaultInterceptor[interceptor]; - } - - if (_.isFunction(interceptor)) { - interceptor = interceptor.call(this, Promise); - } - - if (!_.isPlainObject(interceptor)) { - return; - } - - // TODO: Add config. - if (interceptor.request) { - requestInterceptor.push(interceptor.request); - } - - if (interceptor.response) { - responseInterceptor.push(interceptor.response); - } - - }); - - chain = requestInterceptor.concat([request], responseInterceptor); - promise = chain.reduce(function (sequence, segment) { - - return sequence.then(function (carry) { - return segment.call(vm, carry); - }) - - }, Promise.resolve(options)); + var interceptorStack = interceptorFactory.parse(Http.interceptor); + var chain = interceptorFactory.chain(interceptorStack, request); + var promise = interceptorFactory.run(chain, options, this.vm); promise = extendPromise(promise.then(function (response) { return response.ok ? response : Promise.reject(response); - }), vm); + }), this.vm); if (options.success) { promise = promise.success(options.success); @@ -130,7 +88,8 @@ module.exports = function (_) { }; Http.interceptor = [ - 'mime' + require('./interceptor/option')(_), + require('./interceptor/mime')(_) ]; Http.headers = { diff --git a/src/interceptor/option.js b/src/interceptor/option.js new file mode 100644 index 00000000..c3903356 --- /dev/null +++ b/src/interceptor/option.js @@ -0,0 +1,42 @@ +/** + * Options Interceptor. + */ + +module.exports = function (_) { + + var originUrl = _.url.parse(location.href); + + return { + + request: function (options) { + + if (options.crossOrigin === null) { + options.crossOrigin = crossOrigin(options.url); + } + + options.method = options.method.toUpperCase(); + options.headers = _.extend({}, _.http.headers.common, + !options.crossOrigin ? _.http.headers.custom : {}, + _.http.headers[options.method.toLowerCase()], + options.headers + ); + + if (_.isPlainObject(options.data) && /^(GET|JSONP)$/i.test(options.method)) { + _.extend(options.params, options.data); + delete options.data; + } + + return options; + + } + + }; + + function crossOrigin(url) { + + var requestUrl = _.url.parse(url); + + return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); + } + +} \ No newline at end of file diff --git a/src/lib/interceptor.js b/src/lib/interceptor.js new file mode 100644 index 00000000..8863fdaf --- /dev/null +++ b/src/lib/interceptor.js @@ -0,0 +1,56 @@ +/** + * Interceptor. + */ + +var Promise = require('./promise'); + +module.exports = function (_) { + + return { + + parse: function (interceptorList) { + + var interceptorStack = { + request: [], + response: [] + }; + + interceptorList.forEach(function (interceptor) { + + if (_.isFunction(interceptor)) { + interceptor = interceptor.call(this, Promise); + } + + if (_.isPlainObject(interceptor) && interceptor.request) { + interceptorStack.request.push(interceptor.request); + } + + if (_.isPlainObject(interceptor) && interceptor.response) { + interceptorStack.response.push(interceptor.response); + } + + }); + + return interceptorStack; + + }, + + chain: function (interceptorStack, request) { + return [].concat(interceptorStack.request, [request], interceptorStack.response); + }, + + run: function (chain, options, vm) { + + return chain.reduce(function (sequence, segment) { + + return sequence.then(function (carry) { + return segment.call(vm, carry); + }) + + }, Promise.resolve(options)); + + } + + }; + +}; \ No newline at end of file From 623565af9bc31a0758d6e977a6d4f4ecc8ca811c Mon Sep 17 00:00:00 2001 From: Malte-Christian Date: Mon, 26 Oct 2015 12:42:16 +0100 Subject: [PATCH 25/61] update interceptors (WIP) --- README.md | 16 ++++++++++------ src/lib/interceptor.js | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1f86d248..f011f539 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,8 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt ### Interceptors +Interceptors can be defined globally and are used for pre- and postprocessing of a request. + ```javascript Vue.http.interceptor.push({ @@ -87,18 +89,20 @@ Vue.http.interceptor.push({ #### Interceptor Factory +If Promises are needed inside of a Interceptor, a factory function can be used. + ```javascript Vue.http.interceptor.push(function (Promise) { return { request: function (options) { - - - return Promise.reject(); + if (reject) { + return Promise.reject(); + } }, response: function (response) { - - - return Promise.reject(); + if (reject) { + return Promise.reject(); + } } }; }); diff --git a/src/lib/interceptor.js b/src/lib/interceptor.js index 8863fdaf..f0f493af 100644 --- a/src/lib/interceptor.js +++ b/src/lib/interceptor.js @@ -1,5 +1,5 @@ /** - * Interceptor. + * Interceptor factory. */ var Promise = require('./promise'); From 91ab89dfa54d3452c6144bd5534fdf429fe6149e Mon Sep 17 00:00:00 2001 From: Malte Date: Mon, 26 Oct 2015 16:29:10 +0100 Subject: [PATCH 26/61] refactor request clients (WIP) --- src/client/jsonp.js | 83 ++++++++++++++++++++++++++++++++++++++ src/client/xhr.js | 65 +++++++++++++++++++++++++++++ src/http.js | 32 +++++++-------- src/interceptor/cors.js | 31 ++++++++++++++ src/interceptor/factory.js | 56 +++++++++++++++++++++++++ src/interceptor/jsonp.js | 21 ++++++++++ src/interceptor/mime.js | 23 ++++++----- src/interceptor/option.js | 33 +++++---------- src/lib/interceptor.js | 56 ------------------------- src/lib/jsonp.js | 70 -------------------------------- src/lib/request.js | 46 --------------------- src/lib/xhr.js | 59 --------------------------- 12 files changed, 296 insertions(+), 279 deletions(-) create mode 100644 src/client/jsonp.js create mode 100644 src/client/xhr.js create mode 100644 src/interceptor/cors.js create mode 100644 src/interceptor/factory.js create mode 100644 src/interceptor/jsonp.js delete mode 100644 src/lib/interceptor.js delete mode 100644 src/lib/jsonp.js delete mode 100644 src/lib/request.js delete mode 100644 src/lib/xhr.js diff --git a/src/client/jsonp.js b/src/client/jsonp.js new file mode 100644 index 00000000..27c882cd --- /dev/null +++ b/src/client/jsonp.js @@ -0,0 +1,83 @@ +/** + * JSONP request. + */ + +var Promise = require('../lib/promise'); + +module.exports = function (_) { + + return { + + send: function (request) { + + var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {}, script, body; + + request.params[request.jsonp] = callback; + + if (_.isFunction(request.beforeSend)) { + request.beforeSend.call(this, {}, request); + } + + return new Promise(function (resolve) { + + script = document.createElement('script'); + script.src = _.url(request); + script.type = 'text/javascript'; + script.async = true; + + window[callback] = function (data) { + body = data; + }; + + var handler = function (event) { + + if (event.type === 'load') { + delete window[callback]; + document.body.removeChild(script); + } + + if (event.type === 'load' && !body) { + event.type = 'error'; + } + + switch (event.type) { + case 'load': + response.status = 200; + break; + case 'error': + response.status = 404; + break; + default: + response.status = 0; + } + + response.ok = event.type === 'load'; + response.reject = !response.ok; + response.responseText = body ? body : ''; + response.header = function () { + return null + }; + + resolve(response); + }; + + if (request.timeout) { + setTimeout(function () { + handler({type: 'timeout'}); + }, request.timeout); + } + + script.onload = handler; + script.onerror = handler; + + document.body.appendChild(script); + }); + + }, + + cancel: function () { + + } + + }; +}; \ No newline at end of file diff --git a/src/client/xhr.js b/src/client/xhr.js new file mode 100644 index 00000000..9bd9677c --- /dev/null +++ b/src/client/xhr.js @@ -0,0 +1,65 @@ +/** + * XMLHttp request. + */ + +var Promise = require('../lib/promise'); + +module.exports = function (_) { + + var client; + + return { + + send: function (request) { + + client = new XMLHttpRequest(); + + if (request.crossOrigin && !('withCredentials' in client)) { + client = new XDomainRequest(); + request.headers = {}; + } + + return new Promise(function (resolve) { + + if (_.isFunction(request.beforeSend)) { + request.beforeSend.call(this, client, request); + } + + client.open(request.method, _.url(request), true); + client.timeout = request.timeout; + + _.each(request.headers, function (value, header) { + client.setRequestHeader(header, value); + }); + + var handler = function (event) { + + client.ok = event.type === 'load'; + client.header = function (name) { + return 'getResponseHeader' in this ? this.getResponseHeader(name) : null; + }; + + if (client.ok && client.status) { + client.ok = client.status >= 200 && client.status < 300; + } + client.reject = !client.ok; + + resolve(client); + }; + + client.onload = handler; + client.onabort = handler; + client.onerror = handler; + client.ontimeout = handler; + + client.send(request.data); + }); + + }, + + cancel: function () { + client.abort(); + } + + }; +}; diff --git a/src/http.js b/src/http.js index bb050652..95f24f64 100644 --- a/src/http.js +++ b/src/http.js @@ -7,25 +7,23 @@ var Promise = require('./lib/promise'); module.exports = function (_) { var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; + var factory = require('./interceptor/factory')(_); - var request = require('./lib/request')(_); - var interceptorFactory = require('./lib/interceptor')(_); - - function Http(url, options) { + function Http(url, request) { if (_.isPlainObject(url)) { - options = url; + request = url; url = ''; } - options = _.extend({url: url}, options); - options = _.extend(true, {}, - Http.options, this.options, options + request = _.extend({url: url}, request); + request = _.extend(true, {}, + Http.options, this.options, request ); - var interceptorStack = interceptorFactory.parse(Http.interceptor); - var chain = interceptorFactory.chain(interceptorStack, request); - var promise = interceptorFactory.run(chain, options, this.vm); + request.client = require('./client/xhr')(_); + + var promise = factory(Http.interceptor).run(request); promise = extendPromise(promise.then(function (response) { @@ -33,12 +31,12 @@ module.exports = function (_) { }), this.vm); - if (options.success) { - promise = promise.success(options.success); + if (request.success) { + promise = promise.success(request.success); } - if (options.error) { - promise = promise.error(options.error); + if (request.error) { + promise = promise.error(request.error); } return promise; @@ -88,8 +86,10 @@ module.exports = function (_) { }; Http.interceptor = [ + require('./interceptor/cors')(_), require('./interceptor/option')(_), - require('./interceptor/mime')(_) + require('./interceptor/mime')(_), + require('./interceptor/jsonp')(_) ]; Http.headers = { diff --git a/src/interceptor/cors.js b/src/interceptor/cors.js new file mode 100644 index 00000000..b433bf4d --- /dev/null +++ b/src/interceptor/cors.js @@ -0,0 +1,31 @@ +/** + * CORS Interceptor. + */ + +module.exports = function (_) { + + var originUrl = _.url.parse(location.href); + + return { + + request: function (options) { + + if (options.crossOrigin === null) { + options.crossOrigin = crossOrigin(options.url); + } + + return options; + + } + + }; + + function crossOrigin(url) { + + var requestUrl = _.url.parse(url); + + return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); + + } + +} \ No newline at end of file diff --git a/src/interceptor/factory.js b/src/interceptor/factory.js new file mode 100644 index 00000000..20feef49 --- /dev/null +++ b/src/interceptor/factory.js @@ -0,0 +1,56 @@ +/** + * Interceptor factory. + */ + +var Promise = require('../lib/promise'); + +module.exports = function (_) { + + var skeleton = { + + run: function (request, vm) { + + var chain = [].concat(this.request, [function (request) { + + return request.client.send(request); + + }], this.response); + + return chain.reduce(function (sequence, segment) { + + return sequence.then(function (carry) { + return segment.call(vm, carry); + }) + + }, Promise.resolve(request)); + + }, + + request: [], + + response: [] + + }; + + return function (list) { + + list.forEach(function (interceptor) { + + if (_.isFunction(interceptor)) { + interceptor = interceptor.call(this, Promise); + } + + if (_.isPlainObject(interceptor) && interceptor.request) { + skeleton.request.push(interceptor.request); + } + + if (_.isPlainObject(interceptor) && interceptor.response) { + skeleton.response.push(interceptor.response); + } + + }); + + return skeleton; + + }; +}; \ No newline at end of file diff --git a/src/interceptor/jsonp.js b/src/interceptor/jsonp.js new file mode 100644 index 00000000..46465b42 --- /dev/null +++ b/src/interceptor/jsonp.js @@ -0,0 +1,21 @@ +/** + * JSONP Interceptor. + */ + +module.exports = function (_) { + + return { + + request: function (request) { + + if (request.method == 'JSONP') { + request.client = require('../client/jsonp')(_) + } + + return request; + + } + + }; + +} \ No newline at end of file diff --git a/src/interceptor/mime.js b/src/interceptor/mime.js index d9ed4f16..aa653552 100644 --- a/src/interceptor/mime.js +++ b/src/interceptor/mime.js @@ -6,22 +6,27 @@ module.exports = function (_) { return { - request: function (options) { + request: function (request) { - if (options.emulateJSON && _.isPlainObject(options.data)) { - options.headers['Content-Type'] = 'application/x-www-form-urlencoded'; - options.data = _.url.params(options.data); + if (request.emulateJSON && _.isPlainObject(request.data)) { + request.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + request.data = _.url.params(request.data); } - if (_.isObject(options.data) && /FormData/i.test(options.data.toString())) { - delete options.headers['Content-Type']; + if (request.emulateHTTP && !request.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { + request.headers['X-HTTP-Method-Override'] = request.method; + request.method = 'POST'; } - if (_.isPlainObject(options.data)) { - options.data = JSON.stringify(options.data); + if (_.isObject(request.data) && /FormData/i.test(request.data.toString())) { + delete request.headers['Content-Type']; } - return options; + if (_.isPlainObject(request.data)) { + request.data = JSON.stringify(request.data); + } + + return request; }, diff --git a/src/interceptor/option.js b/src/interceptor/option.js index c3903356..ec6c138e 100644 --- a/src/interceptor/option.js +++ b/src/interceptor/option.js @@ -4,39 +4,26 @@ module.exports = function (_) { - var originUrl = _.url.parse(location.href); - return { - request: function (options) { - - if (options.crossOrigin === null) { - options.crossOrigin = crossOrigin(options.url); - } + request: function (request) { - options.method = options.method.toUpperCase(); - options.headers = _.extend({}, _.http.headers.common, - !options.crossOrigin ? _.http.headers.custom : {}, - _.http.headers[options.method.toLowerCase()], - options.headers + request.method = request.method.toUpperCase(); + request.headers = _.extend({}, _.http.headers.common, + !request.crossOrigin ? _.http.headers.custom : {}, + _.http.headers[request.method.toLowerCase()], + request.headers ); - if (_.isPlainObject(options.data) && /^(GET|JSONP)$/i.test(options.method)) { - _.extend(options.params, options.data); - delete options.data; + if (_.isPlainObject(request.data) && /^(GET|JSONP)$/i.test(request.method)) { + _.extend(request.params, request.data); + delete request.data; } - return options; + return request; } }; - function crossOrigin(url) { - - var requestUrl = _.url.parse(url); - - return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); - } - } \ No newline at end of file diff --git a/src/lib/interceptor.js b/src/lib/interceptor.js deleted file mode 100644 index f0f493af..00000000 --- a/src/lib/interceptor.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Interceptor factory. - */ - -var Promise = require('./promise'); - -module.exports = function (_) { - - return { - - parse: function (interceptorList) { - - var interceptorStack = { - request: [], - response: [] - }; - - interceptorList.forEach(function (interceptor) { - - if (_.isFunction(interceptor)) { - interceptor = interceptor.call(this, Promise); - } - - if (_.isPlainObject(interceptor) && interceptor.request) { - interceptorStack.request.push(interceptor.request); - } - - if (_.isPlainObject(interceptor) && interceptor.response) { - interceptorStack.response.push(interceptor.response); - } - - }); - - return interceptorStack; - - }, - - chain: function (interceptorStack, request) { - return [].concat(interceptorStack.request, [request], interceptorStack.response); - }, - - run: function (chain, options, vm) { - - return chain.reduce(function (sequence, segment) { - - return sequence.then(function (carry) { - return segment.call(vm, carry); - }) - - }, Promise.resolve(options)); - - } - - }; - -}; \ No newline at end of file diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js deleted file mode 100644 index 349a7305..00000000 --- a/src/lib/jsonp.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * JSONP request. - */ - -var Promise = require('./promise'); - -module.exports = function (_, options) { - - var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {}, script, body; - - options.params[options.jsonp] = callback; - - if (_.isFunction(options.beforeSend)) { - options.beforeSend.call(this, {}, options); - } - - return new Promise(function (resolve) { - - script = document.createElement('script'); - script.src = _.url(options); - script.type = 'text/javascript'; - script.async = true; - - window[callback] = function (data) { - body = data; - }; - - var handler = function (event) { - - if (event.type === 'load') { - delete window[callback]; - document.body.removeChild(script); - } - - if (event.type === 'load' && !body) { - event.type = 'error'; - } - - switch (event.type) { - case 'load': - response.status = 200; - break; - case 'error': - response.status = 404; - break; - default: - response.status = 0; - } - - response.ok = event.type === 'load'; - response.reject = !response.ok; - response.responseText = body ? body : ''; - response.header = function () {return null}; - - resolve(response); - }; - - if (options.timeout) { - setTimeout(function () { - handler({type: 'timeout'}); - }, options.timeout); - } - - script.onload = handler; - script.onerror = handler; - - document.body.appendChild(script); - }); - -}; diff --git a/src/lib/request.js b/src/lib/request.js deleted file mode 100644 index 372d00a0..00000000 --- a/src/lib/request.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Request. - */ - -var xhr = require('./xhr'); -var jsonp = require('./jsonp'); - -module.exports = function (_) { - - var originUrl = _.url.parse(location.href); - - return function (options) { - - if (options.crossOrigin === null) { - options.crossOrigin = crossOrigin(options.url); - } - - options.method = options.method.toUpperCase(); - options.headers = _.extend({}, _.http.headers.common, - !options.crossOrigin ? _.http.headers.custom : {}, - _.http.headers[options.method.toLowerCase()], - options.headers - ); - - if (_.isPlainObject(options.data) && /^(GET|JSONP)$/i.test(options.method)) { - _.extend(options.params, options.data); - delete options.data; - } - - if (options.emulateHTTP && !options.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(options.method)) { - options.headers['X-HTTP-Method-Override'] = options.method; - options.method = 'POST'; - } - - return (options.method == 'JSONP' ? jsonp : xhr).call(this.vm, _, options); - - }; - - function crossOrigin(url) { - - var requestUrl = _.url.parse(url); - - return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); - } - -}; \ No newline at end of file diff --git a/src/lib/xhr.js b/src/lib/xhr.js deleted file mode 100644 index bd11a3b7..00000000 --- a/src/lib/xhr.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * XMLHttp request. - */ - -var Promise = require('./promise'); - -module.exports = function (_, options) { - - var request = new XMLHttpRequest(), promise; - - if (options.crossOrigin && !('withCredentials' in request)) { - - request = new XDomainRequest(); - options.headers = {}; - } - - if (_.isPlainObject(options.xhr)) { - _.extend(request, options.xhr); - } - - - if (_.isFunction(options.beforeSend)) { - options.beforeSend.call(this, request, options); - } - - promise = new Promise(function (resolve) { - - request.open(options.method, _.url(options), true); - request.timeout = options.timeout; - - _.each(options.headers, function (value, header) { - request.setRequestHeader(header, value); - }); - - var handler = function (event) { - - request.ok = event.type === 'load'; - request.header = function (name) { - return 'getResponseHeader' in this ? this.getResponseHeader(name) : null; - }; - - if (request.ok && request.status) { - request.ok = request.status >= 200 && request.status < 300; - } - request.reject = !request.ok; - - resolve(request); - }; - - request.onload = handler; - request.onabort = handler; - request.onerror = handler; - request.ontimeout = handler; - - request.send(options.data); - }); - - return promise; -}; From 7c4f55891e54852a69c9cda9417b2ced369f7424 Mon Sep 17 00:00:00 2001 From: Malte Date: Mon, 26 Oct 2015 17:08:00 +0100 Subject: [PATCH 27/61] update interceptor (WIP) --- README.md | 4 +-- src/http.js | 14 +++++---- src/interceptor/cors.js | 8 +++--- src/interceptor/factory.js | 36 ++++++++++++------------ src/interceptor/{option.js => header.js} | 2 +- 5 files changed, 33 insertions(+), 31 deletions(-) rename src/interceptor/{option.js => header.js} (96%) diff --git a/README.md b/README.md index f011f539..3f65f046 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt Interceptors can be defined globally and are used for pre- and postprocessing of a request. ```javascript -Vue.http.interceptor.push({ +Vue.http.interceptors.push({ request: function (options) { return options; @@ -92,7 +92,7 @@ Vue.http.interceptor.push({ If Promises are needed inside of a Interceptor, a factory function can be used. ```javascript -Vue.http.interceptor.push(function (Promise) { +Vue.http.interceptors.push(function (Promise) { return { request: function (options) { if (reject) { diff --git a/src/http.js b/src/http.js index 95f24f64..4e200291 100644 --- a/src/http.js +++ b/src/http.js @@ -9,21 +9,23 @@ module.exports = function (_) { var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; var factory = require('./interceptor/factory')(_); - function Http(url, request) { + function Http(url, options) { + + var request; if (_.isPlainObject(url)) { - request = url; + options = url; url = ''; } - request = _.extend({url: url}, request); + request = _.extend({url: url}, options); request = _.extend(true, {}, Http.options, this.options, request ); request.client = require('./client/xhr')(_); - var promise = factory(Http.interceptor).run(request); + var promise = factory(Http.interceptors).run(request); promise = extendPromise(promise.then(function (response) { @@ -85,9 +87,9 @@ module.exports = function (_) { timeout: 0 }; - Http.interceptor = [ + Http.interceptors = [ require('./interceptor/cors')(_), - require('./interceptor/option')(_), + require('./interceptor/header')(_), require('./interceptor/mime')(_), require('./interceptor/jsonp')(_) ]; diff --git a/src/interceptor/cors.js b/src/interceptor/cors.js index b433bf4d..77a89d06 100644 --- a/src/interceptor/cors.js +++ b/src/interceptor/cors.js @@ -8,13 +8,13 @@ module.exports = function (_) { return { - request: function (options) { + request: function (request) { - if (options.crossOrigin === null) { - options.crossOrigin = crossOrigin(options.url); + if (request.crossOrigin === null) { + request.crossOrigin = crossOrigin(request.url); } - return options; + return request; } diff --git a/src/interceptor/factory.js b/src/interceptor/factory.js index 20feef49..7e4853c0 100644 --- a/src/interceptor/factory.js +++ b/src/interceptor/factory.js @@ -6,33 +6,33 @@ var Promise = require('../lib/promise'); module.exports = function (_) { - var skeleton = { + return function (list) { - run: function (request, vm) { + var stack = { - var chain = [].concat(this.request, [function (request) { + run: function (request, vm) { - return request.client.send(request); + var chain = [].concat(this.request, [function (request) { - }], this.response); + return request.client.send(request); - return chain.reduce(function (sequence, segment) { + }], this.response); - return sequence.then(function (carry) { - return segment.call(vm, carry); - }) + return chain.reduce(function (sequence, segment) { - }, Promise.resolve(request)); + return sequence.then(function (carry) { + return segment.call(vm, carry); + }) - }, + }, Promise.resolve(request)); - request: [], + }, - response: [] + request: [], - }; + response: [] - return function (list) { + }; list.forEach(function (interceptor) { @@ -41,16 +41,16 @@ module.exports = function (_) { } if (_.isPlainObject(interceptor) && interceptor.request) { - skeleton.request.push(interceptor.request); + stack.request.push(interceptor.request); } if (_.isPlainObject(interceptor) && interceptor.response) { - skeleton.response.push(interceptor.response); + stack.response.push(interceptor.response); } }); - return skeleton; + return stack; }; }; \ No newline at end of file diff --git a/src/interceptor/option.js b/src/interceptor/header.js similarity index 96% rename from src/interceptor/option.js rename to src/interceptor/header.js index ec6c138e..a48e3bee 100644 --- a/src/interceptor/option.js +++ b/src/interceptor/header.js @@ -1,5 +1,5 @@ /** - * Options Interceptor. + * Header Interceptor. */ module.exports = function (_) { From 52371e05b03a2c15abdfc38e01a72c5e5e320610 Mon Sep 17 00:00:00 2001 From: Malte Date: Tue, 27 Oct 2015 11:56:43 +0100 Subject: [PATCH 28/61] update interceptor (WIP) --- src/client/jsonp.js | 12 +++++------- src/client/xhr.js | 4 ++-- src/http.js | 1 + src/interceptor/cors.js | 2 +- src/interceptor/header.js | 2 +- src/interceptor/jsonp.js | 4 ++-- src/interceptor/mime.js | 2 +- src/interceptor/timeout.js | 35 +++++++++++++++++++++++++++++++++++ 8 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 src/interceptor/timeout.js diff --git a/src/client/jsonp.js b/src/client/jsonp.js index 27c882cd..7610ebd0 100644 --- a/src/client/jsonp.js +++ b/src/client/jsonp.js @@ -6,6 +6,8 @@ var Promise = require('../lib/promise'); module.exports = function (_) { + var handler; + return { send: function (request) { @@ -29,7 +31,7 @@ module.exports = function (_) { body = data; }; - var handler = function (event) { + handler = function (event) { if (event.type === 'load') { delete window[callback]; @@ -61,12 +63,6 @@ module.exports = function (_) { resolve(response); }; - if (request.timeout) { - setTimeout(function () { - handler({type: 'timeout'}); - }, request.timeout); - } - script.onload = handler; script.onerror = handler; @@ -77,6 +73,8 @@ module.exports = function (_) { cancel: function () { + handler({type: 'cancel'}); + } }; diff --git a/src/client/xhr.js b/src/client/xhr.js index 9bd9677c..1c45e0ca 100644 --- a/src/client/xhr.js +++ b/src/client/xhr.js @@ -26,7 +26,6 @@ module.exports = function (_) { } client.open(request.method, _.url(request), true); - client.timeout = request.timeout; _.each(request.headers, function (value, header) { client.setRequestHeader(header, value); @@ -50,7 +49,6 @@ module.exports = function (_) { client.onload = handler; client.onabort = handler; client.onerror = handler; - client.ontimeout = handler; client.send(request.data); }); @@ -58,7 +56,9 @@ module.exports = function (_) { }, cancel: function () { + client.abort(); + } }; diff --git a/src/http.js b/src/http.js index 4e200291..0c63508a 100644 --- a/src/http.js +++ b/src/http.js @@ -88,6 +88,7 @@ module.exports = function (_) { }; Http.interceptors = [ + require('./interceptor/timeout')(_), require('./interceptor/cors')(_), require('./interceptor/header')(_), require('./interceptor/mime')(_), diff --git a/src/interceptor/cors.js b/src/interceptor/cors.js index 77a89d06..6fd9a18a 100644 --- a/src/interceptor/cors.js +++ b/src/interceptor/cors.js @@ -28,4 +28,4 @@ module.exports = function (_) { } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/interceptor/header.js b/src/interceptor/header.js index a48e3bee..19014ba0 100644 --- a/src/interceptor/header.js +++ b/src/interceptor/header.js @@ -26,4 +26,4 @@ module.exports = function (_) { }; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/interceptor/jsonp.js b/src/interceptor/jsonp.js index 46465b42..af5ed9d5 100644 --- a/src/interceptor/jsonp.js +++ b/src/interceptor/jsonp.js @@ -9,7 +9,7 @@ module.exports = function (_) { request: function (request) { if (request.method == 'JSONP') { - request.client = require('../client/jsonp')(_) + request.client = require('../client/jsonp')(_); } return request; @@ -18,4 +18,4 @@ module.exports = function (_) { }; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/interceptor/mime.js b/src/interceptor/mime.js index aa653552..b8a9bc38 100644 --- a/src/interceptor/mime.js +++ b/src/interceptor/mime.js @@ -44,4 +44,4 @@ module.exports = function (_) { }; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/interceptor/timeout.js b/src/interceptor/timeout.js new file mode 100644 index 00000000..ff0f6a63 --- /dev/null +++ b/src/interceptor/timeout.js @@ -0,0 +1,35 @@ +/** + * Timeout Interceptor. + */ + +module.exports = function (_) { + + var timeout; + + return { + + request: function (request) { + + if (request.timeout) { + timeout = setTimeout(function () { + + request.client.cancel(); + + }, request.timeout); + } + + return request; + + }, + + response: function (response) { + + clearTimeout(timeout); + + return response; + + } + + }; + +}; \ No newline at end of file From 2535db2ef6d202f36e73ac92eed852fb5cfae6ba Mon Sep 17 00:00:00 2001 From: Malte Date: Tue, 27 Oct 2015 14:12:48 +0100 Subject: [PATCH 29/61] add beforeSend interceptor and cleanup --- src/client/jsonp.js | 4 ---- src/client/xhr.js | 8 ++++---- src/http.js | 3 ++- src/interceptor/beforeSend.js | 21 +++++++++++++++++++++ src/interceptor/factory.js | 12 ++++++------ 5 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 src/interceptor/beforeSend.js diff --git a/src/client/jsonp.js b/src/client/jsonp.js index 7610ebd0..c69ea01c 100644 --- a/src/client/jsonp.js +++ b/src/client/jsonp.js @@ -16,10 +16,6 @@ module.exports = function (_) { request.params[request.jsonp] = callback; - if (_.isFunction(request.beforeSend)) { - request.beforeSend.call(this, {}, request); - } - return new Promise(function (resolve) { script = document.createElement('script'); diff --git a/src/client/xhr.js b/src/client/xhr.js index 1c45e0ca..84b8c794 100644 --- a/src/client/xhr.js +++ b/src/client/xhr.js @@ -19,11 +19,11 @@ module.exports = function (_) { request.headers = {}; } - return new Promise(function (resolve) { + if (_.isPlainObject(request.xhr)) { + _.extend(client, request.xhr); + } - if (_.isFunction(request.beforeSend)) { - request.beforeSend.call(this, client, request); - } + return new Promise(function (resolve) { client.open(request.method, _.url(request), true); diff --git a/src/http.js b/src/http.js index 0c63508a..fc78b4f2 100644 --- a/src/http.js +++ b/src/http.js @@ -92,7 +92,8 @@ module.exports = function (_) { require('./interceptor/cors')(_), require('./interceptor/header')(_), require('./interceptor/mime')(_), - require('./interceptor/jsonp')(_) + require('./interceptor/jsonp')(_), + require('./interceptor/beforeSend')(_) ]; Http.headers = { diff --git a/src/interceptor/beforeSend.js b/src/interceptor/beforeSend.js new file mode 100644 index 00000000..0fe448ed --- /dev/null +++ b/src/interceptor/beforeSend.js @@ -0,0 +1,21 @@ +/** + * BeforeSend Interceptor. + */ + +module.exports = function (_) { + + return { + + request: function (request) { + + if (_.isFunction(request.beforeSend)) { + request.beforeSend.call(this, request); + } + + return request; + + } + + }; + +}; \ No newline at end of file diff --git a/src/interceptor/factory.js b/src/interceptor/factory.js index 7e4853c0..6f22f2e8 100644 --- a/src/interceptor/factory.js +++ b/src/interceptor/factory.js @@ -10,6 +10,10 @@ module.exports = function (_) { var stack = { + request: [], + + response: [], + run: function (request, vm) { var chain = [].concat(this.request, [function (request) { @@ -22,15 +26,11 @@ module.exports = function (_) { return sequence.then(function (carry) { return segment.call(vm, carry); - }) + }); }, Promise.resolve(request)); - }, - - request: [], - - response: [] + } }; From 66db41cbf4f1b8a545bbe5bd15c3968988f52496 Mon Sep 17 00:00:00 2001 From: Steffan Date: Fri, 6 Nov 2015 17:52:12 +0100 Subject: [PATCH 30/61] add jasmine test --- .gitignore | 1 + bower.json | 3 +- package.json | 5 ++- src/client/xhr.js | 65 ----------------------------------- src/http.js | 8 ++--- src/interceptor/beforeSend.js | 3 +- src/interceptor/cors.js | 4 +-- src/interceptor/factory.js | 8 ++--- src/interceptor/header.js | 3 +- src/interceptor/jsonp.js | 5 ++- src/interceptor/mime.js | 4 +-- src/interceptor/timeout.js | 6 +--- src/{client => lib}/jsonp.js | 24 +++++-------- src/lib/response.js | 13 +++++++ src/lib/xhr.js | 53 ++++++++++++++++++++++++++++ test/data/test.json | 1 + test/http.js | 23 +++++++++++++ test/index.html | 18 ++++++++++ test/index.js | 7 ++++ test/webpack.config.js | 7 ++++ 20 files changed, 149 insertions(+), 112 deletions(-) delete mode 100644 src/client/xhr.js rename src/{client => lib}/jsonp.js (72%) create mode 100644 src/lib/response.js create mode 100644 src/lib/xhr.js create mode 100644 test/data/test.json create mode 100644 test/http.js create mode 100644 test/index.html create mode 100644 test/index.js create mode 100644 test/webpack.config.js diff --git a/.gitignore b/.gitignore index 90157b1b..f8d83f47 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /node_modules +/test/specs.js .DS_Store \ No newline at end of file diff --git a/bower.json b/bower.json index 81541ea5..a54a3d19 100644 --- a/bower.json +++ b/bower.json @@ -8,7 +8,6 @@ "ignore": [ ".*", "build", - "*.json", - "*.md" + "package.json" ] } \ No newline at end of file diff --git a/package.json b/package.json index ea6556f0..a2525e8b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,9 @@ "description": "A web request service for Vue.js", "main": "src/index.js", "scripts": { - "build": "webpack --config build/webpack.build.config.js" + "build": "webpack --config build/webpack.build.config.js", + "test": "webpack --config test/webpack.config.js", + "install": "npm run build && npm run test" }, "repository": { "type": "git", @@ -22,6 +24,7 @@ }, "homepage": "https://github.com/vuejs/vue-resource#readme", "devDependencies": { + "jasmine-core": "^2.3.4", "webpack": "^1.11.0" } } diff --git a/src/client/xhr.js b/src/client/xhr.js deleted file mode 100644 index 84b8c794..00000000 --- a/src/client/xhr.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * XMLHttp request. - */ - -var Promise = require('../lib/promise'); - -module.exports = function (_) { - - var client; - - return { - - send: function (request) { - - client = new XMLHttpRequest(); - - if (request.crossOrigin && !('withCredentials' in client)) { - client = new XDomainRequest(); - request.headers = {}; - } - - if (_.isPlainObject(request.xhr)) { - _.extend(client, request.xhr); - } - - return new Promise(function (resolve) { - - client.open(request.method, _.url(request), true); - - _.each(request.headers, function (value, header) { - client.setRequestHeader(header, value); - }); - - var handler = function (event) { - - client.ok = event.type === 'load'; - client.header = function (name) { - return 'getResponseHeader' in this ? this.getResponseHeader(name) : null; - }; - - if (client.ok && client.status) { - client.ok = client.status >= 200 && client.status < 300; - } - client.reject = !client.ok; - - resolve(client); - }; - - client.onload = handler; - client.onabort = handler; - client.onerror = handler; - - client.send(request.data); - }); - - }, - - cancel: function () { - - client.abort(); - - } - - }; -}; diff --git a/src/http.js b/src/http.js index fc78b4f2..cc23daf8 100644 --- a/src/http.js +++ b/src/http.js @@ -3,11 +3,11 @@ */ var Promise = require('./lib/promise'); +var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; module.exports = function (_) { - var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; - var factory = require('./interceptor/factory')(_); + var interceptor = require('./interceptor/factory')(_); function Http(url, options) { @@ -23,9 +23,9 @@ module.exports = function (_) { Http.options, this.options, request ); - request.client = require('./client/xhr')(_); + request.client = require('./lib/xhr')(_); - var promise = factory(Http.interceptors).run(request); + var promise = interceptor(Http.interceptors).run(request); promise = extendPromise(promise.then(function (response) { diff --git a/src/interceptor/beforeSend.js b/src/interceptor/beforeSend.js index 0fe448ed..db2e2eae 100644 --- a/src/interceptor/beforeSend.js +++ b/src/interceptor/beforeSend.js @@ -13,9 +13,8 @@ module.exports = function (_) { } return request; - } }; -}; \ No newline at end of file +}; diff --git a/src/interceptor/cors.js b/src/interceptor/cors.js index 6fd9a18a..173749a0 100644 --- a/src/interceptor/cors.js +++ b/src/interceptor/cors.js @@ -15,7 +15,6 @@ module.exports = function (_) { } return request; - } }; @@ -25,7 +24,6 @@ module.exports = function (_) { var requestUrl = _.url.parse(url); return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); - } -}; \ No newline at end of file +}; diff --git a/src/interceptor/factory.js b/src/interceptor/factory.js index 6f22f2e8..675a82f3 100644 --- a/src/interceptor/factory.js +++ b/src/interceptor/factory.js @@ -17,17 +17,13 @@ module.exports = function (_) { run: function (request, vm) { var chain = [].concat(this.request, [function (request) { - return request.client.send(request); - }], this.response); return chain.reduce(function (sequence, segment) { - return sequence.then(function (carry) { return segment.call(vm, carry); }); - }, Promise.resolve(request)); } @@ -51,6 +47,6 @@ module.exports = function (_) { }); return stack; - }; -}; \ No newline at end of file + +}; diff --git a/src/interceptor/header.js b/src/interceptor/header.js index 19014ba0..dbffb0b2 100644 --- a/src/interceptor/header.js +++ b/src/interceptor/header.js @@ -21,9 +21,8 @@ module.exports = function (_) { } return request; - } }; -}; \ No newline at end of file +}; diff --git a/src/interceptor/jsonp.js b/src/interceptor/jsonp.js index af5ed9d5..44efeb5b 100644 --- a/src/interceptor/jsonp.js +++ b/src/interceptor/jsonp.js @@ -9,13 +9,12 @@ module.exports = function (_) { request: function (request) { if (request.method == 'JSONP') { - request.client = require('../client/jsonp')(_); + request.client = require('../lib/jsonp')(_); } return request; - } }; -}; \ No newline at end of file +}; diff --git a/src/interceptor/mime.js b/src/interceptor/mime.js index b8a9bc38..66464e01 100644 --- a/src/interceptor/mime.js +++ b/src/interceptor/mime.js @@ -27,7 +27,6 @@ module.exports = function (_) { } return request; - }, response: function (response) { @@ -39,9 +38,8 @@ module.exports = function (_) { } return response; - } }; -}; \ No newline at end of file +}; diff --git a/src/interceptor/timeout.js b/src/interceptor/timeout.js index ff0f6a63..1e364262 100644 --- a/src/interceptor/timeout.js +++ b/src/interceptor/timeout.js @@ -12,14 +12,11 @@ module.exports = function (_) { if (request.timeout) { timeout = setTimeout(function () { - request.client.cancel(); - }, request.timeout); } return request; - }, response: function (response) { @@ -27,9 +24,8 @@ module.exports = function (_) { clearTimeout(timeout); return response; - } }; -}; \ No newline at end of file +}; diff --git a/src/client/jsonp.js b/src/lib/jsonp.js similarity index 72% rename from src/client/jsonp.js rename to src/lib/jsonp.js index c69ea01c..d49aae6c 100644 --- a/src/client/jsonp.js +++ b/src/lib/jsonp.js @@ -2,7 +2,8 @@ * JSONP request. */ -var Promise = require('../lib/promise'); +var Promise = require('./promise'); +var Response = require('./response'); module.exports = function (_) { @@ -12,7 +13,7 @@ module.exports = function (_) { send: function (request) { - var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {}, script, body; + var callback = '_jsonp' + Math.random().toString(36).substr(2), script, status, body; request.params[request.jsonp] = callback; @@ -40,23 +41,16 @@ module.exports = function (_) { switch (event.type) { case 'load': - response.status = 200; + status = 200; break; case 'error': - response.status = 404; + status = 404; break; default: - response.status = 0; + status = 0; } - response.ok = event.type === 'load'; - response.reject = !response.ok; - response.responseText = body ? body : ''; - response.header = function () { - return null - }; - - resolve(response); + resolve(Response(body, status)); }; script.onload = handler; @@ -68,10 +62,8 @@ module.exports = function (_) { }, cancel: function () { - handler({type: 'cancel'}); - } }; -}; \ No newline at end of file +}; diff --git a/src/lib/response.js b/src/lib/response.js new file mode 100644 index 00000000..4e5690e9 --- /dev/null +++ b/src/lib/response.js @@ -0,0 +1,13 @@ +/** + * Response object. + */ + +module.exports = function (body, status) { + + return { + ok: status >= 200 && status < 300, + status: status || 0, + responseText: body || '' + }; + +}; diff --git a/src/lib/xhr.js b/src/lib/xhr.js new file mode 100644 index 00000000..0872aebd --- /dev/null +++ b/src/lib/xhr.js @@ -0,0 +1,53 @@ +/** + * XMLHttp request. + */ + +var Promise = require('./promise'); +var Response = require('./response'); + +module.exports = function (_) { + + var xhr, handler; + + return { + + send: function (request) { + + xhr = new XMLHttpRequest(); + + if (request.crossOrigin && !('withCredentials' in xhr)) { + xhr = new XDomainRequest(); + request.headers = {}; + } + + if (_.isPlainObject(request.xhr)) { + _.extend(xhr, request.xhr); + } + + return new Promise(function (resolve) { + + xhr.open(request.method, _.url(request), true); + + _.each(request.headers, function (value, header) { + xhr.setRequestHeader(header, value); + }); + + handler = function (event) { + resolve(Response(xhr.responseText, xhr.status)); + }; + + xhr.onload = handler; + xhr.onabort = handler; + xhr.onerror = handler; + + xhr.send(request.data); + }); + + }, + + cancel: function () { + xhr.abort(); + } + + }; +}; diff --git a/test/data/test.json b/test/data/test.json new file mode 100644 index 00000000..18d7acf5 --- /dev/null +++ b/test/data/test.json @@ -0,0 +1 @@ +{"foo": "bar"} \ No newline at end of file diff --git a/test/http.js b/test/http.js new file mode 100644 index 00000000..4c394179 --- /dev/null +++ b/test/http.js @@ -0,0 +1,23 @@ +var Vue = require('vue'); + +describe('Http', function () { + + it('get: test.json', function (done) { + + Vue.http.get('data/test.json', function (data) { + expect(data.foo).toBe('bar'); + done(); + }); + + }); + + it('get: cors-api.com', function (done) { + + Vue.http.get('http://server.cors-api.appspot.com/server?id=1&enable=true', function (data) { + expect(data.shift().requestType).toBe('cors'); + done(); + }); + + }); + +}); diff --git a/test/index.html b/test/index.html new file mode 100644 index 00000000..268c8910 --- /dev/null +++ b/test/index.html @@ -0,0 +1,18 @@ + + + + + Vue Resource - Jasmine + + + + + + + + + + + + + diff --git a/test/index.js b/test/index.js new file mode 100644 index 00000000..2432ef1f --- /dev/null +++ b/test/index.js @@ -0,0 +1,7 @@ +var Vue = require('vue'); +var Resource = require('../src'); + +Vue.use(Resource); + +// require specs +require('./http.js'); diff --git a/test/webpack.config.js b/test/webpack.config.js new file mode 100644 index 00000000..dae0689c --- /dev/null +++ b/test/webpack.config.js @@ -0,0 +1,7 @@ +module.exports = { + entry: './test/index.js', + output: { + path: './test', + filename: 'specs.js' + } +}; From 7e98ecb5c503ce9084568c98f370b8320cd45f59 Mon Sep 17 00:00:00 2001 From: Steffan Date: Fri, 6 Nov 2015 17:53:36 +0100 Subject: [PATCH 31/61] fix favicon path --- test/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.html b/test/index.html index 268c8910..a60aca56 100644 --- a/test/index.html +++ b/test/index.html @@ -4,7 +4,7 @@ Vue Resource - Jasmine - + From d8687480654ae35637e179b7ab67804044ed40d9 Mon Sep 17 00:00:00 2001 From: Steffan Date: Sat, 7 Nov 2015 09:58:57 +0100 Subject: [PATCH 32/61] update dist --- dist/vue-resource.js | 591 ++++++++++++++++++++++++++++----------- dist/vue-resource.min.js | 2 +- 2 files changed, 435 insertions(+), 158 deletions(-) diff --git a/dist/vue-resource.js b/dist/vue-resource.js index 1f48b107..058bd254 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -70,19 +70,19 @@ return /******/ (function(modules) { // webpackBootstrap Vue.url = __webpack_require__(2)(_); Vue.http = __webpack_require__(3)(_); - Vue.resource = __webpack_require__(7)(_); + Vue.resource = __webpack_require__(15)(_); Object.defineProperties(Vue.prototype, { $url: { get: function () { - return this._url || (this._url = _.options(Vue.url, this, this.$options.url)); + return _.options(Vue.url, this, this.$options.url); } }, $http: { get: function () { - return this._http || (this._http = _.options(Vue.http, this, this.$options.http)); + return _.options(Vue.http, this, this.$options.http); } }, @@ -101,6 +101,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = install; + /***/ }, /* 1 */ /***/ function(module, exports) { @@ -111,7 +112,13 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (Vue) { - var _ = Vue.util.extend({}, Vue.util); + var _ = Vue.util.extend({}, Vue.util), config = Vue.config; + + _.warn = function (msg) { + if (window.console && (!config.silent || config.debug)) { + console.warn('[VueResource warn]: ' + msg); + } + }; _.isString = function (value) { return typeof value === 'string'; @@ -358,72 +365,43 @@ return /******/ (function(modules) { // webpackBootstrap * Service for sending network requests. */ - var xhr = __webpack_require__(4); - var jsonp = __webpack_require__(6); - var Promise = __webpack_require__(5); + var Promise = __webpack_require__(4); + var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; module.exports = function (_) { - var originUrl = _.url.parse(location.href); - var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; + var interceptor = __webpack_require__(5)(_); function Http(url, options) { - var promise; + var request; if (_.isPlainObject(url)) { options = url; url = ''; } - options = _.extend({url: url}, options); - options = _.extend(true, {}, - Http.options, this.options, options + request = _.extend({url: url}, options); + request = _.extend(true, {}, + Http.options, this.options, request ); - if (options.crossOrigin === null) { - options.crossOrigin = crossOrigin(options.url); - } + request.client = __webpack_require__(6)(_); - options.method = options.method.toUpperCase(); - options.headers = _.extend({}, Http.headers.common, - !options.crossOrigin ? Http.headers.custom : {}, - Http.headers[options.method.toLowerCase()], - options.headers - ); + var promise = interceptor(Http.interceptors).run(request); - if (_.isPlainObject(options.data) && /^(GET|JSONP)$/i.test(options.method)) { - _.extend(options.params, options.data); - delete options.data; - } + promise = extendPromise(promise.then(function (response) { - if (options.emulateHTTP && !options.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(options.method)) { - options.headers['X-HTTP-Method-Override'] = options.method; - options.method = 'POST'; - } + return response.ok ? response : Promise.reject(response); - if (options.emulateJSON && _.isPlainObject(options.data)) { - options.headers['Content-Type'] = 'application/x-www-form-urlencoded'; - options.data = _.url.params(options.data); - } + }), this.vm); - if (_.isObject(options.data) && /FormData/i.test(options.data.toString())) { - delete options.headers['Content-Type']; + if (request.success) { + promise = promise.success(request.success); } - if (_.isPlainObject(options.data)) { - options.data = JSON.stringify(options.data); - } - - promise = (options.method == 'JSONP' ? jsonp : xhr).call(this.vm, _, options); - promise = extendPromise(promise.then(transformResponse, transformResponse), this.vm); - - if (options.success) { - promise = promise.success(options.success); - } - - if (options.error) { - promise = promise.error(options.error); + if (request.error) { + promise = promise.error(request.error); } return promise; @@ -459,24 +437,6 @@ return /******/ (function(modules) { // webpackBootstrap return promise; } - function transformResponse(response) { - - try { - response.data = JSON.parse(response.responseText); - } catch (e) { - response.data = response.responseText; - } - - return response.ok ? response : Promise.reject(response); - } - - function crossOrigin(url) { - - var requestUrl = _.url.parse(url); - - return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); - } - Http.options = { method: 'get', params: {}, @@ -486,9 +446,19 @@ return /******/ (function(modules) { // webpackBootstrap beforeSend: null, crossOrigin: null, emulateHTTP: false, - emulateJSON: false + emulateJSON: false, + timeout: 0 }; + Http.interceptors = [ + __webpack_require__(8)(_), + __webpack_require__(9)(_), + __webpack_require__(10)(_), + __webpack_require__(11)(_), + __webpack_require__(12)(_), + __webpack_require__(14)(_) + ]; + Http.headers = { put: jsonType, post: jsonType, @@ -518,63 +488,6 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 4 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * XMLHttp request. - */ - - var Promise = __webpack_require__(5); - var XDomain = window.XDomainRequest; - - module.exports = function (_, options) { - - var request = new XMLHttpRequest(), promise; - - if (XDomain && options.crossOrigin) { - request = new XDomainRequest(); options.headers = {}; - } - - if (_.isPlainObject(options.xhr)) { - _.extend(request, options.xhr); - } - - if (_.isFunction(options.beforeSend)) { - options.beforeSend.call(this, request, options); - } - - promise = new Promise(function (resolve, reject) { - - request.open(options.method, _.url(options), true); - - _.each(options.headers, function (value, header) { - request.setRequestHeader(header, value); - }); - - var handler = function (event) { - - request.ok = event.type === 'load'; - - if (request.ok && request.status) { - request.ok = request.status >= 200 && request.status < 300; - } - - (request.ok ? resolve : reject)(request); - }; - - request.onload = handler; - request.onabort = handler; - request.onerror = handler; - - request.send(options.data); - }); - - return promise; - }; - - -/***/ }, -/* 5 */ /***/ function(module, exports) { /** @@ -790,63 +703,427 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 6 */ +/* 5 */ /***/ function(module, exports, __webpack_require__) { /** - * JSONP request. + * Interceptor factory. */ - var Promise = __webpack_require__(5); + var Promise = __webpack_require__(4); - module.exports = function (_, options) { + module.exports = function (_) { - var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {}, script, body; + return function (list) { - options.params[options.jsonp] = callback; + var stack = { - if (_.isFunction(options.beforeSend)) { - options.beforeSend.call(this, {}, options); - } + request: [], - return new Promise(function (resolve, reject) { + response: [], + + run: function (request, vm) { + + var chain = [].concat(this.request, [function (request) { + return request.client.send(request); + }], this.response); - script = document.createElement('script'); - script.src = _.url(options); - script.type = 'text/javascript'; - script.async = true; + return chain.reduce(function (sequence, segment) { + return sequence.then(function (carry) { + return segment.call(vm, carry); + }); + }, Promise.resolve(request)); + + } - window[callback] = function (data) { - body = data; }; - var handler = function (event) { + list.forEach(function (interceptor) { - delete window[callback]; - document.body.removeChild(script); + if (_.isFunction(interceptor)) { + interceptor = interceptor.call(this, Promise); + } - if (event.type === 'load' && !body) { - event.type = 'error'; + if (_.isPlainObject(interceptor) && interceptor.request) { + stack.request.push(interceptor.request); } - response.ok = event.type !== 'error'; - response.status = response.ok ? 200 : 404; - response.responseText = body ? body : event.type; + if (_.isPlainObject(interceptor) && interceptor.response) { + stack.response.push(interceptor.response); + } - (response.ok ? resolve : reject)(response); - }; + }); - script.onload = handler; - script.onerror = handler; + return stack; + }; - document.body.appendChild(script); - }); + }; + + +/***/ }, +/* 6 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * XMLHttp request. + */ + + var Promise = __webpack_require__(4); + var Response = __webpack_require__(7); + + module.exports = function (_) { + + var xhr, handler; + + return { + send: function (request) { + + xhr = new XMLHttpRequest(); + + if (request.crossOrigin && !('withCredentials' in xhr)) { + xhr = new XDomainRequest(); + request.headers = {}; + } + + if (_.isPlainObject(request.xhr)) { + _.extend(xhr, request.xhr); + } + + return new Promise(function (resolve) { + + xhr.open(request.method, _.url(request), true); + + _.each(request.headers, function (value, header) { + xhr.setRequestHeader(header, value); + }); + + handler = function (event) { + resolve(Response(xhr.responseText, xhr.status)); + }; + + xhr.onload = handler; + xhr.onabort = handler; + xhr.onerror = handler; + + xhr.send(request.data); + }); + + }, + + cancel: function () { + xhr.abort(); + } + + }; }; /***/ }, /* 7 */ +/***/ function(module, exports) { + + /** + * Response object. + */ + + module.exports = function (body, status) { + + return { + ok: status >= 200 && status < 300, + status: status || 0, + responseText: body || '' + }; + + }; + + +/***/ }, +/* 8 */ +/***/ function(module, exports) { + + /** + * Timeout Interceptor. + */ + + module.exports = function (_) { + + var timeout; + + return { + + request: function (request) { + + if (request.timeout) { + timeout = setTimeout(function () { + request.client.cancel(); + }, request.timeout); + } + + return request; + }, + + response: function (response) { + + clearTimeout(timeout); + + return response; + } + + }; + + }; + + +/***/ }, +/* 9 */ +/***/ function(module, exports) { + + /** + * CORS Interceptor. + */ + + module.exports = function (_) { + + var originUrl = _.url.parse(location.href); + + return { + + request: function (request) { + + if (request.crossOrigin === null) { + request.crossOrigin = crossOrigin(request.url); + } + + return request; + } + + }; + + function crossOrigin(url) { + + var requestUrl = _.url.parse(url); + + return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); + } + + }; + + +/***/ }, +/* 10 */ +/***/ function(module, exports) { + + /** + * Header Interceptor. + */ + + module.exports = function (_) { + + return { + + request: function (request) { + + request.method = request.method.toUpperCase(); + request.headers = _.extend({}, _.http.headers.common, + !request.crossOrigin ? _.http.headers.custom : {}, + _.http.headers[request.method.toLowerCase()], + request.headers + ); + + if (_.isPlainObject(request.data) && /^(GET|JSONP)$/i.test(request.method)) { + _.extend(request.params, request.data); + delete request.data; + } + + return request; + } + + }; + + }; + + +/***/ }, +/* 11 */ +/***/ function(module, exports) { + + /** + * Mime Interceptor. + */ + + module.exports = function (_) { + + return { + + request: function (request) { + + if (request.emulateJSON && _.isPlainObject(request.data)) { + request.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + request.data = _.url.params(request.data); + } + + if (request.emulateHTTP && !request.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { + request.headers['X-HTTP-Method-Override'] = request.method; + request.method = 'POST'; + } + + if (_.isObject(request.data) && /FormData/i.test(request.data.toString())) { + delete request.headers['Content-Type']; + } + + if (_.isPlainObject(request.data)) { + request.data = JSON.stringify(request.data); + } + + return request; + }, + + response: function (response) { + + try { + response.data = JSON.parse(response.responseText); + } catch (e) { + response.data = response.responseText; + } + + return response; + } + + }; + + }; + + +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * JSONP Interceptor. + */ + + module.exports = function (_) { + + return { + + request: function (request) { + + if (request.method == 'JSONP') { + request.client = __webpack_require__(13)(_); + } + + return request; + } + + }; + + }; + + +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * JSONP request. + */ + + var Promise = __webpack_require__(4); + var Response = __webpack_require__(7); + + module.exports = function (_) { + + var handler; + + return { + + send: function (request) { + + var callback = '_jsonp' + Math.random().toString(36).substr(2), script, status, body; + + request.params[request.jsonp] = callback; + + return new Promise(function (resolve) { + + script = document.createElement('script'); + script.src = _.url(request); + script.type = 'text/javascript'; + script.async = true; + + window[callback] = function (data) { + body = data; + }; + + handler = function (event) { + + if (event.type === 'load') { + delete window[callback]; + document.body.removeChild(script); + } + + if (event.type === 'load' && !body) { + event.type = 'error'; + } + + switch (event.type) { + case 'load': + status = 200; + break; + case 'error': + status = 404; + break; + default: + status = 0; + } + + resolve(Response(body, status)); + }; + + script.onload = handler; + script.onerror = handler; + + document.body.appendChild(script); + }); + + }, + + cancel: function () { + handler({type: 'cancel'}); + } + + }; + }; + + +/***/ }, +/* 14 */ +/***/ function(module, exports) { + + /** + * BeforeSend Interceptor. + */ + + module.exports = function (_) { + + return { + + request: function (request) { + + if (_.isFunction(request.beforeSend)) { + request.beforeSend.call(this, request); + } + + return request; + } + + }; + + }; + + +/***/ }, +/* 15 */ /***/ function(module, exports) { /** @@ -855,7 +1132,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - function Resource(url, params, actions) { + function Resource(url, params, actions, options) { var self = this, resource = {}; @@ -866,7 +1143,7 @@ return /******/ (function(modules) { // webpackBootstrap _.each(actions, function (action, name) { - action = _.extend(true, {url: url, params: params || {}}, action); + action = _.extend(true, {url: url, params: params || {}}, options, action); resource[name] = function () { return (self.$http || _.http)(opts(action, arguments)); diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index 88ec5e30..c3ff0150 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -4,4 +4,4 @@ * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(7)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return this._url||(this._url=e.options(t.url,this,this.$options.url))}},$http:{get:function(){return this._http||(this._http=e.options(t.http,this,this.$options.http))}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var a in r)o&&(n.isPlainObject(r[a])||n.isArray(r[a]))?(n.isPlainObject(r[a])&&!n.isPlainObject(t[a])&&(t[a]={}),n.isArray(r[a])&&!n.isArray(t[a])&&(t[a]=[]),e(t[a],r[a],o)):void 0!==r[a]&&(t[a]=r[a])}var n=t.util.extend({},t.util);return n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&a.status<300),(a.ok?n:r)(a)};a.onload=o,a.onabort=o,a.onerror=o,a.send(e.data)})}},function(t,e){function n(t){this.state=a,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,a=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){a[n]=r,o+=1,o===t.length&&e(a)}}var o=0,a=[];0===t.length&&e(a);for(var i=0;i=200&&300>e,status:e||0,responseText:t||""}}},function(t,e){t.exports=function(t){var e;return{request:function(t){return t.timeout&&(e=setTimeout(function(){t.client.cancel()},t.timeout)),t},response:function(t){return clearTimeout(e),t}}}},function(t,e){t.exports=function(t){function e(e){var r=t.url.parse(e);return r.protocol!==n.protocol||r.host!==n.host}var n=t.url.parse(location.href);return{request:function(t){return null===t.crossOrigin&&(t.crossOrigin=e(t.url)),t}}}},function(t,e){t.exports=function(t){return{request:function(e){return e.method=e.method.toUpperCase(),e.headers=t.extend({},t.http.headers.common,e.crossOrigin?{}:t.http.headers.custom,t.http.headers[e.method.toLowerCase()],e.headers),t.isPlainObject(e.data)&&/^(GET|JSONP)$/i.test(e.method)&&(t.extend(e.params,e.data),delete e.data),e}}}},function(t,e){t.exports=function(t){return{request:function(e){return e.emulateJSON&&t.isPlainObject(e.data)&&(e.headers["Content-Type"]="application/x-www-form-urlencoded",e.data=t.url.params(e.data)),e.emulateHTTP&&!e.crossOrigin&&/^(PUT|PATCH|DELETE)$/i.test(e.method)&&(e.headers["X-HTTP-Method-Override"]=e.method,e.method="POST"),t.isObject(e.data)&&/FormData/i.test(e.data.toString())&&delete e.headers["Content-Type"],t.isPlainObject(e.data)&&(e.data=JSON.stringify(e.data)),e},response:function(t){try{t.data=JSON.parse(t.responseText)}catch(e){t.data=t.responseText}return t}}}},function(t,e,n){t.exports=function(t){return{request:function(e){return"JSONP"==e.method&&(e.client=n(13)(t)),e}}}},function(t,e,n){var r=n(4),o=n(7);t.exports=function(t){var e;return{send:function(n){var i,u,s,a="_jsonp"+Math.random().toString(36).substr(2);return n.params[n.jsonp]=a,new r(function(r){i=document.createElement("script"),i.src=t.url(n),i.type="text/javascript",i.async=!0,window[a]=function(t){s=t},e=function(t){switch("load"===t.type&&(delete window[a],document.body.removeChild(i)),"load"!==t.type||s||(t.type="error"),t.type){case"load":u=200;break;case"error":u=404;break;default:u=0}r(o(s,u))},i.onload=e,i.onerror=e,document.body.appendChild(i)})},cancel:function(){e({type:"cancel"})}}}},function(t,e){t.exports=function(t){return{request:function(e){return t.isFunction(e.beforeSend)&&e.beforeSend.call(this,e),e}}}},function(t,e){t.exports=function(t){function e(r,o,i,u){var s=this,a={};return i=t.extend({},e.actions,i),t.each(i,function(e,i){e=t.extend(!0,{url:r,params:o||{}},u,e),a[i]=function(){return(s.$http||t.http)(n(e,arguments))}}),a}function n(e,n){var r,o,i,u=t.extend({},e),s={};switch(n.length){case 4:i=n[3],o=n[2];case 3:case 2:if(!t.isFunction(n[1])){s=n[0],r=n[1],o=n[2];break}if(t.isFunction(n[0])){o=n[0],i=n[1];break}o=n[1],i=n[2];case 1:t.isFunction(n[0])?o=n[0]:/^(POST|PUT|PATCH)$/i.test(u.method)?r=n[0]:s=n[0];break;case 0:break;default:throw"Expected up to 4 arguments [params, data, success, error], got "+n.length+" arguments"}return u.data=r,u.params=t.extend({},u.params,s),o&&(u.success=o),i&&(u.error=i),u}return e.actions={get:{method:"GET"},save:{method:"POST"},query:{method:"GET"},update:{method:"PUT"},remove:{method:"DELETE"},"delete":{method:"DELETE"}},t.resource=e}}])}); \ No newline at end of file From 31b51a8c114e08e9f1120500c308a5b1edeb807a Mon Sep 17 00:00:00 2001 From: Steffan Date: Fri, 20 Nov 2015 14:19:44 +0100 Subject: [PATCH 33/61] update interceptor implementation --- dist/vue-resource.js | 438 +++++++++++-------- dist/vue-resource.min.js | 2 +- src/client/jsonp.js | 60 +++ src/client/xdr.js | 38 ++ src/client/xhr.js | 94 ++++ src/http.js | 27 +- src/interceptor/{beforeSend.js => before.js} | 2 +- src/interceptor/cors.js | 5 + src/interceptor/factory.js | 52 --- src/interceptor/index.js | 42 ++ src/interceptor/jsonp.js | 2 +- src/interceptor/method.js | 21 + src/interceptor/mime.js | 11 +- src/lib/jsonp.js | 69 --- src/lib/response.js | 13 - src/lib/util.js | 8 + src/lib/xhr.js | 53 --- 17 files changed, 550 insertions(+), 387 deletions(-) create mode 100644 src/client/jsonp.js create mode 100644 src/client/xdr.js create mode 100644 src/client/xhr.js rename src/interceptor/{beforeSend.js => before.js} (90%) delete mode 100644 src/interceptor/factory.js create mode 100644 src/interceptor/index.js create mode 100644 src/interceptor/method.js delete mode 100644 src/lib/jsonp.js delete mode 100644 src/lib/response.js delete mode 100644 src/lib/xhr.js diff --git a/dist/vue-resource.js b/dist/vue-resource.js index 058bd254..cbd05e8b 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -70,7 +70,7 @@ return /******/ (function(modules) { // webpackBootstrap Vue.url = __webpack_require__(2)(_); Vue.http = __webpack_require__(3)(_); - Vue.resource = __webpack_require__(15)(_); + Vue.resource = __webpack_require__(16)(_); Object.defineProperties(Vue.prototype, { @@ -120,6 +120,14 @@ return /******/ (function(modules) { // webpackBootstrap } }; + _.trim = function (str) { + return str.replace(/^\s*|\s*$/g, ''); + }; + + _.toLower = function (str) { + return str ? str.toLowerCase() : ''; + }; + _.isString = function (value) { return typeof value === 'string'; }; @@ -366,15 +374,16 @@ return /******/ (function(modules) { // webpackBootstrap */ var Promise = __webpack_require__(4); - var jsonType = {'Content-Type': 'application/json;charset=utf-8'}; + var jsonType = {'Content-Type': 'application/json'}; module.exports = function (_) { var interceptor = __webpack_require__(5)(_); + var defaultClient = __webpack_require__(6)(_); function Http(url, options) { - var request; + var client = defaultClient, request, promise; if (_.isPlainObject(url)) { options = url; @@ -386,12 +395,13 @@ return /******/ (function(modules) { // webpackBootstrap Http.options, this.options, request ); - request.client = __webpack_require__(6)(_); + Http.interceptors.forEach(function (i) { + client = interceptor(i, this.vm)(client); + }, this); - var promise = interceptor(Http.interceptors).run(request); - - promise = extendPromise(promise.then(function (response) { + promise = extendPromise(client(request).then(function (response) { + response.ok = response.status >= 200 && response.status < 300; return response.ok ? response : Promise.reject(response); }), this.vm); @@ -451,12 +461,13 @@ return /******/ (function(modules) { // webpackBootstrap }; Http.interceptors = [ + __webpack_require__(7)(_), __webpack_require__(8)(_), - __webpack_require__(9)(_), __webpack_require__(10)(_), __webpack_require__(11)(_), __webpack_require__(12)(_), - __webpack_require__(14)(_) + __webpack_require__(13)(_), + __webpack_require__(15)(_) ]; Http.headers = { @@ -714,48 +725,38 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - return function (list) { - - var stack = { - - request: [], + return function (handler, vm) { + return function (client) { + return function (request) { - response: [], + if (_.isFunction(handler.request)) { + request = handler.request.call(vm, request); + } - run: function (request, vm) { + return when(request, function (request) { + return when(client(request), function (response) { - var chain = [].concat(this.request, [function (request) { - return request.client.send(request); - }], this.response); + if (_.isFunction(handler.response)) { + response = handler.response.call(vm, response); + } - return chain.reduce(function (sequence, segment) { - return sequence.then(function (carry) { - return segment.call(vm, carry); + return response; }); - }, Promise.resolve(request)); - - } - + }); + }; }; + }; - list.forEach(function (interceptor) { - - if (_.isFunction(interceptor)) { - interceptor = interceptor.call(this, Promise); - } + function when(value, fulfilled, rejected) { - if (_.isPlainObject(interceptor) && interceptor.request) { - stack.request.push(interceptor.request); - } + var promise = Promise.resolve(value); - if (_.isPlainObject(interceptor) && interceptor.response) { - stack.response.push(interceptor.response); - } - - }); + if (arguments.length < 2) { + return promise; + } - return stack; - }; + return promise.then(fulfilled, rejected); + } }; @@ -769,53 +770,95 @@ return /******/ (function(modules) { // webpackBootstrap */ var Promise = __webpack_require__(4); - var Response = __webpack_require__(7); module.exports = function (_) { - var xhr, handler; + return function (request) { + return new Promise(function (resolve) { - return { + var xhr = new XMLHttpRequest(), response = {}, handler; - send: function (request) { - - xhr = new XMLHttpRequest(); + request.cancel = function () { + xhr.abort(); + }; - if (request.crossOrigin && !('withCredentials' in xhr)) { - xhr = new XDomainRequest(); - request.headers = {}; - } + xhr.open(request.method, _.url(request), true); if (_.isPlainObject(request.xhr)) { _.extend(xhr, request.xhr); } - return new Promise(function (resolve) { + _.each(request.headers || {}, function (value, header) { + xhr.setRequestHeader(header, value); + }); - xhr.open(request.method, _.url(request), true); + handler = function (event) { - _.each(request.headers, function (value, header) { - xhr.setRequestHeader(header, value); - }); + response.data = xhr.responseText; + response.status = xhr.status; + response.statusText = xhr.statusText; + response.headers = getHeaders(xhr); - handler = function (event) { - resolve(Response(xhr.responseText, xhr.status)); - }; + resolve(response); + }; - xhr.onload = handler; - xhr.onabort = handler; - xhr.onerror = handler; + xhr.onload = handler; + xhr.onabort = handler; + xhr.onerror = handler; - xhr.send(request.data); - }); + xhr.send(request.data); + }); - }, + }; - cancel: function () { - xhr.abort(); + function getHeaders(xhr) { + + var headers; + + if (!headers) { + headers = parseHeaders(xhr.getAllResponseHeaders()); } - }; + return function (name) { + + if (name) { + return headers[_.toLower(name)]; + } + + return headers; + }; + } + + function parseHeaders(str) { + + var headers = {}, value, name, i; + + if (_.isString(str)) { + _.each(str.split('\n'), function (row) { + + i = row.indexOf(':'); + name = _.trim(_.toLower(row.slice(0, i))); + value = _.trim(row.slice(i + 1)); + + if (headers[name]) { + + if (_.isArray(headers[name])) { + headers[name].push(value); + } else { + headers[name] = [headers[name], value]; + } + + } else { + + headers[name] = value; + } + + }); + } + + return headers; + } + }; @@ -824,15 +867,22 @@ return /******/ (function(modules) { // webpackBootstrap /***/ function(module, exports) { /** - * Response object. + * Before Interceptor. */ - module.exports = function (body, status) { + module.exports = function (_) { return { - ok: status >= 200 && status < 300, - status: status || 0, - responseText: body || '' + + request: function (request) { + + if (_.isFunction(request.beforeSend)) { + request.beforeSend.call(this, request); + } + + return request; + } + }; }; @@ -840,34 +890,23 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 8 */ -/***/ function(module, exports) { +/***/ function(module, exports, __webpack_require__) { /** - * Timeout Interceptor. + * JSONP Interceptor. */ module.exports = function (_) { - var timeout; - return { request: function (request) { - if (request.timeout) { - timeout = setTimeout(function () { - request.client.cancel(); - }, request.timeout); + if (request.method == 'JSONP') { + request.client = __webpack_require__(9)(_); } return request; - }, - - response: function (response) { - - clearTimeout(timeout); - - return response; } }; @@ -877,35 +916,67 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 9 */ -/***/ function(module, exports) { +/***/ function(module, exports, __webpack_require__) { /** - * CORS Interceptor. + * JSONP request. */ + var Promise = __webpack_require__(4); + module.exports = function (_) { - var originUrl = _.url.parse(location.href); + return function (request) { + return new Promise(function (resolve) { - return { + var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {}, handler, script; - request: function (request) { + request.params[request.jsonp] = callback; + request.cancel = function () { + handler({type: 'cancel'}); + }; - if (request.crossOrigin === null) { - request.crossOrigin = crossOrigin(request.url); - } + script = document.createElement('script'); + script.src = _.url(request); + script.type = 'text/javascript'; + script.async = true; - return request; - } + window[callback] = function (data) { + response.data = data; + }; - }; + handler = function (event) { - function crossOrigin(url) { + if (event.type === 'load') { + delete window[callback]; + document.body.removeChild(script); + } - var requestUrl = _.url.parse(url); + if (event.type === 'load' && !response.data) { + event.type = 'error'; + } - return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); - } + switch (event.type) { + case 'load': + response.status = 200; + break; + case 'error': + response.status = 404; + break; + default: + response.status = 0; + } + + resolve(response); + }; + + script.onload = handler; + script.onerror = handler; + + document.body.appendChild(script); + }); + + }; }; @@ -915,7 +986,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ function(module, exports) { /** - * Header Interceptor. + * HTTP method override Interceptor. */ module.exports = function (_) { @@ -924,16 +995,9 @@ return /******/ (function(modules) { // webpackBootstrap request: function (request) { - request.method = request.method.toUpperCase(); - request.headers = _.extend({}, _.http.headers.common, - !request.crossOrigin ? _.http.headers.custom : {}, - _.http.headers[request.method.toLowerCase()], - request.headers - ); - - if (_.isPlainObject(request.data) && /^(GET|JSONP)$/i.test(request.method)) { - _.extend(request.params, request.data); - delete request.data; + if (request.emulateHTTP && !request.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { + request.headers['X-HTTP-Method-Override'] = request.method; + request.method = 'POST'; } return request; @@ -963,11 +1027,6 @@ return /******/ (function(modules) { // webpackBootstrap request.data = _.url.params(request.data); } - if (request.emulateHTTP && !request.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { - request.headers['X-HTTP-Method-Override'] = request.method; - request.method = 'POST'; - } - if (_.isObject(request.data) && /FormData/i.test(request.data.toString())) { delete request.headers['Content-Type']; } @@ -982,10 +1041,8 @@ return /******/ (function(modules) { // webpackBootstrap response: function (response) { try { - response.data = JSON.parse(response.responseText); - } catch (e) { - response.data = response.responseText; - } + response.data = JSON.parse(response.data); + } catch (e) {} return response; } @@ -997,10 +1054,10 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 12 */ -/***/ function(module, exports, __webpack_require__) { +/***/ function(module, exports) { /** - * JSONP Interceptor. + * Header Interceptor. */ module.exports = function (_) { @@ -1009,8 +1066,16 @@ return /******/ (function(modules) { // webpackBootstrap request: function (request) { - if (request.method == 'JSONP') { - request.client = __webpack_require__(13)(_); + request.method = request.method.toUpperCase(); + request.headers = _.extend({}, _.http.headers.common, + !request.crossOrigin ? _.http.headers.custom : {}, + _.http.headers[request.method.toLowerCase()], + request.headers + ); + + if (_.isPlainObject(request.data) && /^(GET|JSONP)$/i.test(request.method)) { + _.extend(request.params, request.data); + delete request.data; } return request; @@ -1026,95 +1091,116 @@ return /******/ (function(modules) { // webpackBootstrap /***/ function(module, exports, __webpack_require__) { /** - * JSONP request. + * CORS Interceptor. */ - var Promise = __webpack_require__(4); - var Response = __webpack_require__(7); - module.exports = function (_) { - var handler; + var xhrCors = 'withCredentials' in new XMLHttpRequest(); + var originUrl = _.url.parse(location.href); return { - send: function (request) { + request: function (request) { + + if (request.crossOrigin === null) { + request.crossOrigin = crossOrigin(request.url); + } + + if (request.crossOrigin && !xhrCors) { + request.client = __webpack_require__(14)(_); + } - var callback = '_jsonp' + Math.random().toString(36).substr(2), script, status, body; + return request; + } - request.params[request.jsonp] = callback; + }; - return new Promise(function (resolve) { + function crossOrigin(url) { - script = document.createElement('script'); - script.src = _.url(request); - script.type = 'text/javascript'; - script.async = true; + var requestUrl = _.url.parse(url); - window[callback] = function (data) { - body = data; - }; + return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); + } - handler = function (event) { + }; - if (event.type === 'load') { - delete window[callback]; - document.body.removeChild(script); - } - if (event.type === 'load' && !body) { - event.type = 'error'; - } +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { - switch (event.type) { - case 'load': - status = 200; - break; - case 'error': - status = 404; - break; - default: - status = 0; - } + /** + * XDomain request (Internet Explorer). + */ - resolve(Response(body, status)); - }; + var Promise = __webpack_require__(4); - script.onload = handler; - script.onerror = handler; + module.exports = function (_) { - document.body.appendChild(script); - }); + return function (request) { + return new Promise(function (resolve) { - }, + var xdr = new XDomainRequest(), response = {}, handler; - cancel: function () { - handler({type: 'cancel'}); - } + request.cancel = function () { + xdr.abort(); + }; + + xdr.open(request.method, _.url(request), true); + + handler = function (event) { + + response.data = xdr.responseText; + response.status = xdr.status; + response.statusText = xdr.statusText; + + resolve(response); + }; + + xdr.onload = handler; + xdr.onabort = handler; + xdr.onerror = handler; + xdr.onprogress = function () {}; + + xdr.send(request.data); + }); }; + }; /***/ }, -/* 14 */ +/* 15 */ /***/ function(module, exports) { /** - * BeforeSend Interceptor. + * Timeout Interceptor. */ module.exports = function (_) { + var timeout; + return { request: function (request) { - if (_.isFunction(request.beforeSend)) { - request.beforeSend.call(this, request); + if (request.timeout) { + timeout = setTimeout(function () { + request.client.cancel(); + }, request.timeout); } return request; + }, + + response: function (response) { + + clearTimeout(timeout); + + return response; } }; @@ -1123,7 +1209,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 15 */ +/* 16 */ /***/ function(module, exports) { /** diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index c3ff0150..1c7527f4 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -4,4 +4,4 @@ * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(15)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return e.options(t.url,this,this.$options.url)}},$http:{get:function(){return e.options(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var i in r)o&&(n.isPlainObject(r[i])||n.isArray(r[i]))?(n.isPlainObject(r[i])&&!n.isPlainObject(t[i])&&(t[i]={}),n.isArray(r[i])&&!n.isArray(t[i])&&(t[i]=[]),e(t[i],r[i],o)):void 0!==r[i]&&(t[i]=r[i])}var n=t.util.extend({},t.util),r=t.config;return n.warn=function(t){!window.console||r.silent&&!r.debug||console.warn("[VueResource warn]: "+t)},n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&300>e,status:e||0,responseText:t||""}}},function(t,e){t.exports=function(t){var e;return{request:function(t){return t.timeout&&(e=setTimeout(function(){t.client.cancel()},t.timeout)),t},response:function(t){return clearTimeout(e),t}}}},function(t,e){t.exports=function(t){function e(e){var r=t.url.parse(e);return r.protocol!==n.protocol||r.host!==n.host}var n=t.url.parse(location.href);return{request:function(t){return null===t.crossOrigin&&(t.crossOrigin=e(t.url)),t}}}},function(t,e){t.exports=function(t){return{request:function(e){return e.method=e.method.toUpperCase(),e.headers=t.extend({},t.http.headers.common,e.crossOrigin?{}:t.http.headers.custom,t.http.headers[e.method.toLowerCase()],e.headers),t.isPlainObject(e.data)&&/^(GET|JSONP)$/i.test(e.method)&&(t.extend(e.params,e.data),delete e.data),e}}}},function(t,e){t.exports=function(t){return{request:function(e){return e.emulateJSON&&t.isPlainObject(e.data)&&(e.headers["Content-Type"]="application/x-www-form-urlencoded",e.data=t.url.params(e.data)),e.emulateHTTP&&!e.crossOrigin&&/^(PUT|PATCH|DELETE)$/i.test(e.method)&&(e.headers["X-HTTP-Method-Override"]=e.method,e.method="POST"),t.isObject(e.data)&&/FormData/i.test(e.data.toString())&&delete e.headers["Content-Type"],t.isPlainObject(e.data)&&(e.data=JSON.stringify(e.data)),e},response:function(t){try{t.data=JSON.parse(t.responseText)}catch(e){t.data=t.responseText}return t}}}},function(t,e,n){t.exports=function(t){return{request:function(e){return"JSONP"==e.method&&(e.client=n(13)(t)),e}}}},function(t,e,n){var r=n(4),o=n(7);t.exports=function(t){var e;return{send:function(n){var i,u,s,a="_jsonp"+Math.random().toString(36).substr(2);return n.params[n.jsonp]=a,new r(function(r){i=document.createElement("script"),i.src=t.url(n),i.type="text/javascript",i.async=!0,window[a]=function(t){s=t},e=function(t){switch("load"===t.type&&(delete window[a],document.body.removeChild(i)),"load"!==t.type||s||(t.type="error"),t.type){case"load":u=200;break;case"error":u=404;break;default:u=0}r(o(s,u))},i.onload=e,i.onerror=e,document.body.appendChild(i)})},cancel:function(){e({type:"cancel"})}}}},function(t,e){t.exports=function(t){return{request:function(e){return t.isFunction(e.beforeSend)&&e.beforeSend.call(this,e),e}}}},function(t,e){t.exports=function(t){function e(r,o,i,u){var s=this,a={};return i=t.extend({},e.actions,i),t.each(i,function(e,i){e=t.extend(!0,{url:r,params:o||{}},u,e),a[i]=function(){return(s.$http||t.http)(n(e,arguments))}}),a}function n(e,n){var r,o,i,u=t.extend({},e),s={};switch(n.length){case 4:i=n[3],o=n[2];case 3:case 2:if(!t.isFunction(n[1])){s=n[0],r=n[1],o=n[2];break}if(t.isFunction(n[0])){o=n[0],i=n[1];break}o=n[1],i=n[2];case 1:t.isFunction(n[0])?o=n[0]:/^(POST|PUT|PATCH)$/i.test(u.method)?r=n[0]:s=n[0];break;case 0:break;default:throw"Expected up to 4 arguments [params, data, success, error], got "+n.length+" arguments"}return u.data=r,u.params=t.extend({},u.params,s),o&&(u.success=o),i&&(u.error=i),u}return e.actions={get:{method:"GET"},save:{method:"POST"},query:{method:"GET"},update:{method:"PUT"},remove:{method:"DELETE"},"delete":{method:"DELETE"}},t.resource=e}}])}); \ No newline at end of file +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(16)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return e.options(t.url,this,this.$options.url)}},$http:{get:function(){return e.options(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var i in r)o&&(n.isPlainObject(r[i])||n.isArray(r[i]))?(n.isPlainObject(r[i])&&!n.isPlainObject(t[i])&&(t[i]={}),n.isArray(r[i])&&!n.isArray(t[i])&&(t[i]=[]),e(t[i],r[i],o)):void 0!==r[i]&&(t[i]=r[i])}var n=t.util.extend({},t.util),r=t.config;return n.warn=function(t){!window.console||r.silent&&!r.debug||console.warn("[VueResource warn]: "+t)},n.trim=function(t){return t.replace(/^\s*|\s*$/g,"")},n.toLower=function(t){return t?t.toLowerCase():""},n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&t.status<300,t.ok?t:r.reject(t)}),this.vm),s.success&&(c=c.success(s.success)),s.error&&(c=c.error(s.error)),c}function i(t,e){return t.success=function(n){return i(t.then(function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.error=function(n){return i(t.then(void 0,function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.always=function(n){var r=function(t){return n.call(e,t.data,t.status,t)||t};return i(t.then(r,r),e)},t}var u=n(5)(t),a=n(6)(t);return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(7)(t),n(8)(t),n(10)(t),n(11)(t),n(12)(t),n(13)(t),n(15)(t)],e.headers={put:o,post:o,patch:o,"delete":o,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){function n(t){this.state=i,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,i=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){i[n]=r,o+=1,o===t.length&&e(i)}}var o=0,i=[];0===t.length&&e(i);for(var u=0;u= 200 && response.status < 300; return response.ok ? response : Promise.reject(response); }), this.vm); @@ -88,12 +90,13 @@ module.exports = function (_) { }; Http.interceptors = [ - require('./interceptor/timeout')(_), - require('./interceptor/cors')(_), - require('./interceptor/header')(_), - require('./interceptor/mime')(_), + require('./interceptor/before')(_), require('./interceptor/jsonp')(_), - require('./interceptor/beforeSend')(_) + require('./interceptor/method')(_), + require('./interceptor/mime')(_), + require('./interceptor/header')(_), + require('./interceptor/cors')(_), + require('./interceptor/timeout')(_) ]; Http.headers = { diff --git a/src/interceptor/beforeSend.js b/src/interceptor/before.js similarity index 90% rename from src/interceptor/beforeSend.js rename to src/interceptor/before.js index db2e2eae..09fb6c82 100644 --- a/src/interceptor/beforeSend.js +++ b/src/interceptor/before.js @@ -1,5 +1,5 @@ /** - * BeforeSend Interceptor. + * Before Interceptor. */ module.exports = function (_) { diff --git a/src/interceptor/cors.js b/src/interceptor/cors.js index 173749a0..7ec3600d 100644 --- a/src/interceptor/cors.js +++ b/src/interceptor/cors.js @@ -4,6 +4,7 @@ module.exports = function (_) { + var xhrCors = 'withCredentials' in new XMLHttpRequest(); var originUrl = _.url.parse(location.href); return { @@ -14,6 +15,10 @@ module.exports = function (_) { request.crossOrigin = crossOrigin(request.url); } + if (request.crossOrigin && !xhrCors) { + request.client = require('../client/xdr')(_); + } + return request; } diff --git a/src/interceptor/factory.js b/src/interceptor/factory.js deleted file mode 100644 index 675a82f3..00000000 --- a/src/interceptor/factory.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Interceptor factory. - */ - -var Promise = require('../lib/promise'); - -module.exports = function (_) { - - return function (list) { - - var stack = { - - request: [], - - response: [], - - run: function (request, vm) { - - var chain = [].concat(this.request, [function (request) { - return request.client.send(request); - }], this.response); - - return chain.reduce(function (sequence, segment) { - return sequence.then(function (carry) { - return segment.call(vm, carry); - }); - }, Promise.resolve(request)); - - } - - }; - - list.forEach(function (interceptor) { - - if (_.isFunction(interceptor)) { - interceptor = interceptor.call(this, Promise); - } - - if (_.isPlainObject(interceptor) && interceptor.request) { - stack.request.push(interceptor.request); - } - - if (_.isPlainObject(interceptor) && interceptor.response) { - stack.response.push(interceptor.response); - } - - }); - - return stack; - }; - -}; diff --git a/src/interceptor/index.js b/src/interceptor/index.js new file mode 100644 index 00000000..8658d6af --- /dev/null +++ b/src/interceptor/index.js @@ -0,0 +1,42 @@ +/** + * Interceptor factory. + */ + +var Promise = require('../lib/promise'); + +module.exports = function (_) { + + return function (handler, vm) { + return function (client) { + return function (request) { + + if (_.isFunction(handler.request)) { + request = handler.request.call(vm, request); + } + + return when(request, function (request) { + return when(client(request), function (response) { + + if (_.isFunction(handler.response)) { + response = handler.response.call(vm, response); + } + + return response; + }); + }); + }; + }; + }; + + function when(value, fulfilled, rejected) { + + var promise = Promise.resolve(value); + + if (arguments.length < 2) { + return promise; + } + + return promise.then(fulfilled, rejected); + } + +}; diff --git a/src/interceptor/jsonp.js b/src/interceptor/jsonp.js index 44efeb5b..297f0bb5 100644 --- a/src/interceptor/jsonp.js +++ b/src/interceptor/jsonp.js @@ -9,7 +9,7 @@ module.exports = function (_) { request: function (request) { if (request.method == 'JSONP') { - request.client = require('../lib/jsonp')(_); + request.client = require('../client/jsonp')(_); } return request; diff --git a/src/interceptor/method.js b/src/interceptor/method.js new file mode 100644 index 00000000..7d7c1906 --- /dev/null +++ b/src/interceptor/method.js @@ -0,0 +1,21 @@ +/** + * HTTP method override Interceptor. + */ + +module.exports = function (_) { + + return { + + request: function (request) { + + if (request.emulateHTTP && !request.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { + request.headers['X-HTTP-Method-Override'] = request.method; + request.method = 'POST'; + } + + return request; + } + + }; + +}; diff --git a/src/interceptor/mime.js b/src/interceptor/mime.js index 66464e01..db2cb908 100644 --- a/src/interceptor/mime.js +++ b/src/interceptor/mime.js @@ -13,11 +13,6 @@ module.exports = function (_) { request.data = _.url.params(request.data); } - if (request.emulateHTTP && !request.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { - request.headers['X-HTTP-Method-Override'] = request.method; - request.method = 'POST'; - } - if (_.isObject(request.data) && /FormData/i.test(request.data.toString())) { delete request.headers['Content-Type']; } @@ -32,10 +27,8 @@ module.exports = function (_) { response: function (response) { try { - response.data = JSON.parse(response.responseText); - } catch (e) { - response.data = response.responseText; - } + response.data = JSON.parse(response.data); + } catch (e) {} return response; } diff --git a/src/lib/jsonp.js b/src/lib/jsonp.js deleted file mode 100644 index d49aae6c..00000000 --- a/src/lib/jsonp.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * JSONP request. - */ - -var Promise = require('./promise'); -var Response = require('./response'); - -module.exports = function (_) { - - var handler; - - return { - - send: function (request) { - - var callback = '_jsonp' + Math.random().toString(36).substr(2), script, status, body; - - request.params[request.jsonp] = callback; - - return new Promise(function (resolve) { - - script = document.createElement('script'); - script.src = _.url(request); - script.type = 'text/javascript'; - script.async = true; - - window[callback] = function (data) { - body = data; - }; - - handler = function (event) { - - if (event.type === 'load') { - delete window[callback]; - document.body.removeChild(script); - } - - if (event.type === 'load' && !body) { - event.type = 'error'; - } - - switch (event.type) { - case 'load': - status = 200; - break; - case 'error': - status = 404; - break; - default: - status = 0; - } - - resolve(Response(body, status)); - }; - - script.onload = handler; - script.onerror = handler; - - document.body.appendChild(script); - }); - - }, - - cancel: function () { - handler({type: 'cancel'}); - } - - }; -}; diff --git a/src/lib/response.js b/src/lib/response.js deleted file mode 100644 index 4e5690e9..00000000 --- a/src/lib/response.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Response object. - */ - -module.exports = function (body, status) { - - return { - ok: status >= 200 && status < 300, - status: status || 0, - responseText: body || '' - }; - -}; diff --git a/src/lib/util.js b/src/lib/util.js index a6a58458..72cc02ae 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -12,6 +12,14 @@ module.exports = function (Vue) { } }; + _.trim = function (str) { + return str.replace(/^\s*|\s*$/g, ''); + }; + + _.toLower = function (str) { + return str ? str.toLowerCase() : ''; + }; + _.isString = function (value) { return typeof value === 'string'; }; diff --git a/src/lib/xhr.js b/src/lib/xhr.js deleted file mode 100644 index 0872aebd..00000000 --- a/src/lib/xhr.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * XMLHttp request. - */ - -var Promise = require('./promise'); -var Response = require('./response'); - -module.exports = function (_) { - - var xhr, handler; - - return { - - send: function (request) { - - xhr = new XMLHttpRequest(); - - if (request.crossOrigin && !('withCredentials' in xhr)) { - xhr = new XDomainRequest(); - request.headers = {}; - } - - if (_.isPlainObject(request.xhr)) { - _.extend(xhr, request.xhr); - } - - return new Promise(function (resolve) { - - xhr.open(request.method, _.url(request), true); - - _.each(request.headers, function (value, header) { - xhr.setRequestHeader(header, value); - }); - - handler = function (event) { - resolve(Response(xhr.responseText, xhr.status)); - }; - - xhr.onload = handler; - xhr.onabort = handler; - xhr.onerror = handler; - - xhr.send(request.data); - }); - - }, - - cancel: function () { - xhr.abort(); - } - - }; -}; From 4b11000f559a9fa0e483edef987f77cfe3ae893a Mon Sep 17 00:00:00 2001 From: Steffan Date: Fri, 20 Nov 2015 14:46:26 +0100 Subject: [PATCH 34/61] add default client --- dist/vue-resource.js | 64 ++++++++++++++++++++++++-------------- dist/vue-resource.min.js | 2 +- src/client/default.js | 13 ++++++++ src/client/jsonp.js | 2 +- src/client/xdr.js | 2 +- src/client/xhr.js | 2 +- src/http.js | 2 +- src/interceptor/jsonp.js | 4 ++- src/interceptor/timeout.js | 2 +- 9 files changed, 63 insertions(+), 30 deletions(-) create mode 100644 src/client/default.js diff --git a/dist/vue-resource.js b/dist/vue-resource.js index cbd05e8b..a8e4c2ac 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -70,7 +70,7 @@ return /******/ (function(modules) { // webpackBootstrap Vue.url = __webpack_require__(2)(_); Vue.http = __webpack_require__(3)(_); - Vue.resource = __webpack_require__(16)(_); + Vue.resource = __webpack_require__(17)(_); Object.defineProperties(Vue.prototype, { @@ -461,13 +461,13 @@ return /******/ (function(modules) { // webpackBootstrap }; Http.interceptors = [ - __webpack_require__(7)(_), __webpack_require__(8)(_), - __webpack_require__(10)(_), + __webpack_require__(9)(_), __webpack_require__(11)(_), __webpack_require__(12)(_), __webpack_require__(13)(_), - __webpack_require__(15)(_) + __webpack_require__(14)(_), + __webpack_require__(16)(_) ]; Http.headers = { @@ -766,7 +766,26 @@ return /******/ (function(modules) { // webpackBootstrap /***/ function(module, exports, __webpack_require__) { /** - * XMLHttp request. + * Default client. + */ + + module.exports = function (_) { + + var xhrClient = __webpack_require__(7)(_); + + return function (request) { + return (request.client || xhrClient)(request); + }; + + }; + + +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * XMLHttp client. */ var Promise = __webpack_require__(4); @@ -808,7 +827,6 @@ return /******/ (function(modules) { // webpackBootstrap xhr.send(request.data); }); - }; function getHeaders(xhr) { @@ -863,7 +881,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 7 */ +/* 8 */ /***/ function(module, exports) { /** @@ -889,7 +907,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 8 */ +/* 9 */ /***/ function(module, exports, __webpack_require__) { /** @@ -898,12 +916,14 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { + var jsonpClient = __webpack_require__(10)(_); + return { request: function (request) { if (request.method == 'JSONP') { - request.client = __webpack_require__(9)(_); + request.client = jsonpClient; } return request; @@ -915,11 +935,11 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 9 */ +/* 10 */ /***/ function(module, exports, __webpack_require__) { /** - * JSONP request. + * JSONP client. */ var Promise = __webpack_require__(4); @@ -975,14 +995,13 @@ return /******/ (function(modules) { // webpackBootstrap document.body.appendChild(script); }); - }; }; /***/ }, -/* 10 */ +/* 11 */ /***/ function(module, exports) { /** @@ -1009,7 +1028,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 11 */ +/* 12 */ /***/ function(module, exports) { /** @@ -1053,7 +1072,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 12 */ +/* 13 */ /***/ function(module, exports) { /** @@ -1087,7 +1106,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 13 */ +/* 14 */ /***/ function(module, exports, __webpack_require__) { /** @@ -1108,7 +1127,7 @@ return /******/ (function(modules) { // webpackBootstrap } if (request.crossOrigin && !xhrCors) { - request.client = __webpack_require__(14)(_); + request.client = __webpack_require__(15)(_); } return request; @@ -1127,11 +1146,11 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 14 */ +/* 15 */ /***/ function(module, exports, __webpack_require__) { /** - * XDomain request (Internet Explorer). + * XDomain client (Internet Explorer). */ var Promise = __webpack_require__(4); @@ -1165,14 +1184,13 @@ return /******/ (function(modules) { // webpackBootstrap xdr.send(request.data); }); - }; }; /***/ }, -/* 15 */ +/* 16 */ /***/ function(module, exports) { /** @@ -1189,7 +1207,7 @@ return /******/ (function(modules) { // webpackBootstrap if (request.timeout) { timeout = setTimeout(function () { - request.client.cancel(); + request.cancel(); }, request.timeout); } @@ -1209,7 +1227,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 16 */ +/* 17 */ /***/ function(module, exports) { /** diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index 1c7527f4..d1e525f7 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -4,4 +4,4 @@ * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(16)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return e.options(t.url,this,this.$options.url)}},$http:{get:function(){return e.options(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var i in r)o&&(n.isPlainObject(r[i])||n.isArray(r[i]))?(n.isPlainObject(r[i])&&!n.isPlainObject(t[i])&&(t[i]={}),n.isArray(r[i])&&!n.isArray(t[i])&&(t[i]=[]),e(t[i],r[i],o)):void 0!==r[i]&&(t[i]=r[i])}var n=t.util.extend({},t.util),r=t.config;return n.warn=function(t){!window.console||r.silent&&!r.debug||console.warn("[VueResource warn]: "+t)},n.trim=function(t){return t.replace(/^\s*|\s*$/g,"")},n.toLower=function(t){return t?t.toLowerCase():""},n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&t.status<300,t.ok?t:r.reject(t)}),this.vm),s.success&&(c=c.success(s.success)),s.error&&(c=c.error(s.error)),c}function i(t,e){return t.success=function(n){return i(t.then(function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.error=function(n){return i(t.then(void 0,function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.always=function(n){var r=function(t){return n.call(e,t.data,t.status,t)||t};return i(t.then(r,r),e)},t}var u=n(5)(t),a=n(6)(t);return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(7)(t),n(8)(t),n(10)(t),n(11)(t),n(12)(t),n(13)(t),n(15)(t)],e.headers={put:o,post:o,patch:o,"delete":o,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){function n(t){this.state=i,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,i=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){i[n]=r,o+=1,o===t.length&&e(i)}}var o=0,i=[];0===t.length&&e(i);for(var u=0;u=200&&t.status<300,t.ok?t:r.reject(t)}),this.vm),s.success&&(c=c.success(s.success)),s.error&&(c=c.error(s.error)),c}function u(t,e){return t.success=function(n){return u(t.then(function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.error=function(n){return u(t.then(void 0,function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.always=function(n){var r=function(t){return n.call(e,t.data,t.status,t)||t};return u(t.then(r,r),e)},t}var i=n(5)(t),a=n(6)(t);return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(11)(t),n(12)(t),n(13)(t),n(14)(t),n(16)(t)],e.headers={put:o,post:o,patch:o,"delete":o,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,u){return t.isFunction(r)&&(u=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},u))}}),t.http=e}},function(t,e){function n(t){this.state=u,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,u=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){u[n]=r,o+=1,o===t.length&&e(u)}}var o=0,u=[];0===t.length&&e(u);for(var i=0;i Date: Fri, 20 Nov 2015 15:02:20 +0100 Subject: [PATCH 35/61] update cors interceptor --- dist/vue-resource.js | 55 +++++----------------------------------- dist/vue-resource.min.js | 2 +- src/interceptor/cors.js | 5 ++-- 3 files changed, 10 insertions(+), 52 deletions(-) diff --git a/dist/vue-resource.js b/dist/vue-resource.js index a8e4c2ac..ca984255 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -70,7 +70,7 @@ return /******/ (function(modules) { // webpackBootstrap Vue.url = __webpack_require__(2)(_); Vue.http = __webpack_require__(3)(_); - Vue.resource = __webpack_require__(17)(_); + Vue.resource = __webpack_require__(16)(_); Object.defineProperties(Vue.prototype, { @@ -467,7 +467,7 @@ return /******/ (function(modules) { // webpackBootstrap __webpack_require__(12)(_), __webpack_require__(13)(_), __webpack_require__(14)(_), - __webpack_require__(16)(_) + __webpack_require__(15)(_) ]; Http.headers = { @@ -1115,8 +1115,9 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var xhrCors = 'withCredentials' in new XMLHttpRequest(); var originUrl = _.url.parse(location.href); + var xdrClient = __webpack_require__(10)(_); + var xhrCors = 'withCredentials' in new XMLHttpRequest(); return { @@ -1127,7 +1128,7 @@ return /******/ (function(modules) { // webpackBootstrap } if (request.crossOrigin && !xhrCors) { - request.client = __webpack_require__(15)(_); + request.client = xdrClient; } return request; @@ -1147,50 +1148,6 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 15 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * XDomain client (Internet Explorer). - */ - - var Promise = __webpack_require__(4); - - module.exports = function (_) { - - return function (request) { - return new Promise(function (resolve) { - - var xdr = new XDomainRequest(), response = {}, handler; - - request.cancel = function () { - xdr.abort(); - }; - - xdr.open(request.method, _.url(request), true); - - handler = function (event) { - - response.data = xdr.responseText; - response.status = xdr.status; - response.statusText = xdr.statusText; - - resolve(response); - }; - - xdr.onload = handler; - xdr.onabort = handler; - xdr.onerror = handler; - xdr.onprogress = function () {}; - - xdr.send(request.data); - }); - }; - - }; - - -/***/ }, -/* 16 */ /***/ function(module, exports) { /** @@ -1227,7 +1184,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 17 */ +/* 16 */ /***/ function(module, exports) { /** diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index d1e525f7..a6efe982 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -4,4 +4,4 @@ * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(17)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return e.options(t.url,this,this.$options.url)}},$http:{get:function(){return e.options(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var u in r)o&&(n.isPlainObject(r[u])||n.isArray(r[u]))?(n.isPlainObject(r[u])&&!n.isPlainObject(t[u])&&(t[u]={}),n.isArray(r[u])&&!n.isArray(t[u])&&(t[u]=[]),e(t[u],r[u],o)):void 0!==r[u]&&(t[u]=r[u])}var n=t.util.extend({},t.util),r=t.config;return n.warn=function(t){!window.console||r.silent&&!r.debug||console.warn("[VueResource warn]: "+t)},n.trim=function(t){return t.replace(/^\s*|\s*$/g,"")},n.toLower=function(t){return t?t.toLowerCase():""},n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&t.status<300,t.ok?t:r.reject(t)}),this.vm),s.success&&(c=c.success(s.success)),s.error&&(c=c.error(s.error)),c}function u(t,e){return t.success=function(n){return u(t.then(function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.error=function(n){return u(t.then(void 0,function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.always=function(n){var r=function(t){return n.call(e,t.data,t.status,t)||t};return u(t.then(r,r),e)},t}var i=n(5)(t),a=n(6)(t);return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(11)(t),n(12)(t),n(13)(t),n(14)(t),n(16)(t)],e.headers={put:o,post:o,patch:o,"delete":o,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,u){return t.isFunction(r)&&(u=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},u))}}),t.http=e}},function(t,e){function n(t){this.state=u,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,u=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){u[n]=r,o+=1,o===t.length&&e(u)}}var o=0,u=[];0===t.length&&e(u);for(var i=0;i=200&&t.status<300,t.ok?t:r.reject(t)}),this.vm),s.success&&(c=c.success(s.success)),s.error&&(c=c.error(s.error)),c}function i(t,e){return t.success=function(n){return i(t.then(function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.error=function(n){return i(t.then(void 0,function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.always=function(n){var r=function(t){return n.call(e,t.data,t.status,t)||t};return i(t.then(r,r),e)},t}var u=n(5)(t),a=n(6)(t);return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(11)(t),n(12)(t),n(13)(t),n(14)(t),n(15)(t)],e.headers={put:o,post:o,patch:o,"delete":o,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){function n(t){this.state=i,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,i=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){i[n]=r,o+=1,o===t.length&&e(i)}}var o=0,i=[];0===t.length&&e(i);for(var u=0;u Date: Sat, 21 Nov 2015 10:11:38 +0100 Subject: [PATCH 36/61] add request to response object --- dist/vue-resource.js | 4 ++-- dist/vue-resource.min.js | 2 +- src/client/jsonp.js | 2 +- src/client/xdr.js | 2 +- src/client/xhr.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dist/vue-resource.js b/dist/vue-resource.js index ca984255..cdb0aadc 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -795,7 +795,7 @@ return /******/ (function(modules) { // webpackBootstrap return function (request) { return new Promise(function (resolve) { - var xhr = new XMLHttpRequest(), response = {}, handler; + var xhr = new XMLHttpRequest(), response = {request: request}, handler; request.cancel = function () { xhr.abort(); @@ -949,7 +949,7 @@ return /******/ (function(modules) { // webpackBootstrap return function (request) { return new Promise(function (resolve) { - var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {}, handler, script; + var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {request: request}, handler, script; request.params[request.jsonp] = callback; request.cancel = function () { diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index a6efe982..c9714ab4 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -4,4 +4,4 @@ * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(16)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return e.options(t.url,this,this.$options.url)}},$http:{get:function(){return e.options(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var i in r)o&&(n.isPlainObject(r[i])||n.isArray(r[i]))?(n.isPlainObject(r[i])&&!n.isPlainObject(t[i])&&(t[i]={}),n.isArray(r[i])&&!n.isArray(t[i])&&(t[i]=[]),e(t[i],r[i],o)):void 0!==r[i]&&(t[i]=r[i])}var n=t.util.extend({},t.util),r=t.config;return n.warn=function(t){!window.console||r.silent&&!r.debug||console.warn("[VueResource warn]: "+t)},n.trim=function(t){return t.replace(/^\s*|\s*$/g,"")},n.toLower=function(t){return t?t.toLowerCase():""},n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&t.status<300,t.ok?t:r.reject(t)}),this.vm),s.success&&(c=c.success(s.success)),s.error&&(c=c.error(s.error)),c}function i(t,e){return t.success=function(n){return i(t.then(function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.error=function(n){return i(t.then(void 0,function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.always=function(n){var r=function(t){return n.call(e,t.data,t.status,t)||t};return i(t.then(r,r),e)},t}var u=n(5)(t),a=n(6)(t);return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(11)(t),n(12)(t),n(13)(t),n(14)(t),n(15)(t)],e.headers={put:o,post:o,patch:o,"delete":o,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){function n(t){this.state=i,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,i=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){i[n]=r,o+=1,o===t.length&&e(i)}}var o=0,i=[];0===t.length&&e(i);for(var u=0;u=200&&t.status<300,t.ok?t:r.reject(t)}),this.vm),s.success&&(c=c.success(s.success)),s.error&&(c=c.error(s.error)),c}function i(t,e){return t.success=function(n){return i(t.then(function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.error=function(n){return i(t.then(void 0,function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.always=function(n){var r=function(t){return n.call(e,t.data,t.status,t)||t};return i(t.then(r,r),e)},t}var u=n(5)(t),a=n(6)(t);return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(11)(t),n(12)(t),n(13)(t),n(14)(t),n(15)(t)],e.headers={put:o,post:o,patch:o,"delete":o,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){function n(t){this.state=i,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,i=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){i[n]=r,o+=1,o===t.length&&e(i)}}var o=0,i=[];0===t.length&&e(i);for(var u=0;u Date: Mon, 23 Nov 2015 13:12:45 +0100 Subject: [PATCH 37/61] update cors interceptor call interceptor factory --- dist/vue-resource.js | 109 +++++++++++++++++++++---------------- dist/vue-resource.min.js | 2 +- src/http.js | 4 +- src/interceptor/cors.js | 9 ++- src/interceptor/index.js | 5 ++ src/interceptor/method.js | 2 +- src/interceptor/timeout.js | 31 ++++++----- 7 files changed, 94 insertions(+), 68 deletions(-) diff --git a/dist/vue-resource.js b/dist/vue-resource.js index cdb0aadc..c8a3f984 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -463,7 +463,7 @@ return /******/ (function(modules) { // webpackBootstrap Http.interceptors = [ __webpack_require__(8)(_), __webpack_require__(9)(_), - __webpack_require__(11)(_), + __webpack_require__(10)(_), __webpack_require__(12)(_), __webpack_require__(13)(_), __webpack_require__(14)(_), @@ -727,6 +727,11 @@ return /******/ (function(modules) { // webpackBootstrap return function (handler, vm) { return function (client) { + + if (_.isFunction(handler)) { + handler = handler.call(vm, Promise); + } + return function (request) { if (_.isFunction(handler.request)) { @@ -908,6 +913,46 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 9 */ +/***/ function(module, exports) { + + /** + * Timeout Interceptor. + */ + + module.exports = function (_) { + + return function () { + + var timeout; + + return { + + request: function (request) { + + if (request.timeout) { + timeout = setTimeout(function () { + request.cancel(); + }, request.timeout); + } + + return request; + }, + + response: function (response) { + + clearTimeout(timeout); + + return response; + } + + }; + }; + + }; + + +/***/ }, +/* 10 */ /***/ function(module, exports, __webpack_require__) { /** @@ -916,7 +961,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var jsonpClient = __webpack_require__(10)(_); + var jsonpClient = __webpack_require__(11)(_); return { @@ -935,7 +980,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 10 */ +/* 11 */ /***/ function(module, exports, __webpack_require__) { /** @@ -1001,7 +1046,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 11 */ +/* 12 */ /***/ function(module, exports) { /** @@ -1014,7 +1059,7 @@ return /******/ (function(modules) { // webpackBootstrap request: function (request) { - if (request.emulateHTTP && !request.crossOrigin && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { + if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { request.headers['X-HTTP-Method-Override'] = request.method; request.method = 'POST'; } @@ -1028,7 +1073,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 12 */ +/* 13 */ /***/ function(module, exports) { /** @@ -1072,7 +1117,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 13 */ +/* 14 */ /***/ function(module, exports) { /** @@ -1106,7 +1151,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 14 */ +/* 15 */ /***/ function(module, exports, __webpack_require__) { /** @@ -1116,7 +1161,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { var originUrl = _.url.parse(location.href); - var xdrClient = __webpack_require__(10)(_); + var xdrClient = __webpack_require__(11)(_); var xhrCors = 'withCredentials' in new XMLHttpRequest(); return { @@ -1127,8 +1172,13 @@ return /******/ (function(modules) { // webpackBootstrap request.crossOrigin = crossOrigin(request.url); } - if (request.crossOrigin && !xhrCors) { - request.client = xdrClient; + if (request.crossOrigin) { + + if (!xhrCors) { + request.client = xdrClient; + } + + request.emulateHTTP = false; } return request; @@ -1146,43 +1196,6 @@ return /******/ (function(modules) { // webpackBootstrap }; -/***/ }, -/* 15 */ -/***/ function(module, exports) { - - /** - * Timeout Interceptor. - */ - - module.exports = function (_) { - - var timeout; - - return { - - request: function (request) { - - if (request.timeout) { - timeout = setTimeout(function () { - request.cancel(); - }, request.timeout); - } - - return request; - }, - - response: function (response) { - - clearTimeout(timeout); - - return response; - } - - }; - - }; - - /***/ }, /* 16 */ /***/ function(module, exports) { diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index c9714ab4..babaf5a9 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -4,4 +4,4 @@ * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(16)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return e.options(t.url,this,this.$options.url)}},$http:{get:function(){return e.options(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var i in r)o&&(n.isPlainObject(r[i])||n.isArray(r[i]))?(n.isPlainObject(r[i])&&!n.isPlainObject(t[i])&&(t[i]={}),n.isArray(r[i])&&!n.isArray(t[i])&&(t[i]=[]),e(t[i],r[i],o)):void 0!==r[i]&&(t[i]=r[i])}var n=t.util.extend({},t.util),r=t.config;return n.warn=function(t){!window.console||r.silent&&!r.debug||console.warn("[VueResource warn]: "+t)},n.trim=function(t){return t.replace(/^\s*|\s*$/g,"")},n.toLower=function(t){return t?t.toLowerCase():""},n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&t.status<300,t.ok?t:r.reject(t)}),this.vm),s.success&&(c=c.success(s.success)),s.error&&(c=c.error(s.error)),c}function i(t,e){return t.success=function(n){return i(t.then(function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.error=function(n){return i(t.then(void 0,function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.always=function(n){var r=function(t){return n.call(e,t.data,t.status,t)||t};return i(t.then(r,r),e)},t}var u=n(5)(t),a=n(6)(t);return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(11)(t),n(12)(t),n(13)(t),n(14)(t),n(15)(t)],e.headers={put:o,post:o,patch:o,"delete":o,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){function n(t){this.state=i,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,i=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){i[n]=r,o+=1,o===t.length&&e(i)}}var o=0,i=[];0===t.length&&e(i);for(var u=0;u=200&&t.status<300,t.ok?t:r.reject(t)}),this.vm),s.success&&(c=c.success(s.success)),s.error&&(c=c.error(s.error)),c}function i(t,e){return t.success=function(n){return i(t.then(function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.error=function(n){return i(t.then(void 0,function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.always=function(n){var r=function(t){return n.call(e,t.data,t.status,t)||t};return i(t.then(r,r),e)},t}var u=n(5)(t),a=n(6)(t);return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(10)(t),n(12)(t),n(13)(t),n(14)(t),n(15)(t)],e.headers={put:o,post:o,patch:o,"delete":o,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){function n(t){this.state=i,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,i=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){i[n]=r,o+=1,o===t.length&&e(i)}}var o=0,i=[];0===t.length&&e(i);for(var u=0;u Date: Mon, 23 Nov 2015 13:42:19 +0100 Subject: [PATCH 38/61] update jsonp client --- src/client/jsonp.js | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/client/jsonp.js b/src/client/jsonp.js index 0ed9d1bc..080dbd4f 100644 --- a/src/client/jsonp.js +++ b/src/client/jsonp.js @@ -9,7 +9,7 @@ module.exports = function (_) { return function (request) { return new Promise(function (resolve) { - var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {request: request}, handler, script; + var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {request: request, data: null}, handler, script; request.params[request.jsonp] = callback; request.cancel = function () { @@ -27,27 +27,18 @@ module.exports = function (_) { handler = function (event) { - if (event.type === 'load') { - delete window[callback]; - document.body.removeChild(script); - } - - if (event.type === 'load' && !response.data) { - event.type = 'error'; - } - - switch (event.type) { - case 'load': - response.status = 200; - break; - case 'error': - response.status = 404; - break; - default: - response.status = 0; + if (event.type === 'load' && response.data !== null) { + response.status = 200; + } else if (event.type === 'error') { + response.status = 404; + } else { + response.status = 0; } resolve(response); + + delete window[callback]; + document.body.removeChild(script); }; script.onload = handler; From 41448668dd33e1842e90cf1853213d61f67c0424 Mon Sep 17 00:00:00 2001 From: Steffan Date: Sun, 13 Dec 2015 16:51:16 +0100 Subject: [PATCH 39/61] add Promise.bind to bind vm use nextTick() in Promise remove native browser Promise --- README.md | 44 +++-- bower.json | 2 +- dist/vue-resource.js | 396 ++++++++++++++++++--------------------- dist/vue-resource.min.js | 4 +- package.json | 3 +- src/client/jsonp.js | 4 +- src/client/xdr.js | 6 +- src/client/xhr.js | 4 +- src/http.js | 23 ++- src/index.js | 1 + src/interceptor/cors.js | 6 +- src/interceptor/index.js | 4 +- src/lib/promise.js | 321 +++++++++++++++---------------- test/http.js | 66 ++++++- 14 files changed, 460 insertions(+), 424 deletions(-) diff --git a/README.md b/README.md index 3f65f046..aee8ed8c 100644 --- a/README.md +++ b/README.md @@ -76,8 +76,8 @@ Interceptors can be defined globally and are used for pre- and postprocessing of ```javascript Vue.http.interceptors.push({ - request: function (options) { - return options; + request: function (request) { + return request; }, response: function (response) { @@ -94,11 +94,13 @@ If Promises are needed inside of a Interceptor, a factory function can be used. ```javascript Vue.http.interceptors.push(function (Promise) { return { - request: function (options) { + + request: function (request) { if (reject) { return Promise.reject(); } }, + response: function (response) { if (reject) { return Promise.reject(); @@ -116,14 +118,24 @@ new Vue({ ready: function() { // GET request - this.$http.get('/someUrl', function (data, status, request) { + this.$http.get('/someUrl').then(function (response) { + + // get status + response.status; + + // get all headers + response.headers(); + + // get 'expires' header + response.headers('expires'); // set data on vm - this.$set('someData', data) + this.$set('someData', response.data) + + }, function (response) { - }).error(function (data, status, request) { // handle error - }) + }); } @@ -158,23 +170,23 @@ new Vue({ var resource = this.$resource('someItem/:id'); // get item - resource.get({id: 1}, function (item, status, request) { - this.$set('item', item) - }) + resource.get({id: 1}).then(function (response) { + this.$set('item', response.item) + }); // save item - resource.save({id: 1}, {item: this.item}, function (data, status, request) { + resource.save({id: 1}, {item: this.item}).then(function (response) { // handle success - }).error(function (data, status, request) { + }, function (response) { // handle error - }) + }); // delete item - resource.delete({id: 1}, function (data, status, request) { + resource.delete({id: 1}).then(function (response) { // handle success - }).error(function (data, status, request) { + }, function (response) { // handle error - }) + }); } diff --git a/bower.json b/bower.json index a54a3d19..c5b36ed4 100644 --- a/bower.json +++ b/bower.json @@ -2,7 +2,7 @@ "name": "vue-resource", "main": "dist/vue-resource.js", "description": "A web request service for Vue.js", - "version": "0.1.16", + "version": "0.2.0", "homepage": "https://github.com/vuejs/vue-resource", "license": "MIT", "ignore": [ diff --git a/dist/vue-resource.js b/dist/vue-resource.js index c8a3f984..6a71dad7 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -1,5 +1,5 @@ /** - * vue-resource v0.1.16 + * vue-resource v0.2.0 * https://github.com/vuejs/vue-resource * Released under the MIT License. */ @@ -8,7 +8,7 @@ if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) - define(factory); + define([], factory); else if(typeof exports === 'object') exports["VueResource"] = factory(); else @@ -71,6 +71,7 @@ return /******/ (function(modules) { // webpackBootstrap Vue.url = __webpack_require__(2)(_); Vue.http = __webpack_require__(3)(_); Vue.resource = __webpack_require__(16)(_); + Vue.promise = __webpack_require__(4)(_); Object.defineProperties(Vue.prototype, { @@ -373,13 +374,12 @@ return /******/ (function(modules) { // webpackBootstrap * Service for sending network requests. */ - var Promise = __webpack_require__(4); - var jsonType = {'Content-Type': 'application/json'}; - module.exports = function (_) { + var Promise = __webpack_require__(4)(_); var interceptor = __webpack_require__(5)(_); var defaultClient = __webpack_require__(6)(_); + var jsonType = {'Content-Type': 'application/json'}; function Http(url, options) { @@ -399,12 +399,12 @@ return /******/ (function(modules) { // webpackBootstrap client = interceptor(i, this.vm)(client); }, this); - promise = extendPromise(client(request).then(function (response) { + promise = extendPromise(client(request).bind(this.vm).then(function (response) { response.ok = response.status >= 200 && response.status < 300; return response.ok ? response : Promise.reject(response); - }), this.vm); + })); if (request.success) { promise = promise.success(request.success); @@ -417,31 +417,31 @@ return /******/ (function(modules) { // webpackBootstrap return promise; } - function extendPromise(promise, vm) { + function extendPromise(promise) { promise.success = function (fn) { return extendPromise(promise.then(function (response) { - return fn.call(vm, response.data, response.status, response) || response; - }), vm); + return fn.call(this, response.data, response.status, response) || response; + })); }; promise.error = function (fn) { return extendPromise(promise.then(undefined, function (response) { - return fn.call(vm, response.data, response.status, response) || response; - }), vm); + return fn.call(this, response.data, response.status, response) || response; + })); }; promise.always = function (fn) { var cb = function (response) { - return fn.call(vm, response.data, response.status, response) || response; + return fn.call(this, response.data, response.status, response) || response; }; - return extendPromise(promise.then(cb, cb), vm); + return extendPromise(promise.then(cb, cb)); }; return promise; @@ -502,215 +502,202 @@ return /******/ (function(modules) { // webpackBootstrap /***/ function(module, exports) { /** - * Promises/A+ polyfill v1.1.0 (https://github.com/bramstein/promis) + * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) */ - var RESOLVED = 0; - var REJECTED = 1; - var PENDING = 2; + module.exports = function (_) { + + var RESOLVED = 0; + var REJECTED = 1; + var PENDING = 2; - function Promise(executor) { + function Promise(executor) { - this.state = PENDING; - this.value = undefined; - this.deferred = []; + this.state = PENDING; + this.value = undefined; + this.deferred = []; - var promise = this; + var promise = this; - try { - executor(function (x) { - promise.resolve(x); - }, function (r) { - promise.reject(r); - }); - } catch (e) { - promise.reject(e); + try { + executor(function (x) { + promise.resolve(x); + }, function (r) { + promise.reject(r); + }); + } catch (e) { + promise.reject(e); + } } - } - Promise.reject = function (r) { - return new Promise(function (resolve, reject) { - reject(r); - }); - }; + Promise.reject = function (r) { + return new Promise(function (resolve, reject) { + reject(r); + }); + }; - Promise.resolve = function (x) { - return new Promise(function (resolve, reject) { - resolve(x); - }); - }; + Promise.resolve = function (x) { + return new Promise(function (resolve, reject) { + resolve(x); + }); + }; - Promise.all = function all(iterable) { - return new Promise(function (resolve, reject) { - var count = 0, - result = []; + Promise.all = function all(iterable) { + return new Promise(function (resolve, reject) { + var count = 0, result = []; - if (iterable.length === 0) { - resolve(result); - } + if (iterable.length === 0) { + resolve(result); + } - function resolver(i) { - return function (x) { - result[i] = x; - count += 1; + function resolver(i) { + return function (x) { + result[i] = x; + count += 1; - if (count === iterable.length) { - resolve(result); - } - }; - } + if (count === iterable.length) { + resolve(result); + } + }; + } - for (var i = 0; i < iterable.length; i += 1) { - iterable[i].then(resolver(i), reject); - } - }); - }; + for (var i = 0; i < iterable.length; i += 1) { + Promise.resolve(iterable[i]).then(resolver(i), reject); + } + }); + }; - Promise.race = function race(iterable) { - return new Promise(function (resolve, reject) { - for (var i = 0; i < iterable.length; i += 1) { - iterable[i].then(resolve, reject); - } - }); - }; + Promise.race = function race(iterable) { + return new Promise(function (resolve, reject) { + for (var i = 0; i < iterable.length; i += 1) { + Promise.resolve(iterable[i]).then(resolve, reject); + } + }); + }; - var p = Promise.prototype; + var p = Promise.prototype; - p.resolve = function resolve(x) { - var promise = this; + p.resolve = function resolve(x) { + var promise = this; - if (promise.state === PENDING) { - if (x === promise) { - throw new TypeError('Promise settled with itself.'); - } + if (promise.state === PENDING) { + if (x === promise) { + throw new TypeError('Promise settled with itself.'); + } - var called = false; + var called = false; - try { - var then = x && x['then']; + try { + var then = x && x['then']; - if (x !== null && typeof x === 'object' && typeof then === 'function') { - then.call(x, function (x) { - if (!called) { - promise.resolve(x); - } - called = true; + if (x !== null && typeof x === 'object' && typeof then === 'function') { + then.call(x, function (x) { + if (!called) { + promise.resolve(x); + } + called = true; - }, function (r) { - if (!called) { - promise.reject(r); - } - called = true; - }); + }, function (r) { + if (!called) { + promise.reject(r); + } + called = true; + }); + return; + } + } catch (e) { + if (!called) { + promise.reject(e); + } return; } - } catch (e) { - if (!called) { - promise.reject(e); - } - return; + + promise.state = RESOLVED; + promise.value = x; + promise.notify(); } - promise.state = RESOLVED; - promise.value = x; - promise.notify(); - } - }; + }; - p.reject = function reject(reason) { - var promise = this; + p.reject = function reject(reason) { + var promise = this; - if (promise.state === PENDING) { - if (reason === promise) { - throw new TypeError('Promise settled with itself.'); - } + if (promise.state === PENDING) { + if (reason === promise) { + throw new TypeError('Promise settled with itself.'); + } - promise.state = REJECTED; - promise.value = reason; - promise.notify(); - } - }; + promise.state = REJECTED; + promise.value = reason; + promise.notify(); + } + }; - p.notify = function notify() { - var promise = this; - - async(function () { - if (promise.state !== PENDING) { - while (promise.deferred.length) { - var deferred = promise.deferred.shift(), - onResolved = deferred[0], - onRejected = deferred[1], - resolve = deferred[2], - reject = deferred[3]; - - try { - if (promise.state === RESOLVED) { - if (typeof onResolved === 'function') { - resolve(onResolved.call(undefined, promise.value)); - } else { - resolve(promise.value); - } - } else if (promise.state === REJECTED) { - if (typeof onRejected === 'function') { - resolve(onRejected.call(undefined, promise.value)); - } else { - reject(promise.value); + p.notify = function notify() { + var promise = this; + + _.nextTick(function () { + if (promise.state !== PENDING) { + while (promise.deferred.length) { + var deferred = promise.deferred.shift(), + onResolved = deferred[0], + onRejected = deferred[1], + resolve = deferred[2], + reject = deferred[3]; + + try { + if (promise.state === RESOLVED) { + if (typeof onResolved === 'function') { + resolve(onResolved.call(undefined, promise.value)); + } else { + resolve(promise.value); + } + } else if (promise.state === REJECTED) { + if (typeof onRejected === 'function') { + resolve(onRejected.call(undefined, promise.value)); + } else { + reject(promise.value); + } } + } catch (e) { + reject(e); } - } catch (e) { - reject(e); } } - } - }); - }; - - p.catch = function (onRejected) { - return this.then(undefined, onRejected); - }; - - p.then = function then(onResolved, onRejected) { - var promise = this; - - return new Promise(function (resolve, reject) { - promise.deferred.push([onResolved, onRejected, resolve, reject]); - promise.notify(); - }); - }; + }); + }; - var queue = []; - var async = function (callback) { - queue.push(callback); + p.bind = function (context) { + this.context = context; + return this; + }; - if (queue.length === 1) { - async.async(); - } - }; + p.catch = function (onRejected) { + return this.then(undefined, onRejected); + }; - async.run = function () { - while (queue.length) { - queue[0](); - queue.shift(); - } - }; + p.then = function then(onResolved, onRejected) { + var promise = this; - if (window.MutationObserver) { - var el = document.createElement('div'); - var mo = new MutationObserver(async.run); + if (onResolved && this.context) { + onResolved = onResolved.bind(this.context); + } - mo.observe(el, { - attributes: true - }); + if (onRejected && this.context) { + onRejected = onRejected.bind(this.context); + } - async.async = function () { - el.setAttribute("x", 0); + return new Promise(function (resolve, reject) { + promise.deferred.push([onResolved, onRejected, resolve, reject]); + promise.notify(); + }).bind(this.context); }; - } else { - async.async = function () { - setTimeout(async.run); + + _.promise = function (executor) { + return new Promise(executor); }; - } - module.exports = window.Promise || Promise; + return Promise; + }; /***/ }, @@ -721,10 +708,10 @@ return /******/ (function(modules) { // webpackBootstrap * Interceptor factory. */ - var Promise = __webpack_require__(4); - module.exports = function (_) { + var Promise = __webpack_require__(4)(_); + return function (handler, vm) { return function (client) { @@ -793,10 +780,10 @@ return /******/ (function(modules) { // webpackBootstrap * XMLHttp client. */ - var Promise = __webpack_require__(4); - module.exports = function (_) { + var Promise = __webpack_require__(4)(_); + return function (request) { return new Promise(function (resolve) { @@ -987,14 +974,14 @@ return /******/ (function(modules) { // webpackBootstrap * JSONP client. */ - var Promise = __webpack_require__(4); - module.exports = function (_) { + var Promise = __webpack_require__(4)(_); + return function (request) { return new Promise(function (resolve) { - var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {request: request}, handler, script; + var callback = '_jsonp' + Math.random().toString(36).substr(2), response = {request: request, data: null}, handler, script; request.params[request.jsonp] = callback; request.cancel = function () { @@ -1012,27 +999,18 @@ return /******/ (function(modules) { // webpackBootstrap handler = function (event) { - if (event.type === 'load') { - delete window[callback]; - document.body.removeChild(script); - } - - if (event.type === 'load' && !response.data) { - event.type = 'error'; - } - - switch (event.type) { - case 'load': - response.status = 200; - break; - case 'error': - response.status = 404; - break; - default: - response.status = 0; + if (event.type === 'load' && response.data !== null) { + response.status = 200; + } else if (event.type === 'error') { + response.status = 404; + } else { + response.status = 0; } resolve(response); + + delete window[callback]; + document.body.removeChild(script); }; script.onload = handler; @@ -1169,7 +1147,7 @@ return /******/ (function(modules) { // webpackBootstrap request: function (request) { if (request.crossOrigin === null) { - request.crossOrigin = crossOrigin(request.url); + request.crossOrigin = crossOrigin(request); } if (request.crossOrigin) { @@ -1186,9 +1164,9 @@ return /******/ (function(modules) { // webpackBootstrap }; - function crossOrigin(url) { + function crossOrigin(request) { - var requestUrl = _.url.parse(url); + var requestUrl = _.url.parse(_.url(request)); return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); } diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index babaf5a9..571e4fb1 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -1,7 +1,7 @@ /** - * vue-resource v0.1.16 + * vue-resource v0.2.0 * https://github.com/vuejs/vue-resource * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(16)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return e.options(t.url,this,this.$options.url)}},$http:{get:function(){return e.options(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var i in r)o&&(n.isPlainObject(r[i])||n.isArray(r[i]))?(n.isPlainObject(r[i])&&!n.isPlainObject(t[i])&&(t[i]={}),n.isArray(r[i])&&!n.isArray(t[i])&&(t[i]=[]),e(t[i],r[i],o)):void 0!==r[i]&&(t[i]=r[i])}var n=t.util.extend({},t.util),r=t.config;return n.warn=function(t){!window.console||r.silent&&!r.debug||console.warn("[VueResource warn]: "+t)},n.trim=function(t){return t.replace(/^\s*|\s*$/g,"")},n.toLower=function(t){return t?t.toLowerCase():""},n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&t.status<300,t.ok?t:r.reject(t)}),this.vm),s.success&&(c=c.success(s.success)),s.error&&(c=c.error(s.error)),c}function i(t,e){return t.success=function(n){return i(t.then(function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.error=function(n){return i(t.then(void 0,function(t){return n.call(e,t.data,t.status,t)||t}),e)},t.always=function(n){var r=function(t){return n.call(e,t.data,t.status,t)||t};return i(t.then(r,r),e)},t}var u=n(5)(t),a=n(6)(t);return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(10)(t),n(12)(t),n(13)(t),n(14)(t),n(15)(t)],e.headers={put:o,post:o,patch:o,"delete":o,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){function n(t){this.state=i,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var r=0,o=1,i=2;n.reject=function(t){return new n(function(e,n){n(t)})},n.resolve=function(t){return new n(function(e,n){e(t)})},n.all=function(t){return new n(function(e,n){function r(n){return function(r){i[n]=r,o+=1,o===t.length&&e(i)}}var o=0,i=[];0===t.length&&e(i);for(var u=0;u=200&&t.status<300,t.ok?t:o.reject(t)})),c.success&&(a=a.success(c.success)),c.error&&(a=a.error(c.error)),a}function r(t){return t.success=function(e){return r(t.then(function(t){return e.call(this,t.data,t.status,t)||t}))},t.error=function(e){return r(t.then(void 0,function(t){return e.call(this,t.data,t.status,t)||t}))},t.always=function(e){var n=function(t){return e.call(this,t.data,t.status,t)||t};return r(t.then(n,n))},t}var o=n(4)(t),i=n(5)(t),u=n(6)(t),s={"Content-Type":"application/json"};return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(10)(t),n(12)(t),n(13)(t),n(14)(t),n(15)(t)],e.headers={put:s,post:s,patch:s,"delete":s,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){t.exports=function(t){function e(t){this.state=o,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var n=0,r=1,o=2;e.reject=function(t){return new e(function(e,n){n(t)})},e.resolve=function(t){return new e(function(e,n){e(t)})},e.all=function(t){return new e(function(n,r){function o(e){return function(r){u[e]=r,i+=1,i===t.length&&n(u)}}var i=0,u=[];0===t.length&&n(u);for(var s=0;s= 200 && response.status < 300; return response.ok ? response : Promise.reject(response); - }), this.vm); + })); if (request.success) { promise = promise.success(request.success); @@ -46,31 +45,31 @@ module.exports = function (_) { return promise; } - function extendPromise(promise, vm) { + function extendPromise(promise) { promise.success = function (fn) { return extendPromise(promise.then(function (response) { - return fn.call(vm, response.data, response.status, response) || response; - }), vm); + return fn.call(this, response.data, response.status, response) || response; + })); }; promise.error = function (fn) { return extendPromise(promise.then(undefined, function (response) { - return fn.call(vm, response.data, response.status, response) || response; - }), vm); + return fn.call(this, response.data, response.status, response) || response; + })); }; promise.always = function (fn) { var cb = function (response) { - return fn.call(vm, response.data, response.status, response) || response; + return fn.call(this, response.data, response.status, response) || response; }; - return extendPromise(promise.then(cb, cb), vm); + return extendPromise(promise.then(cb, cb)); }; return promise; diff --git a/src/index.js b/src/index.js index d39d504a..f55e8957 100644 --- a/src/index.js +++ b/src/index.js @@ -9,6 +9,7 @@ function install(Vue) { Vue.url = require('./url')(_); Vue.http = require('./http')(_); Vue.resource = require('./resource')(_); + Vue.promise = require('./lib/promise')(_); Object.defineProperties(Vue.prototype, { diff --git a/src/interceptor/cors.js b/src/interceptor/cors.js index c6498d82..b0000541 100644 --- a/src/interceptor/cors.js +++ b/src/interceptor/cors.js @@ -13,7 +13,7 @@ module.exports = function (_) { request: function (request) { if (request.crossOrigin === null) { - request.crossOrigin = crossOrigin(request.url); + request.crossOrigin = crossOrigin(request); } if (request.crossOrigin) { @@ -30,9 +30,9 @@ module.exports = function (_) { }; - function crossOrigin(url) { + function crossOrigin(request) { - var requestUrl = _.url.parse(url); + var requestUrl = _.url.parse(_.url(request)); return (requestUrl.protocol !== originUrl.protocol || requestUrl.host !== originUrl.host); } diff --git a/src/interceptor/index.js b/src/interceptor/index.js index aee06c8e..65d2a9ac 100644 --- a/src/interceptor/index.js +++ b/src/interceptor/index.js @@ -2,10 +2,10 @@ * Interceptor factory. */ -var Promise = require('../lib/promise'); - module.exports = function (_) { + var Promise = require('../lib/promise')(_); + return function (handler, vm) { return function (client) { diff --git a/src/lib/promise.js b/src/lib/promise.js index 0c65f928..aedffecb 100644 --- a/src/lib/promise.js +++ b/src/lib/promise.js @@ -1,210 +1,197 @@ /** - * Promises/A+ polyfill v1.1.0 (https://github.com/bramstein/promis) + * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) */ -var RESOLVED = 0; -var REJECTED = 1; -var PENDING = 2; +module.exports = function (_) { -function Promise(executor) { + var RESOLVED = 0; + var REJECTED = 1; + var PENDING = 2; - this.state = PENDING; - this.value = undefined; - this.deferred = []; + function Promise(executor) { - var promise = this; + this.state = PENDING; + this.value = undefined; + this.deferred = []; - try { - executor(function (x) { - promise.resolve(x); - }, function (r) { - promise.reject(r); - }); - } catch (e) { - promise.reject(e); + var promise = this; + + try { + executor(function (x) { + promise.resolve(x); + }, function (r) { + promise.reject(r); + }); + } catch (e) { + promise.reject(e); + } } -} -Promise.reject = function (r) { - return new Promise(function (resolve, reject) { - reject(r); - }); -}; + Promise.reject = function (r) { + return new Promise(function (resolve, reject) { + reject(r); + }); + }; -Promise.resolve = function (x) { - return new Promise(function (resolve, reject) { - resolve(x); - }); -}; + Promise.resolve = function (x) { + return new Promise(function (resolve, reject) { + resolve(x); + }); + }; -Promise.all = function all(iterable) { - return new Promise(function (resolve, reject) { - var count = 0, - result = []; + Promise.all = function all(iterable) { + return new Promise(function (resolve, reject) { + var count = 0, result = []; - if (iterable.length === 0) { - resolve(result); - } + if (iterable.length === 0) { + resolve(result); + } - function resolver(i) { - return function (x) { - result[i] = x; - count += 1; + function resolver(i) { + return function (x) { + result[i] = x; + count += 1; - if (count === iterable.length) { - resolve(result); - } - }; - } + if (count === iterable.length) { + resolve(result); + } + }; + } - for (var i = 0; i < iterable.length; i += 1) { - iterable[i].then(resolver(i), reject); - } - }); -}; + for (var i = 0; i < iterable.length; i += 1) { + Promise.resolve(iterable[i]).then(resolver(i), reject); + } + }); + }; -Promise.race = function race(iterable) { - return new Promise(function (resolve, reject) { - for (var i = 0; i < iterable.length; i += 1) { - iterable[i].then(resolve, reject); - } - }); -}; + Promise.race = function race(iterable) { + return new Promise(function (resolve, reject) { + for (var i = 0; i < iterable.length; i += 1) { + Promise.resolve(iterable[i]).then(resolve, reject); + } + }); + }; -var p = Promise.prototype; + var p = Promise.prototype; -p.resolve = function resolve(x) { - var promise = this; + p.resolve = function resolve(x) { + var promise = this; - if (promise.state === PENDING) { - if (x === promise) { - throw new TypeError('Promise settled with itself.'); - } + if (promise.state === PENDING) { + if (x === promise) { + throw new TypeError('Promise settled with itself.'); + } - var called = false; + var called = false; - try { - var then = x && x['then']; + try { + var then = x && x['then']; - if (x !== null && typeof x === 'object' && typeof then === 'function') { - then.call(x, function (x) { - if (!called) { - promise.resolve(x); - } - called = true; + if (x !== null && typeof x === 'object' && typeof then === 'function') { + then.call(x, function (x) { + if (!called) { + promise.resolve(x); + } + called = true; - }, function (r) { - if (!called) { - promise.reject(r); - } - called = true; - }); + }, function (r) { + if (!called) { + promise.reject(r); + } + called = true; + }); + return; + } + } catch (e) { + if (!called) { + promise.reject(e); + } return; } - } catch (e) { - if (!called) { - promise.reject(e); - } - return; + + promise.state = RESOLVED; + promise.value = x; + promise.notify(); } - promise.state = RESOLVED; - promise.value = x; - promise.notify(); - } -}; + }; -p.reject = function reject(reason) { - var promise = this; + p.reject = function reject(reason) { + var promise = this; - if (promise.state === PENDING) { - if (reason === promise) { - throw new TypeError('Promise settled with itself.'); - } + if (promise.state === PENDING) { + if (reason === promise) { + throw new TypeError('Promise settled with itself.'); + } - promise.state = REJECTED; - promise.value = reason; - promise.notify(); - } -}; + promise.state = REJECTED; + promise.value = reason; + promise.notify(); + } + }; -p.notify = function notify() { - var promise = this; - - async(function () { - if (promise.state !== PENDING) { - while (promise.deferred.length) { - var deferred = promise.deferred.shift(), - onResolved = deferred[0], - onRejected = deferred[1], - resolve = deferred[2], - reject = deferred[3]; - - try { - if (promise.state === RESOLVED) { - if (typeof onResolved === 'function') { - resolve(onResolved.call(undefined, promise.value)); - } else { - resolve(promise.value); - } - } else if (promise.state === REJECTED) { - if (typeof onRejected === 'function') { - resolve(onRejected.call(undefined, promise.value)); - } else { - reject(promise.value); + p.notify = function notify() { + var promise = this; + + _.nextTick(function () { + if (promise.state !== PENDING) { + while (promise.deferred.length) { + var deferred = promise.deferred.shift(), + onResolved = deferred[0], + onRejected = deferred[1], + resolve = deferred[2], + reject = deferred[3]; + + try { + if (promise.state === RESOLVED) { + if (typeof onResolved === 'function') { + resolve(onResolved.call(undefined, promise.value)); + } else { + resolve(promise.value); + } + } else if (promise.state === REJECTED) { + if (typeof onRejected === 'function') { + resolve(onRejected.call(undefined, promise.value)); + } else { + reject(promise.value); + } } + } catch (e) { + reject(e); } - } catch (e) { - reject(e); } } - } - }); -}; - -p.catch = function (onRejected) { - return this.then(undefined, onRejected); -}; - -p.then = function then(onResolved, onRejected) { - var promise = this; - - return new Promise(function (resolve, reject) { - promise.deferred.push([onResolved, onRejected, resolve, reject]); - promise.notify(); - }); -}; + }); + }; -var queue = []; -var async = function (callback) { - queue.push(callback); + p.bind = function (context) { + this.context = context; + return this; + }; - if (queue.length === 1) { - async.async(); - } -}; + p.catch = function (onRejected) { + return this.then(undefined, onRejected); + }; -async.run = function () { - while (queue.length) { - queue[0](); - queue.shift(); - } -}; + p.then = function then(onResolved, onRejected) { + var promise = this; -if (window.MutationObserver) { - var el = document.createElement('div'); - var mo = new MutationObserver(async.run); + if (onResolved && this.context) { + onResolved = onResolved.bind(this.context); + } - mo.observe(el, { - attributes: true - }); + if (onRejected && this.context) { + onRejected = onRejected.bind(this.context); + } - async.async = function () { - el.setAttribute("x", 0); + return new Promise(function (resolve, reject) { + promise.deferred.push([onResolved, onRejected, resolve, reject]); + promise.notify(); + }).bind(this.context); }; -} else { - async.async = function () { - setTimeout(async.run); + + _.promise = function (executor) { + return new Promise(executor); }; -} -module.exports = window.Promise || Promise; + return Promise; +}; diff --git a/test/http.js b/test/http.js index 4c394179..bde5ac8c 100644 --- a/test/http.js +++ b/test/http.js @@ -1,11 +1,15 @@ var Vue = require('vue'); -describe('Http', function () { +describe('Vue.http', function () { it('get: test.json', function (done) { - Vue.http.get('data/test.json', function (data) { - expect(data.foo).toBe('bar'); + Vue.http.get('data/test.json').then(function (res) { + + expect(res.ok).toBe(true); + expect(res.status).toBe(200); + expect(res.data.foo).toBe('bar'); + done(); }); @@ -13,11 +17,63 @@ describe('Http', function () { it('get: cors-api.com', function (done) { - Vue.http.get('http://server.cors-api.appspot.com/server?id=1&enable=true', function (data) { - expect(data.shift().requestType).toBe('cors'); + Vue.http.get('http://server.cors-api.appspot.com/server?id=1&enable=true').then(function (res) { + + expect(res.ok).toBe(true); + expect(res.status).toBe(200); + expect(res.data.shift().requestType).toBe('cors'); + expect(res.headers('content-type')).toBe('application/json'); + done(); }); }); }); + +describe('this.$http', function () { + + it('get: test.json', function (done) { + + var vm = new Vue({ + + created: function () { + + this.$http.get('data/test.json').then(function (res) { + + expect(this).toBe(vm); + expect(res.ok).toBe(true); + expect(res.status).toBe(200); + expect(res.data.foo).toBe('bar'); + + done(); + }); + + } + + }); + + }); + + it('get: notfound.json using catch()', function (done) { + + var vm = new Vue({ + + created: function () { + + this.$http.get('data/notfound.json').catch(function (res) { + + expect(this).toBe(vm); + expect(res.ok).toBe(false); + expect(res.status).toBe(404); + + done(); + }); + + } + + }); + + }); + +}); \ No newline at end of file From 0d01a5341d5a5f947bfdbc6ff10dfdd5d2423737 Mon Sep 17 00:00:00 2001 From: Steffan Date: Sun, 13 Dec 2015 18:53:52 +0100 Subject: [PATCH 40/61] add Promise.finally method add deprecation warnings for success, error, always --- README.md | 2 -- src/http.js | 6 ++++++ src/lib/promise.js | 30 +++++++++++++++++++++--------- test/http.js | 1 + 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index aee8ed8c..3b8a28c9 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,6 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt * **method** - `string` - HTTP method (e.g. GET, POST, ...) * **params** - `Object` - Parameters object to be appended as GET parameters * **headers** - `Object` - Headers object to be sent as HTTP request headers -* **success** - `function(data, status, request)` - Callback function to be called when the request finishes -* **error** - `function(data, status, request)` - Callback function to be called when the request fails * **beforeSend** - `function(request, options)` - Callback function to modify the request object before it is sent * **emulateHTTP** - `boolean` - Send PUT, PATCH and DELETE requests with a HTTP POST and set the `X-HTTP-Method-Override` header * **emulateJSON** - `boolean` - Send request data as `application/x-www-form-urlencoded` content type diff --git a/src/http.js b/src/http.js index 8da5a76e..2df73bb9 100644 --- a/src/http.js +++ b/src/http.js @@ -49,6 +49,8 @@ module.exports = function (_) { promise.success = function (fn) { + _.warn('The `success` method has been deprecated. Use the `then` method instead.'); + return extendPromise(promise.then(function (response) { return fn.call(this, response.data, response.status, response) || response; })); @@ -57,6 +59,8 @@ module.exports = function (_) { promise.error = function (fn) { + _.warn('The `error` method has been deprecated. Use the `catch` method instead.'); + return extendPromise(promise.then(undefined, function (response) { return fn.call(this, response.data, response.status, response) || response; })); @@ -65,6 +69,8 @@ module.exports = function (_) { promise.always = function (fn) { + _.warn('The `always` method has been deprecated. Use the `finally` method instead.'); + var cb = function (response) { return fn.call(this, response.data, response.status, response) || response; }; diff --git a/src/lib/promise.js b/src/lib/promise.js index aedffecb..fe429629 100644 --- a/src/lib/promise.js +++ b/src/lib/promise.js @@ -163,15 +163,6 @@ module.exports = function (_) { }); }; - p.bind = function (context) { - this.context = context; - return this; - }; - - p.catch = function (onRejected) { - return this.then(undefined, onRejected); - }; - p.then = function then(onResolved, onRejected) { var promise = this; @@ -189,6 +180,27 @@ module.exports = function (_) { }).bind(this.context); }; + p.catch = function (onRejected) { + return this.then(undefined, onRejected); + }; + + p.finally = function (callback) { + return this.then(function (value) { + return Promise.resolve(callback.call(this, value)).bind(this).then(function () { + return value; + }); + }, function (reason) { + return Promise.resolve(callback.call(this, reason)).bind(this).then(function () { + return Promise.reject(reason); + }); + }); + }; + + p.bind = function (context) { + this.context = context; + return this; + }; + _.promise = function (executor) { return new Promise(executor); }; diff --git a/test/http.js b/test/http.js index bde5ac8c..85ecae8e 100644 --- a/test/http.js +++ b/test/http.js @@ -47,6 +47,7 @@ describe('this.$http', function () { expect(res.data.foo).toBe('bar'); done(); + }); } From de1102d3b8fa8d5627191da07c905be5a435c8c1 Mon Sep 17 00:00:00 2001 From: Steffan Date: Sun, 13 Dec 2015 18:59:09 +0100 Subject: [PATCH 41/61] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b8a28c9..7c118a60 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt * **emulateJSON** - `boolean` - Send request data as `application/x-www-form-urlencoded` content type * **xhr** - `Object` - Parameters object to be set on the native XHR object * **jsonp** - `string` - Callback function name in a JSONP request -* **timeout** - `unsigned long` - Request timeout in milliseconds (`0` means no timeout) +* **timeout** - `number` - Request timeout in milliseconds (`0` means no timeout) ### Interceptors From e9fbaba3df4c4e2af18d9a4db1ed6130663003d3 Mon Sep 17 00:00:00 2001 From: Steffan Date: Sun, 13 Dec 2015 19:03:04 +0100 Subject: [PATCH 42/61] update readme --- README.md | 83 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 7c118a60..e66f5395 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,8 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt ### Options * **url** - `string` - URL to which the request is sent -* **data** - `Object|string` - Data to be sent as the request message data * **method** - `string` - HTTP method (e.g. GET, POST, ...) +* **data** - `Object|string` - Data to be sent as the request message data * **params** - `Object` - Parameters object to be appended as GET parameters * **headers** - `Object` - Headers object to be sent as HTTP request headers * **beforeSend** - `function(request, options)` - Callback function to modify the request object before it is sent @@ -67,46 +67,6 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt * **jsonp** - `string` - Callback function name in a JSONP request * **timeout** - `number` - Request timeout in milliseconds (`0` means no timeout) -### Interceptors - -Interceptors can be defined globally and are used for pre- and postprocessing of a request. - -```javascript -Vue.http.interceptors.push({ - - request: function (request) { - return request; - }, - - response: function (response) { - return response; - } - -}); -``` - -#### Interceptor Factory - -If Promises are needed inside of a Interceptor, a factory function can be used. - -```javascript -Vue.http.interceptors.push(function (Promise) { - return { - - request: function (request) { - if (reject) { - return Promise.reject(); - } - }, - - response: function (response) { - if (reject) { - return Promise.reject(); - } - } - }; -}); -``` ### Example @@ -190,3 +150,44 @@ new Vue({ }) ``` + +## Interceptors + +Interceptors can be defined globally and are used for pre- and postprocessing of a request. + +```javascript +Vue.http.interceptors.push({ + + request: function (request) { + return request; + }, + + response: function (response) { + return response; + } + +}); +``` + +#### Interceptor Factory + +If Promises are needed inside of a Interceptor, a factory function can be used. + +```javascript +Vue.http.interceptors.push(function (Promise) { + return { + + request: function (request) { + if (reject) { + return Promise.reject(); + } + }, + + response: function (response) { + if (reject) { + return Promise.reject(); + } + } + }; +}); +``` From 769e878a5a64d0cfb745c82d6747f35a225c72b5 Mon Sep 17 00:00:00 2001 From: Steffan Date: Sun, 13 Dec 2015 19:06:17 +0100 Subject: [PATCH 43/61] update dist --- dist/vue-resource.js | 36 +++++++++++++++++++++++++++--------- dist/vue-resource.min.js | 2 +- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/dist/vue-resource.js b/dist/vue-resource.js index 6a71dad7..da54da20 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -421,6 +421,8 @@ return /******/ (function(modules) { // webpackBootstrap promise.success = function (fn) { + _.warn('The `success` method has been deprecated. Use the `then` method instead.'); + return extendPromise(promise.then(function (response) { return fn.call(this, response.data, response.status, response) || response; })); @@ -429,6 +431,8 @@ return /******/ (function(modules) { // webpackBootstrap promise.error = function (fn) { + _.warn('The `error` method has been deprecated. Use the `catch` method instead.'); + return extendPromise(promise.then(undefined, function (response) { return fn.call(this, response.data, response.status, response) || response; })); @@ -437,6 +441,8 @@ return /******/ (function(modules) { // webpackBootstrap promise.always = function (fn) { + _.warn('The `always` method has been deprecated. Use the `finally` method instead.'); + var cb = function (response) { return fn.call(this, response.data, response.status, response) || response; }; @@ -666,15 +672,6 @@ return /******/ (function(modules) { // webpackBootstrap }); }; - p.bind = function (context) { - this.context = context; - return this; - }; - - p.catch = function (onRejected) { - return this.then(undefined, onRejected); - }; - p.then = function then(onResolved, onRejected) { var promise = this; @@ -692,6 +689,27 @@ return /******/ (function(modules) { // webpackBootstrap }).bind(this.context); }; + p.catch = function (onRejected) { + return this.then(undefined, onRejected); + }; + + p.finally = function (callback) { + return this.then(function (value) { + return Promise.resolve(callback.call(this, value)).bind(this).then(function () { + return value; + }); + }, function (reason) { + return Promise.resolve(callback.call(this, reason)).bind(this).then(function () { + return Promise.reject(reason); + }); + }); + }; + + p.bind = function (context) { + this.context = context; + return this; + }; + _.promise = function (executor) { return new Promise(executor); }; diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index 571e4fb1..79c11350 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -4,4 +4,4 @@ * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(16)(e),t.promise=n(4)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return e.options(t.url,this,this.$options.url)}},$http:{get:function(){return e.options(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var i in r)o&&(n.isPlainObject(r[i])||n.isArray(r[i]))?(n.isPlainObject(r[i])&&!n.isPlainObject(t[i])&&(t[i]={}),n.isArray(r[i])&&!n.isArray(t[i])&&(t[i]=[]),e(t[i],r[i],o)):void 0!==r[i]&&(t[i]=r[i])}var n=t.util.extend({},t.util),r=t.config;return n.warn=function(t){!window.console||r.silent&&!r.debug||console.warn("[VueResource warn]: "+t)},n.trim=function(t){return t.replace(/^\s*|\s*$/g,"")},n.toLower=function(t){return t?t.toLowerCase():""},n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&t.status<300,t.ok?t:o.reject(t)})),c.success&&(a=a.success(c.success)),c.error&&(a=a.error(c.error)),a}function r(t){return t.success=function(e){return r(t.then(function(t){return e.call(this,t.data,t.status,t)||t}))},t.error=function(e){return r(t.then(void 0,function(t){return e.call(this,t.data,t.status,t)||t}))},t.always=function(e){var n=function(t){return e.call(this,t.data,t.status,t)||t};return r(t.then(n,n))},t}var o=n(4)(t),i=n(5)(t),u=n(6)(t),s={"Content-Type":"application/json"};return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(10)(t),n(12)(t),n(13)(t),n(14)(t),n(15)(t)],e.headers={put:s,post:s,patch:s,"delete":s,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){t.exports=function(t){function e(t){this.state=o,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var n=0,r=1,o=2;e.reject=function(t){return new e(function(e,n){n(t)})},e.resolve=function(t){return new e(function(e,n){e(t)})},e.all=function(t){return new e(function(n,r){function o(e){return function(r){u[e]=r,i+=1,i===t.length&&n(u)}}var i=0,u=[];0===t.length&&n(u);for(var s=0;s=200&&t.status<300,t.ok?t:o.reject(t)})),a.success&&(c=c.success(a.success)),a.error&&(c=c.error(a.error)),c}function r(e){return e.success=function(n){return t.warn("The `success` method has been deprecated. Use the `then` method instead."),r(e.then(function(t){return n.call(this,t.data,t.status,t)||t}))},e.error=function(n){return t.warn("The `error` method has been deprecated. Use the `catch` method instead."),r(e.then(void 0,function(t){return n.call(this,t.data,t.status,t)||t}))},e.always=function(n){t.warn("The `always` method has been deprecated. Use the `finally` method instead.");var o=function(t){return n.call(this,t.data,t.status,t)||t};return r(e.then(o,o))},e}var o=n(4)(t),i=n(5)(t),u=n(6)(t),s={"Content-Type":"application/json"};return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(10)(t),n(12)(t),n(13)(t),n(14)(t),n(15)(t)],e.headers={put:s,post:s,patch:s,"delete":s,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){t.exports=function(t){function e(t){this.state=o,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var n=0,r=1,o=2;e.reject=function(t){return new e(function(e,n){n(t)})},e.resolve=function(t){return new e(function(e,n){e(t)})},e.all=function(t){return new e(function(n,r){function o(e){return function(r){u[e]=r,i+=1,i===t.length&&n(u)}}var i=0,u=[];0===t.length&&n(u);for(var s=0;s Date: Mon, 14 Dec 2015 17:11:29 +0100 Subject: [PATCH 44/61] add error log update promise --- src/http.js | 10 +++++++++- src/lib/promise.js | 4 ---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/http.js b/src/http.js index 2df73bb9..5be46566 100644 --- a/src/http.js +++ b/src/http.js @@ -32,6 +32,13 @@ module.exports = function (_) { response.ok = response.status >= 200 && response.status < 300; return response.ok ? response : Promise.reject(response); + }, function (response) { + + if (response instanceof Error) { + console.error(response); + } + + return Promise.reject(response); })); if (request.success) { @@ -83,8 +90,9 @@ module.exports = function (_) { Http.options = { method: 'get', - params: {}, data: '', + params: {}, + headers: {}, xhr: null, jsonp: 'callback', beforeSend: null, diff --git a/src/lib/promise.js b/src/lib/promise.js index fe429629..6d46ec6a 100644 --- a/src/lib/promise.js +++ b/src/lib/promise.js @@ -201,9 +201,5 @@ module.exports = function (_) { return this; }; - _.promise = function (executor) { - return new Promise(executor); - }; - return Promise; }; From 0991e1915bdfab3a94959336dfb23c6a65d7a788 Mon Sep 17 00:00:00 2001 From: Steffan Date: Mon, 14 Dec 2015 18:23:35 +0100 Subject: [PATCH 45/61] add optional success or options --- src/http.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/http.js b/src/http.js index 5be46566..6bb19c1b 100644 --- a/src/http.js +++ b/src/http.js @@ -131,6 +131,11 @@ module.exports = function (_) { data = undefined; } + if (_.isObject(success)) { + options = success; + success = undefined; + } + return this(url, _.extend({method: method, data: data, success: success}, options)); }; }); From 9aba2bafeab08207b850057ff5f1edd4ab5911fb Mon Sep 17 00:00:00 2001 From: Steffan Date: Tue, 15 Dec 2015 10:44:29 +0100 Subject: [PATCH 46/61] add util.error function --- src/http.js | 2 +- src/lib/util.js | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/http.js b/src/http.js index 6bb19c1b..f01eef5c 100644 --- a/src/http.js +++ b/src/http.js @@ -35,7 +35,7 @@ module.exports = function (_) { }, function (response) { if (response instanceof Error) { - console.error(response); + _.error(response); } return Promise.reject(response); diff --git a/src/lib/util.js b/src/lib/util.js index 72cc02ae..a9777605 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -4,14 +4,20 @@ module.exports = function (Vue) { - var _ = Vue.util.extend({}, Vue.util), config = Vue.config; + var _ = Vue.util.extend({}, Vue.util), config = Vue.config, console = window.console; _.warn = function (msg) { - if (window.console && (!config.silent || config.debug)) { + if (console && (!config.silent || config.debug)) { console.warn('[VueResource warn]: ' + msg); } }; + _.error = function (msg) { + if (console && (!config.silent || config.debug)) { + console.error(msg); + } + }; + _.trim = function (str) { return str.replace(/^\s*|\s*$/g, ''); }; From 2615cb283c68608d42c16de40575642b35be8225 Mon Sep 17 00:00:00 2001 From: Malte Date: Tue, 15 Dec 2015 15:40:18 +0100 Subject: [PATCH 47/61] update only if Vue is in develop mode --- src/lib/util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/util.js b/src/lib/util.js index a9777605..bc8a620c 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -7,13 +7,13 @@ module.exports = function (Vue) { var _ = Vue.util.extend({}, Vue.util), config = Vue.config, console = window.console; _.warn = function (msg) { - if (console && (!config.silent || config.debug)) { + if (console && Vue.util.warn &&(!config.silent || config.debug)) { console.warn('[VueResource warn]: ' + msg); } }; _.error = function (msg) { - if (console && (!config.silent || config.debug)) { + if (console && Vue.util.error && (!config.silent || config.debug)) { console.error(msg); } }; From f3bbb3d306f6c06f300b64d1b6b24bfb6e7e0352 Mon Sep 17 00:00:00 2001 From: Malte Date: Tue, 15 Dec 2015 15:45:09 +0100 Subject: [PATCH 48/61] always throw errors --- src/lib/util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/util.js b/src/lib/util.js index bc8a620c..3131e6f2 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -7,13 +7,13 @@ module.exports = function (Vue) { var _ = Vue.util.extend({}, Vue.util), config = Vue.config, console = window.console; _.warn = function (msg) { - if (console && Vue.util.warn &&(!config.silent || config.debug)) { + if (console && Vue.util.warn && (!config.silent || config.debug)) { console.warn('[VueResource warn]: ' + msg); } }; _.error = function (msg) { - if (console && Vue.util.error && (!config.silent || config.debug)) { + if (console) { console.error(msg); } }; From 7426edf106c537dcd35bdbe4f0d419b8e32b6c5a Mon Sep 17 00:00:00 2001 From: Malte Date: Wed, 16 Dec 2015 13:41:14 +0100 Subject: [PATCH 49/61] wrap native promise if possible --- src/client/jsonp.js | 2 +- src/client/xdr.js | 2 +- src/client/xhr.js | 2 +- src/http.js | 2 +- src/index.js | 2 +- src/interceptor/index.js | 2 +- src/lib/promise.js | 27 +---------------- src/promise.js | 62 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 69 insertions(+), 32 deletions(-) create mode 100644 src/promise.js diff --git a/src/client/jsonp.js b/src/client/jsonp.js index cc08b1bf..ad031a54 100644 --- a/src/client/jsonp.js +++ b/src/client/jsonp.js @@ -4,7 +4,7 @@ module.exports = function (_) { - var Promise = require('../lib/promise')(_); + var Promise = require('../promise')(_); return function (request) { return new Promise(function (resolve) { diff --git a/src/client/xdr.js b/src/client/xdr.js index 48401852..ce2424fb 100644 --- a/src/client/xdr.js +++ b/src/client/xdr.js @@ -4,7 +4,7 @@ module.exports = function (_) { - var Promise = require('../lib/promise')(_); + var Promise = require('../promise')(_); return function (request) { return new Promise(function (resolve) { diff --git a/src/client/xhr.js b/src/client/xhr.js index 879f46d8..060c76b8 100644 --- a/src/client/xhr.js +++ b/src/client/xhr.js @@ -4,7 +4,7 @@ module.exports = function (_) { - var Promise = require('../lib/promise')(_); + var Promise = require('../promise')(_); return function (request) { return new Promise(function (resolve) { diff --git a/src/http.js b/src/http.js index f01eef5c..9ae02f80 100644 --- a/src/http.js +++ b/src/http.js @@ -4,7 +4,7 @@ module.exports = function (_) { - var Promise = require('./lib/promise')(_); + var Promise = require('./promise')(_); var interceptor = require('./interceptor')(_); var defaultClient = require('./client/default')(_); var jsonType = {'Content-Type': 'application/json'}; diff --git a/src/index.js b/src/index.js index f55e8957..71ae7fa0 100644 --- a/src/index.js +++ b/src/index.js @@ -9,7 +9,7 @@ function install(Vue) { Vue.url = require('./url')(_); Vue.http = require('./http')(_); Vue.resource = require('./resource')(_); - Vue.promise = require('./lib/promise')(_); + Vue.promise = require('./promise')(_); Object.defineProperties(Vue.prototype, { diff --git a/src/interceptor/index.js b/src/interceptor/index.js index 65d2a9ac..a54c8017 100644 --- a/src/interceptor/index.js +++ b/src/interceptor/index.js @@ -4,7 +4,7 @@ module.exports = function (_) { - var Promise = require('../lib/promise')(_); + var Promise = require('../promise')(_); return function (handler, vm) { return function (client) { diff --git a/src/lib/promise.js b/src/lib/promise.js index 6d46ec6a..346e64c3 100644 --- a/src/lib/promise.js +++ b/src/lib/promise.js @@ -166,40 +166,15 @@ module.exports = function (_) { p.then = function then(onResolved, onRejected) { var promise = this; - if (onResolved && this.context) { - onResolved = onResolved.bind(this.context); - } - - if (onRejected && this.context) { - onRejected = onRejected.bind(this.context); - } - return new Promise(function (resolve, reject) { promise.deferred.push([onResolved, onRejected, resolve, reject]); promise.notify(); - }).bind(this.context); + }); }; p.catch = function (onRejected) { return this.then(undefined, onRejected); }; - p.finally = function (callback) { - return this.then(function (value) { - return Promise.resolve(callback.call(this, value)).bind(this).then(function () { - return value; - }); - }, function (reason) { - return Promise.resolve(callback.call(this, reason)).bind(this).then(function () { - return Promise.reject(reason); - }); - }); - }; - - p.bind = function (context) { - this.context = context; - return this; - }; - return Promise; }; diff --git a/src/promise.js b/src/promise.js new file mode 100644 index 00000000..e7e5b4cf --- /dev/null +++ b/src/promise.js @@ -0,0 +1,62 @@ +module.exports = function (_) { + + var Promise = window.Promise || require('./lib/promise')(_); + + var Adapter = function (executor) { + + if (executor instanceof Promise) { + this.promise = executor; + } else { + this.promise = new Promise(executor); + } + + }; + + Adapter.all = function (iterable) { + return new Adapter(Promise.all(iterable)); + }; + + Adapter.resolve = function (value) { + return new Adapter(Promise.resolve(value)); + }; + + Adapter.reject = function (reason) { + return new Adapter(Promise.reject(reason)); + }; + + Adapter.race = function (iterable) { + return new Adapter(Promise.race(iterable)); + }; + + Adapter.prototype.bind = function (context) { + this.context = context; + return this; + }; + + Adapter.prototype.catch = function (onRejected) { + + if (onRejected && this.context) { + onRejected = onRejected.bind(this.context); + } + + this.promise = this.promise.catch(onRejected); + return this; + }; + + Adapter.prototype.then = function (onFulfilled, onRejected) { + + if (onFulfilled && this.context) { + onFulfilled = onFulfilled.bind(this.context); + } + + if (onRejected && this.context) { + onRejected = onRejected.bind(this.context); + } + + this.promise = this.promise.then(onFulfilled, onRejected); + return this; + }; + + return Adapter; + +}; \ No newline at end of file From c846ea27a77d38ad93f530617e208730f23bfef8 Mon Sep 17 00:00:00 2001 From: Malte Date: Wed, 16 Dec 2015 13:42:35 +0100 Subject: [PATCH 50/61] add promise tests --- test/index.js | 1 + test/promise.js | 141 +++++++++++++++++++++++++++++++++++++++++ test/webpack.config.js | 4 +- 3 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 test/promise.js diff --git a/test/index.js b/test/index.js index 2432ef1f..7408c696 100644 --- a/test/index.js +++ b/test/index.js @@ -4,4 +4,5 @@ var Resource = require('../src'); Vue.use(Resource); // require specs +require('./promise.js'); require('./http.js'); diff --git a/test/promise.js b/test/promise.js new file mode 100644 index 00000000..76c926ee --- /dev/null +++ b/test/promise.js @@ -0,0 +1,141 @@ +var Vue = require('vue'); + +var specs = function (Promise) { + + it('then fulfill', function (done) { + + Promise.resolve(1).then(function (value) { + expect(value).toBe(1); + done(); + }); + + }); + + it('then reject', function (done) { + + Promise.reject(1).then(undefined, function (value) { + expect(value).toBe(1); + done(); + }); + + }); + + it('catch', function (done) { + + Promise.reject(1).catch(function (value) { + expect(value).toBe(1); + done(); + }); + + }); + + it('all', function (done) { + + Promise.all([ + + Promise.resolve(1), + Promise.resolve(2) + + ]).then(function (values) { + expect(values[0]).toBe(1); + expect(values[1]).toBe(2); + done(); + }); + + }); + + it('duplicate', function (done) { + + Promise.all([ + + Promise.resolve(1).then(function (value) { + expect(value).toBe(1); + }), + + Promise.resolve(2).then(function (value) { + expect(value).toBe(2); + }) + + ]).then(done); + + }); + + it('context', function (done) { + + var context = {foo: 'bar'}; + + Promise.resolve().bind(context).then(function () { + expect(this).toBe(context); + done(); + }); + + }); + + it('context chain', function (done) { + + var context = {foo: 'bar'}; + + Promise.resolve().bind(context).catch(undefined).then(function () { + expect(this).toBe(context); + done(); + }); + + }); + + it('no chain breaking', function (done) { + + var promise = Promise.reject(); + + Promise.all([ + + promise.catch(function () { + expect(true).toBe(true); + }), + + promise.catch(function () { + fail('Chain break'); + }) + + ]).then(done); + + }); + +}; + +describe('Promise Adapter (native)', function () { + + if (window.Promise) { + + var Promise = require('../src/promise')(); + + it('is native', function () { + expect((new Promise.resolve()).promise instanceof window.Promise).toBe(true); + }); + + specs(Promise); + + } else { + + it('no native promise', function () { + expect(true).toBe(true); + }) + + } + +}); + +describe('Promise Adapter (polyfill)', function () { + + var native = window.Promise; + delete window.Promise; + + var Promise = require('../src/promise')(Vue.util); + window.Promise = native; + + it('is polyfill', function () { + expect((new Promise.resolve()).promise.state).toBe(0); + }); + + specs(Promise); + +}); \ No newline at end of file diff --git a/test/webpack.config.js b/test/webpack.config.js index dae0689c..521edad3 100644 --- a/test/webpack.config.js +++ b/test/webpack.config.js @@ -1,7 +1,7 @@ module.exports = { - entry: './test/index.js', + entry: __dirname + '/index.js', output: { - path: './test', + path: __dirname + '/', filename: 'specs.js' } }; From 61f98193387eb6e6d1eefbe068f0c8a5a7e4528f Mon Sep 17 00:00:00 2001 From: Malte Date: Wed, 16 Dec 2015 14:11:38 +0100 Subject: [PATCH 51/61] add promise finally method --- src/promise.js | 22 ++++++++++++++++++++++ test/promise.js | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/promise.js b/src/promise.js index e7e5b4cf..26e91d5a 100644 --- a/src/promise.js +++ b/src/promise.js @@ -57,6 +57,28 @@ module.exports = function (_) { return this; }; + Adapter.prototype.finally = function (callback) { + + return this.then( + + function (value) { + + callback.call(this); + return value; + + }, + + function (value) { + + callback.call(this); + return Promise.reject(value); + + } + + ); + + }; + return Adapter; }; \ No newline at end of file diff --git a/test/promise.js b/test/promise.js index 76c926ee..6fbe10ef 100644 --- a/test/promise.js +++ b/test/promise.js @@ -29,6 +29,28 @@ var specs = function (Promise) { }); + it('finally fulfill', function (done) { + + Promise.resolve(1).finally(function (arg) { + expect(arg).toBe(undefined); + }).then(function (arg) { + expect(arg).toBe(1); + done(); + }); + + }); + + it('finally reject', function (done) { + + Promise.reject(1).finally(function (arg) { + expect(arg).toBe(undefined); + }).catch(function (arg) { + expect(arg).toBe(1); + done(); + }); + + }); + it('all', function (done) { Promise.all([ @@ -71,11 +93,29 @@ var specs = function (Promise) { }); - it('context chain', function (done) { + it('context chain fulfill', function (done) { + + var context = {foo: 'bar'}; + + Promise.resolve().bind(context).catch(undefined).finally(function () { + expect(this).toBe(context); + }).then(function () { + expect(this).toBe(context); + done(); + }); + + }); + + it('context chain reject', function (done) { var context = {foo: 'bar'}; - Promise.resolve().bind(context).catch(undefined).then(function () { + Promise.reject().bind(context).catch(function () { + expect(this).toBe(context); + return Promise.reject(); + }).finally(function () { + expect(this).toBe(context); + }).catch(function () { expect(this).toBe(context); done(); }); @@ -127,9 +167,11 @@ describe('Promise Adapter (native)', function () { describe('Promise Adapter (polyfill)', function () { var native = window.Promise; + delete window.Promise; var Promise = require('../src/promise')(Vue.util); + window.Promise = native; it('is polyfill', function () { From 1f5094aaa85009ec5746019ffbc05cef561d3785 Mon Sep 17 00:00:00 2001 From: Steffan Date: Wed, 16 Dec 2015 15:16:32 +0100 Subject: [PATCH 52/61] update promise adapter --- src/promise.js | 53 +++++++++++++++++++++++-------------------------- test/index.js | 2 +- test/promise.js | 8 ++++---- 3 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/promise.js b/src/promise.js index 26e91d5a..c884d424 100644 --- a/src/promise.js +++ b/src/promise.js @@ -1,3 +1,7 @@ +/** + * Promise adapter. + */ + module.exports = function (_) { var Promise = window.Promise || require('./lib/promise')(_); @@ -28,57 +32,50 @@ module.exports = function (_) { return new Adapter(Promise.race(iterable)); }; - Adapter.prototype.bind = function (context) { + var p = Adapter.prototype; + + p.bind = function (context) { this.context = context; return this; }; - Adapter.prototype.catch = function (onRejected) { + p.then = function (fulfilled, rejected) { + + if (fulfilled && fulfilled.bind && this.context) { + fulfilled = fulfilled.bind(this.context); + } - if (onRejected && this.context) { - onRejected = onRejected.bind(this.context); + if (rejected && rejected.bind && this.context) { + rejected = rejected.bind(this.context); } - this.promise = this.promise.catch(onRejected); + this.promise = this.promise.then(fulfilled, rejected); + return this; }; - Adapter.prototype.then = function (onFulfilled, onRejected) { + p.catch = function (rejected) { - if (onFulfilled && this.context) { - onFulfilled = onFulfilled.bind(this.context); + if (rejected && rejected.bind && this.context) { + rejected = rejected.bind(this.context); } - if (onRejected && this.context) { - onRejected = onRejected.bind(this.context); - } + this.promise = this.promise.catch(rejected); - this.promise = this.promise.then(onFulfilled, onRejected); return this; }; - Adapter.prototype.finally = function (callback) { - - return this.then( - - function (value) { + p.finally = function (callback) { + return this.then(function (value) { callback.call(this); return value; - - }, - - function (value) { - + }, function (reason) { callback.call(this); - return Promise.reject(value); - + return Promise.reject(reason); } - ); - }; return Adapter; - -}; \ No newline at end of file +}; diff --git a/test/index.js b/test/index.js index 7408c696..446da99b 100644 --- a/test/index.js +++ b/test/index.js @@ -4,5 +4,5 @@ var Resource = require('../src'); Vue.use(Resource); // require specs -require('./promise.js'); require('./http.js'); +require('./promise.js'); diff --git a/test/promise.js b/test/promise.js index 6fbe10ef..9360fa18 100644 --- a/test/promise.js +++ b/test/promise.js @@ -142,7 +142,7 @@ var specs = function (Promise) { }; -describe('Promise Adapter (native)', function () { +describe('Vue.promise (native)', function () { if (window.Promise) { @@ -158,13 +158,13 @@ describe('Promise Adapter (native)', function () { it('no native promise', function () { expect(true).toBe(true); - }) + }); } }); -describe('Promise Adapter (polyfill)', function () { +describe('Vue.promise (polyfill)', function () { var native = window.Promise; @@ -180,4 +180,4 @@ describe('Promise Adapter (polyfill)', function () { specs(Promise); -}); \ No newline at end of file +}); From 460083d9cab69ad03af8b4e202fa2ebc242e179d Mon Sep 17 00:00:00 2001 From: Steffan Date: Wed, 16 Dec 2015 15:17:13 +0100 Subject: [PATCH 53/61] update dist --- dist/vue-resource.js | 185 +++++++++++++++++++++++++++------------ dist/vue-resource.min.js | 2 +- 2 files changed, 132 insertions(+), 55 deletions(-) diff --git a/dist/vue-resource.js b/dist/vue-resource.js index da54da20..1d6761fc 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -70,7 +70,7 @@ return /******/ (function(modules) { // webpackBootstrap Vue.url = __webpack_require__(2)(_); Vue.http = __webpack_require__(3)(_); - Vue.resource = __webpack_require__(16)(_); + Vue.resource = __webpack_require__(17)(_); Vue.promise = __webpack_require__(4)(_); Object.defineProperties(Vue.prototype, { @@ -113,14 +113,20 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (Vue) { - var _ = Vue.util.extend({}, Vue.util), config = Vue.config; + var _ = Vue.util.extend({}, Vue.util), config = Vue.config, console = window.console; _.warn = function (msg) { - if (window.console && (!config.silent || config.debug)) { + if (console && Vue.util.warn && (!config.silent || config.debug)) { console.warn('[VueResource warn]: ' + msg); } }; + _.error = function (msg) { + if (console) { + console.error(msg); + } + }; + _.trim = function (str) { return str.replace(/^\s*|\s*$/g, ''); }; @@ -377,8 +383,8 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { var Promise = __webpack_require__(4)(_); - var interceptor = __webpack_require__(5)(_); - var defaultClient = __webpack_require__(6)(_); + var interceptor = __webpack_require__(6)(_); + var defaultClient = __webpack_require__(7)(_); var jsonType = {'Content-Type': 'application/json'}; function Http(url, options) { @@ -404,6 +410,13 @@ return /******/ (function(modules) { // webpackBootstrap response.ok = response.status >= 200 && response.status < 300; return response.ok ? response : Promise.reject(response); + }, function (response) { + + if (response instanceof Error) { + _.error(response); + } + + return Promise.reject(response); })); if (request.success) { @@ -455,8 +468,9 @@ return /******/ (function(modules) { // webpackBootstrap Http.options = { method: 'get', - params: {}, data: '', + params: {}, + headers: {}, xhr: null, jsonp: 'callback', beforeSend: null, @@ -467,13 +481,13 @@ return /******/ (function(modules) { // webpackBootstrap }; Http.interceptors = [ - __webpack_require__(8)(_), __webpack_require__(9)(_), __webpack_require__(10)(_), - __webpack_require__(12)(_), + __webpack_require__(11)(_), __webpack_require__(13)(_), __webpack_require__(14)(_), - __webpack_require__(15)(_) + __webpack_require__(15)(_), + __webpack_require__(16)(_) ]; Http.headers = { @@ -495,6 +509,11 @@ return /******/ (function(modules) { // webpackBootstrap data = undefined; } + if (_.isObject(success)) { + options = success; + success = undefined; + } + return this(url, _.extend({method: method, data: data, success: success}, options)); }; }); @@ -505,6 +524,93 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 4 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Promise adapter. + */ + + module.exports = function (_) { + + var Promise = window.Promise || __webpack_require__(5)(_); + + var Adapter = function (executor) { + + if (executor instanceof Promise) { + this.promise = executor; + } else { + this.promise = new Promise(executor); + } + + }; + + Adapter.all = function (iterable) { + return new Adapter(Promise.all(iterable)); + }; + + Adapter.resolve = function (value) { + return new Adapter(Promise.resolve(value)); + }; + + Adapter.reject = function (reason) { + return new Adapter(Promise.reject(reason)); + }; + + Adapter.race = function (iterable) { + return new Adapter(Promise.race(iterable)); + }; + + var p = Adapter.prototype; + + p.bind = function (context) { + this.context = context; + return this; + }; + + p.then = function (fulfilled, rejected) { + + if (fulfilled && fulfilled.bind && this.context) { + fulfilled = fulfilled.bind(this.context); + } + + if (rejected && rejected.bind && this.context) { + rejected = rejected.bind(this.context); + } + + this.promise = this.promise.then(fulfilled, rejected); + + return this; + }; + + p.catch = function (rejected) { + + if (rejected && rejected.bind && this.context) { + rejected = rejected.bind(this.context); + } + + this.promise = this.promise.catch(rejected); + + return this; + }; + + p.finally = function (callback) { + + return this.then(function (value) { + callback.call(this); + return value; + }, function (reason) { + callback.call(this); + return Promise.reject(reason); + } + ); + }; + + return Adapter; + }; + + +/***/ }, +/* 5 */ /***/ function(module, exports) { /** @@ -675,51 +781,22 @@ return /******/ (function(modules) { // webpackBootstrap p.then = function then(onResolved, onRejected) { var promise = this; - if (onResolved && this.context) { - onResolved = onResolved.bind(this.context); - } - - if (onRejected && this.context) { - onRejected = onRejected.bind(this.context); - } - return new Promise(function (resolve, reject) { promise.deferred.push([onResolved, onRejected, resolve, reject]); promise.notify(); - }).bind(this.context); + }); }; p.catch = function (onRejected) { return this.then(undefined, onRejected); }; - p.finally = function (callback) { - return this.then(function (value) { - return Promise.resolve(callback.call(this, value)).bind(this).then(function () { - return value; - }); - }, function (reason) { - return Promise.resolve(callback.call(this, reason)).bind(this).then(function () { - return Promise.reject(reason); - }); - }); - }; - - p.bind = function (context) { - this.context = context; - return this; - }; - - _.promise = function (executor) { - return new Promise(executor); - }; - return Promise; }; /***/ }, -/* 5 */ +/* 6 */ /***/ function(module, exports, __webpack_require__) { /** @@ -772,7 +849,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 6 */ +/* 7 */ /***/ function(module, exports, __webpack_require__) { /** @@ -781,7 +858,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var xhrClient = __webpack_require__(7)(_); + var xhrClient = __webpack_require__(8)(_); return function (request) { return (request.client || xhrClient)(request); @@ -791,7 +868,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 7 */ +/* 8 */ /***/ function(module, exports, __webpack_require__) { /** @@ -891,7 +968,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 8 */ +/* 9 */ /***/ function(module, exports) { /** @@ -917,7 +994,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 9 */ +/* 10 */ /***/ function(module, exports) { /** @@ -957,7 +1034,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 10 */ +/* 11 */ /***/ function(module, exports, __webpack_require__) { /** @@ -966,7 +1043,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var jsonpClient = __webpack_require__(11)(_); + var jsonpClient = __webpack_require__(12)(_); return { @@ -985,7 +1062,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 11 */ +/* 12 */ /***/ function(module, exports, __webpack_require__) { /** @@ -1042,7 +1119,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 12 */ +/* 13 */ /***/ function(module, exports) { /** @@ -1069,7 +1146,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 13 */ +/* 14 */ /***/ function(module, exports) { /** @@ -1113,7 +1190,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 14 */ +/* 15 */ /***/ function(module, exports) { /** @@ -1147,7 +1224,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 15 */ +/* 16 */ /***/ function(module, exports, __webpack_require__) { /** @@ -1157,7 +1234,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { var originUrl = _.url.parse(location.href); - var xdrClient = __webpack_require__(11)(_); + var xdrClient = __webpack_require__(12)(_); var xhrCors = 'withCredentials' in new XMLHttpRequest(); return { @@ -1193,7 +1270,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 16 */ +/* 17 */ /***/ function(module, exports) { /** diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index 79c11350..c75553c8 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -4,4 +4,4 @@ * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(16)(e),t.promise=n(4)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return e.options(t.url,this,this.$options.url)}},$http:{get:function(){return e.options(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var i in r)o&&(n.isPlainObject(r[i])||n.isArray(r[i]))?(n.isPlainObject(r[i])&&!n.isPlainObject(t[i])&&(t[i]={}),n.isArray(r[i])&&!n.isArray(t[i])&&(t[i]=[]),e(t[i],r[i],o)):void 0!==r[i]&&(t[i]=r[i])}var n=t.util.extend({},t.util),r=t.config;return n.warn=function(t){!window.console||r.silent&&!r.debug||console.warn("[VueResource warn]: "+t)},n.trim=function(t){return t.replace(/^\s*|\s*$/g,"")},n.toLower=function(t){return t?t.toLowerCase():""},n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&t.status<300,t.ok?t:o.reject(t)})),a.success&&(c=c.success(a.success)),a.error&&(c=c.error(a.error)),c}function r(e){return e.success=function(n){return t.warn("The `success` method has been deprecated. Use the `then` method instead."),r(e.then(function(t){return n.call(this,t.data,t.status,t)||t}))},e.error=function(n){return t.warn("The `error` method has been deprecated. Use the `catch` method instead."),r(e.then(void 0,function(t){return n.call(this,t.data,t.status,t)||t}))},e.always=function(n){t.warn("The `always` method has been deprecated. Use the `finally` method instead.");var o=function(t){return n.call(this,t.data,t.status,t)||t};return r(e.then(o,o))},e}var o=n(4)(t),i=n(5)(t),u=n(6)(t),s={"Content-Type":"application/json"};return e.options={method:"get",params:{},data:"",xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(8)(t),n(9)(t),n(10)(t),n(12)(t),n(13)(t),n(14)(t),n(15)(t)],e.headers={put:s,post:s,patch:s,"delete":s,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e){t.exports=function(t){function e(t){this.state=o,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var n=0,r=1,o=2;e.reject=function(t){return new e(function(e,n){n(t)})},e.resolve=function(t){return new e(function(e,n){e(t)})},e.all=function(t){return new e(function(n,r){function o(e){return function(r){u[e]=r,i+=1,i===t.length&&n(u)}}var i=0,u=[];0===t.length&&n(u);for(var s=0;s=200&&t.status<300,t.ok?t:o.reject(t)},function(e){return e instanceof Error&&t.error(e),o.reject(e)})),c.success&&(a=a.success(c.success)),c.error&&(a=a.error(c.error)),a}function r(e){return e.success=function(n){return t.warn("The `success` method has been deprecated. Use the `then` method instead."),r(e.then(function(t){return n.call(this,t.data,t.status,t)||t}))},e.error=function(n){return t.warn("The `error` method has been deprecated. Use the `catch` method instead."),r(e.then(void 0,function(t){return n.call(this,t.data,t.status,t)||t}))},e.always=function(n){t.warn("The `always` method has been deprecated. Use the `finally` method instead.");var o=function(t){return n.call(this,t.data,t.status,t)||t};return r(e.then(o,o))},e}var o=n(4)(t),i=n(6)(t),u=n(7)(t),s={"Content-Type":"application/json"};return e.options={method:"get",data:"",params:{},headers:{},xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(9)(t),n(10)(t),n(11)(t),n(13)(t),n(14)(t),n(15)(t),n(16)(t)],e.headers={put:s,post:s,patch:s,"delete":s,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),t.isObject(o)&&(i=o,o=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e,n){t.exports=function(t){var e=window.Promise||n(5)(t),r=function(t){t instanceof e?this.promise=t:this.promise=new e(t)};r.all=function(t){return new r(e.all(t))},r.resolve=function(t){return new r(e.resolve(t))},r.reject=function(t){return new r(e.reject(t))},r.race=function(t){return new r(e.race(t))};var o=r.prototype;return o.bind=function(t){return this.context=t,this},o.then=function(t,e){return t&&t.bind&&this.context&&(t=t.bind(this.context)),e&&e.bind&&this.context&&(e=e.bind(this.context)),this.promise=this.promise.then(t,e),this},o["catch"]=function(t){return t&&t.bind&&this.context&&(t=t.bind(this.context)),this.promise=this.promise["catch"](t),this},o["finally"]=function(t){return this.then(function(e){return t.call(this),e},function(n){return t.call(this),e.reject(n)})},r}},function(t,e){t.exports=function(t){function e(t){this.state=o,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var n=0,r=1,o=2;e.reject=function(t){return new e(function(e,n){n(t)})},e.resolve=function(t){return new e(function(e,n){e(t)})},e.all=function(t){return new e(function(n,r){function o(e){return function(r){u[e]=r,i+=1,i===t.length&&n(u)}}var i=0,u=[];0===t.length&&n(u);for(var s=0;s Date: Wed, 16 Dec 2015 15:19:05 +0100 Subject: [PATCH 54/61] init context --- src/promise.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/promise.js b/src/promise.js index c884d424..39250832 100644 --- a/src/promise.js +++ b/src/promise.js @@ -14,6 +14,7 @@ module.exports = function (_) { this.promise = new Promise(executor); } + this.context = undefined; }; Adapter.all = function (iterable) { From fe73c797bf7686d4470f0b73fee4f70e32b472ee Mon Sep 17 00:00:00 2001 From: Steffan Date: Wed, 16 Dec 2015 16:56:46 +0100 Subject: [PATCH 55/61] move methods to promise adapter --- src/http.js | 44 ++++---------------------------------------- src/promise.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 40 deletions(-) diff --git a/src/http.js b/src/http.js index 9ae02f80..42a18e40 100644 --- a/src/http.js +++ b/src/http.js @@ -27,7 +27,7 @@ module.exports = function (_) { client = interceptor(i, this.vm)(client); }, this); - promise = extendPromise(client(request).bind(this.vm).then(function (response) { + promise = client(request).bind(this.vm).then(function (response) { response.ok = response.status >= 200 && response.status < 300; return response.ok ? response : Promise.reject(response); @@ -39,55 +39,19 @@ module.exports = function (_) { } return Promise.reject(response); - })); + }); if (request.success) { - promise = promise.success(request.success); + promise.success(request.success); } if (request.error) { - promise = promise.error(request.error); + promise.error(request.error); } return promise; } - function extendPromise(promise) { - - promise.success = function (fn) { - - _.warn('The `success` method has been deprecated. Use the `then` method instead.'); - - return extendPromise(promise.then(function (response) { - return fn.call(this, response.data, response.status, response) || response; - })); - - }; - - promise.error = function (fn) { - - _.warn('The `error` method has been deprecated. Use the `catch` method instead.'); - - return extendPromise(promise.then(undefined, function (response) { - return fn.call(this, response.data, response.status, response) || response; - })); - - }; - - promise.always = function (fn) { - - _.warn('The `always` method has been deprecated. Use the `finally` method instead.'); - - var cb = function (response) { - return fn.call(this, response.data, response.status, response) || response; - }; - - return extendPromise(promise.then(cb, cb)); - }; - - return promise; - } - Http.options = { method: 'get', data: '', diff --git a/src/promise.js b/src/promise.js index 39250832..6bf03765 100644 --- a/src/promise.js +++ b/src/promise.js @@ -78,5 +78,34 @@ module.exports = function (_) { ); }; + p.success = function (callback) { + + _.warn('The `success` method has been deprecated. Use the `then` method instead.'); + + return this.then(function (response) { + return callback.call(this, response.data, response.status, response) || response; + }); + }; + + p.error = function (callback) { + + _.warn('The `error` method has been deprecated. Use the `catch` method instead.'); + + return this.catch(function (response) { + return callback.call(this, response.data, response.status, response) || response; + }); + }; + + p.always = function (callback) { + + _.warn('The `always` method has been deprecated. Use the `finally` method instead.'); + + var cb = function (response) { + return callback.call(this, response.data, response.status, response) || response; + }; + + return this.then(cb, cb); + }; + return Adapter; }; From 3468e4cf4c2f80ca6e39f431927045de915e3a27 Mon Sep 17 00:00:00 2001 From: Steffan Date: Wed, 16 Dec 2015 17:05:35 +0100 Subject: [PATCH 56/61] update readme --- README.md | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index e66f5395..a86bf02e 100644 --- a/README.md +++ b/README.md @@ -46,12 +46,12 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt ### Methods -* `get(url, [data], [success], [options])` -* `post(url, [data], [success], [options])` -* `put(url, [data], [success], [options])` -* `patch(url, [data], [success], [options])` -* `delete(url, [data], [success], [options])` -* `jsonp(url, [data], [success], [options])` +* `get(url, [data], [options])` +* `post(url, [data], [options])` +* `put(url, [data], [options])` +* `patch(url, [data], [options])` +* `delete(url, [data], [options])` +* `jsonp(url, [data], [options])` ### Options @@ -60,7 +60,7 @@ The http service can be used globally `Vue.http` or in a Vue instance `this.$htt * **data** - `Object|string` - Data to be sent as the request message data * **params** - `Object` - Parameters object to be appended as GET parameters * **headers** - `Object` - Headers object to be sent as HTTP request headers -* **beforeSend** - `function(request, options)` - Callback function to modify the request object before it is sent +* **beforeSend** - `function(request)` - Callback function to modify the request object before it is sent * **emulateHTTP** - `boolean` - Send PUT, PATCH and DELETE requests with a HTTP POST and set the `X-HTTP-Method-Override` header * **emulateJSON** - `boolean` - Send request data as `application/x-www-form-urlencoded` content type * **xhr** - `Object` - Parameters object to be set on the native XHR object @@ -177,17 +177,18 @@ If Promises are needed inside of a Interceptor, a factory function can be used. Vue.http.interceptors.push(function (Promise) { return { - request: function (request) { - if (reject) { - return Promise.reject(); - } - }, + request: function (request) { + if (reject) { + return Promise.reject(); + } + }, - response: function (response) { - if (reject) { + response: function (response) { + if (reject) { return Promise.reject(); - } - } + } + } + }; }); ``` From f31aa947baca7afef0bc93e67c6cc0f874c35032 Mon Sep 17 00:00:00 2001 From: Steffan Date: Sat, 19 Dec 2015 18:15:04 +0100 Subject: [PATCH 57/61] add URI Templating, RFC6570 --- src/lib/url-template.js | 150 ++++++++++++++++++++++++++++++++++++++++ src/url.js | 16 +++-- test/index.js | 1 + test/url.js | 20 ++++++ 4 files changed, 181 insertions(+), 6 deletions(-) create mode 100644 src/lib/url-template.js create mode 100644 test/url.js diff --git a/src/lib/url-template.js b/src/lib/url-template.js new file mode 100644 index 00000000..803388b4 --- /dev/null +++ b/src/lib/url-template.js @@ -0,0 +1,150 @@ +/** + * URL Template v2.0.6 (https://github.com/bramstein/url-template) + */ + +exports.expand = function (url, params, variables) { + + var tmpl = this.parse(url), expanded = tmpl.expand(params); + + if (variables) { + variables.push.apply(variables, tmpl.vars); + } + + return expanded; +}; + +exports.parse = function (template) { + + var operators = ['+', '#', '.', '/', ';', '?', '&'], variables = []; + + return { + vars: variables, + expand: function (context) { + return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) { + if (expression) { + + var operator = null, values = []; + + if (operators.indexOf(expression.charAt(0)) !== -1) { + operator = expression.charAt(0); + expression = expression.substr(1); + } + + expression.split(/,/g).forEach(function (variable) { + var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); + values.push.apply(values, exports.getValues(context, operator, tmp[1], tmp[2] || tmp[3])); + variables.push(tmp[1]); + }); + + if (operator && operator !== '+') { + + var separator = ','; + + if (operator === '?') { + separator = '&'; + } else if (operator !== '#') { + separator = operator; + } + + return (values.length !== 0 ? operator : '') + values.join(separator); + } else { + return values.join(','); + } + + } else { + return exports.encodeReserved(literal); + } + }); + } + }; +}; + +exports.getValues = function (context, operator, key, modifier) { + + var value = context[key], result = []; + + if (this.isDefined(value) && value !== '') { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + value = value.toString(); + + if (modifier && modifier !== '*') { + value = value.substring(0, parseInt(modifier, 10)); + } + + result.push(this.encodeValue(operator, value, this.isKeyOperator(operator) ? key : null)); + } else { + if (modifier === '*') { + if (Array.isArray(value)) { + value.filter(this.isDefined).forEach(function (value) { + result.push(this.encodeValue(operator, value, this.isKeyOperator(operator) ? key : null)); + }, this); + } else { + Object.keys(value).forEach(function (k) { + if (this.isDefined(value[k])) { + result.push(this.encodeValue(operator, value[k], k)); + } + }, this); + } + } else { + var tmp = []; + + if (Array.isArray(value)) { + value.filter(this.isDefined).forEach(function (value) { + tmp.push(this.encodeValue(operator, value)); + }, this); + } else { + Object.keys(value).forEach(function (k) { + if (this.isDefined(value[k])) { + tmp.push(encodeURIComponent(k)); + tmp.push(this.encodeValue(operator, value[k].toString())); + } + }, this); + } + + if (this.isKeyOperator(operator)) { + result.push(encodeURIComponent(key) + '=' + tmp.join(',')); + } else if (tmp.length !== 0) { + result.push(tmp.join(',')); + } + } + } + } else { + if (operator === ';') { + result.push(encodeURIComponent(key)); + } else if (value === '' && (operator === '&' || operator === '?')) { + result.push(encodeURIComponent(key) + '='); + } else if (value === '') { + result.push(''); + } + } + + return result; +}; + +exports.isDefined = function (value) { + return value !== undefined && value !== null; +}; + +exports.isKeyOperator = function (operator) { + return operator === ';' || operator === '&' || operator === '?'; +}; + +exports.encodeValue = function (operator, value, key) { + + value = (operator === '+' || operator === '#') ? this.encodeReserved(value) : encodeURIComponent(value); + + if (key) { + return encodeURIComponent(key) + '=' + value; + } else { + return value; + } +}; + +exports.encodeReserved = function (str) { + return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) { + if (!/%[0-9A-Fa-f]/.test(part)) { + part = encodeURI(part); + } + return part; + }).join(''); +}; diff --git a/src/url.js b/src/url.js index 67ea81ec..4693ffe0 100644 --- a/src/url.js +++ b/src/url.js @@ -2,14 +2,16 @@ * Service for URL templating. */ -var ie = document.documentMode; -var el = document.createElement('a'); +var UrlTemplate = require('./lib/url-template'); module.exports = function (_) { + var ie = document.documentMode; + var el = document.createElement('a'); + function Url(url, params) { - var urlParams = {}, queryParams = {}, options = url, query; + var urlParams = [], queryParams = {}, options = url, query; if (!_.isPlainObject(options)) { options = {url: url, params: params}; @@ -19,10 +21,12 @@ module.exports = function (_) { Url.options, this.options, options ); - url = options.url.replace(/(\/?):([a-z]\w*)/gi, function (match, slash, name) { + url = UrlTemplate.expand(options.url, options.params, urlParams); + + url = url.replace(/(\/?):([a-z]\w*)/gi, function (match, slash, name) { if (options.params[name]) { - urlParams[name] = true; + urlParams.push(name); return slash + encodeUriSegment(options.params[name]); } @@ -34,7 +38,7 @@ module.exports = function (_) { } _.each(options.params, function (value, key) { - if (!urlParams[key]) { + if (urlParams.indexOf(key) === -1) { queryParams[key] = value; } }); diff --git a/test/index.js b/test/index.js index 446da99b..388d62c9 100644 --- a/test/index.js +++ b/test/index.js @@ -4,5 +4,6 @@ var Resource = require('../src'); Vue.use(Resource); // require specs +require('./url.js'); require('./http.js'); require('./promise.js'); diff --git a/test/url.js b/test/url.js new file mode 100644 index 00000000..27afa9d6 --- /dev/null +++ b/test/url.js @@ -0,0 +1,20 @@ +var Vue = require('vue'); +var Url = require('url-template'); + +describe('Vue.url', function () { + + it('data{/id}', function () { + + expect(Vue.url('data{/id}')).toBe('data'); + expect(Vue.url('data{/id}', {id: 1})).toBe('data/1'); + + }); + + it('data/:id (deprecated)', function () { + + expect(Vue.url('data/:id')).toBe('data'); + expect(Vue.url('data/:id', {id: 1})).toBe('data/1'); + + }); + +}); From ae44f37c24836fee7a2eba9f252ec4e3836968ca Mon Sep 17 00:00:00 2001 From: Steffan Date: Sat, 19 Dec 2015 18:48:42 +0100 Subject: [PATCH 58/61] add check for default url params --- src/url.js | 2 +- test/url.js | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/url.js b/src/url.js index 4693ffe0..5b537895 100644 --- a/src/url.js +++ b/src/url.js @@ -11,7 +11,7 @@ module.exports = function (_) { function Url(url, params) { - var urlParams = [], queryParams = {}, options = url, query; + var urlParams = Object.keys(Url.options.params), queryParams = {}, options = url, query; if (!_.isPlainObject(options)) { options = {url: url, params: params}; diff --git a/test/url.js b/test/url.js index 27afa9d6..e26debd8 100644 --- a/test/url.js +++ b/test/url.js @@ -1,8 +1,14 @@ var Vue = require('vue'); -var Url = require('url-template'); describe('Vue.url', function () { + it('data/:id', function () { + + expect(Vue.url('data/:id')).toBe('data'); + expect(Vue.url('data/:id', {id: 1})).toBe('data/1'); + + }); + it('data{/id}', function () { expect(Vue.url('data{/id}')).toBe('data'); @@ -10,10 +16,17 @@ describe('Vue.url', function () { }); - it('data/:id (deprecated)', function () { + it('{+path}data', function () { - expect(Vue.url('data/:id')).toBe('data'); - expect(Vue.url('data/:id', {id: 1})).toBe('data/1'); + expect(Vue.url('{+path}data')).toBe('data'); + expect(Vue.url('{+path}data', {path: 'path1/path2/'})).toBe('path1/path2/data'); + + }); + + it('{+base}data', function () { + + Vue.url.options.params.base = 'base/path/'; + expect(Vue.url('{+base}data')).toBe('base/path/data'); }); From 328486343f3ca9e263d35db8184214b0ca330f1b Mon Sep 17 00:00:00 2001 From: Steffan Date: Sat, 19 Dec 2015 18:52:34 +0100 Subject: [PATCH 59/61] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a86bf02e..512c4508 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ new Vue({ ready: function() { - var resource = this.$resource('someItem/:id'); + var resource = this.$resource('someItem{/id}'); // get item resource.get({id: 1}).then(function (response) { From 8d2f0d53b9482c03b31fd4471e98cfdc3680add0 Mon Sep 17 00:00:00 2001 From: Steffan Date: Sun, 20 Dec 2015 13:50:31 +0100 Subject: [PATCH 60/61] add url parameter deprecation notice --- src/url.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/url.js b/src/url.js index 5b537895..eb42a0f5 100644 --- a/src/url.js +++ b/src/url.js @@ -25,6 +25,8 @@ module.exports = function (_) { url = url.replace(/(\/?):([a-z]\w*)/gi, function (match, slash, name) { + _.warn('The `:' + name + '` parameter syntax has been deprecated. Use the `{' + name + '}` syntax instead.'); + if (options.params[name]) { urlParams.push(name); return slash + encodeUriSegment(options.params[name]); From e6b4d64aba87d0d55f67cec16b2fd38654cad16b Mon Sep 17 00:00:00 2001 From: Steffan Date: Sun, 20 Dec 2015 13:53:15 +0100 Subject: [PATCH 61/61] v0.5.0 --- bower.json | 2 +- dist/vue-resource.js | 312 +++++++++++++++++++++++++++++---------- dist/vue-resource.min.js | 4 +- package.json | 2 +- 4 files changed, 238 insertions(+), 82 deletions(-) diff --git a/bower.json b/bower.json index c5b36ed4..d731040e 100644 --- a/bower.json +++ b/bower.json @@ -2,7 +2,7 @@ "name": "vue-resource", "main": "dist/vue-resource.js", "description": "A web request service for Vue.js", - "version": "0.2.0", + "version": "0.5.0", "homepage": "https://github.com/vuejs/vue-resource", "license": "MIT", "ignore": [ diff --git a/dist/vue-resource.js b/dist/vue-resource.js index 1d6761fc..edb7d85b 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -1,5 +1,5 @@ /** - * vue-resource v0.2.0 + * vue-resource v0.5.0 * https://github.com/vuejs/vue-resource * Released under the MIT License. */ @@ -69,9 +69,9 @@ return /******/ (function(modules) { // webpackBootstrap var _ = __webpack_require__(1)(Vue); Vue.url = __webpack_require__(2)(_); - Vue.http = __webpack_require__(3)(_); - Vue.resource = __webpack_require__(17)(_); - Vue.promise = __webpack_require__(4)(_); + Vue.http = __webpack_require__(4)(_); + Vue.resource = __webpack_require__(18)(_); + Vue.promise = __webpack_require__(5)(_); Object.defineProperties(Vue.prototype, { @@ -211,20 +211,22 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 2 */ -/***/ function(module, exports) { +/***/ function(module, exports, __webpack_require__) { /** * Service for URL templating. */ - var ie = document.documentMode; - var el = document.createElement('a'); + var UrlTemplate = __webpack_require__(3); module.exports = function (_) { + var ie = document.documentMode; + var el = document.createElement('a'); + function Url(url, params) { - var urlParams = {}, queryParams = {}, options = url, query; + var urlParams = Object.keys(Url.options.params), queryParams = {}, options = url, query; if (!_.isPlainObject(options)) { options = {url: url, params: params}; @@ -234,10 +236,14 @@ return /******/ (function(modules) { // webpackBootstrap Url.options, this.options, options ); - url = options.url.replace(/(\/?):([a-z]\w*)/gi, function (match, slash, name) { + url = UrlTemplate.expand(options.url, options.params, urlParams); + + url = url.replace(/(\/?):([a-z]\w*)/gi, function (match, slash, name) { + + _.warn('The `:' + name + '` parameter syntax has been deprecated. Use the `{' + name + '}` syntax instead.'); if (options.params[name]) { - urlParams[name] = true; + urlParams.push(name); return slash + encodeUriSegment(options.params[name]); } @@ -249,7 +255,7 @@ return /******/ (function(modules) { // webpackBootstrap } _.each(options.params, function (value, key) { - if (!urlParams[key]) { + if (urlParams.indexOf(key) === -1) { queryParams[key] = value; } }); @@ -374,6 +380,162 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, /* 3 */ +/***/ function(module, exports) { + + /** + * URL Template v2.0.6 (https://github.com/bramstein/url-template) + */ + + exports.expand = function (url, params, variables) { + + var tmpl = this.parse(url), expanded = tmpl.expand(params); + + if (variables) { + variables.push.apply(variables, tmpl.vars); + } + + return expanded; + }; + + exports.parse = function (template) { + + var operators = ['+', '#', '.', '/', ';', '?', '&'], variables = []; + + return { + vars: variables, + expand: function (context) { + return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) { + if (expression) { + + var operator = null, values = []; + + if (operators.indexOf(expression.charAt(0)) !== -1) { + operator = expression.charAt(0); + expression = expression.substr(1); + } + + expression.split(/,/g).forEach(function (variable) { + var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); + values.push.apply(values, exports.getValues(context, operator, tmp[1], tmp[2] || tmp[3])); + variables.push(tmp[1]); + }); + + if (operator && operator !== '+') { + + var separator = ','; + + if (operator === '?') { + separator = '&'; + } else if (operator !== '#') { + separator = operator; + } + + return (values.length !== 0 ? operator : '') + values.join(separator); + } else { + return values.join(','); + } + + } else { + return exports.encodeReserved(literal); + } + }); + } + }; + }; + + exports.getValues = function (context, operator, key, modifier) { + + var value = context[key], result = []; + + if (this.isDefined(value) && value !== '') { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + value = value.toString(); + + if (modifier && modifier !== '*') { + value = value.substring(0, parseInt(modifier, 10)); + } + + result.push(this.encodeValue(operator, value, this.isKeyOperator(operator) ? key : null)); + } else { + if (modifier === '*') { + if (Array.isArray(value)) { + value.filter(this.isDefined).forEach(function (value) { + result.push(this.encodeValue(operator, value, this.isKeyOperator(operator) ? key : null)); + }, this); + } else { + Object.keys(value).forEach(function (k) { + if (this.isDefined(value[k])) { + result.push(this.encodeValue(operator, value[k], k)); + } + }, this); + } + } else { + var tmp = []; + + if (Array.isArray(value)) { + value.filter(this.isDefined).forEach(function (value) { + tmp.push(this.encodeValue(operator, value)); + }, this); + } else { + Object.keys(value).forEach(function (k) { + if (this.isDefined(value[k])) { + tmp.push(encodeURIComponent(k)); + tmp.push(this.encodeValue(operator, value[k].toString())); + } + }, this); + } + + if (this.isKeyOperator(operator)) { + result.push(encodeURIComponent(key) + '=' + tmp.join(',')); + } else if (tmp.length !== 0) { + result.push(tmp.join(',')); + } + } + } + } else { + if (operator === ';') { + result.push(encodeURIComponent(key)); + } else if (value === '' && (operator === '&' || operator === '?')) { + result.push(encodeURIComponent(key) + '='); + } else if (value === '') { + result.push(''); + } + } + + return result; + }; + + exports.isDefined = function (value) { + return value !== undefined && value !== null; + }; + + exports.isKeyOperator = function (operator) { + return operator === ';' || operator === '&' || operator === '?'; + }; + + exports.encodeValue = function (operator, value, key) { + + value = (operator === '+' || operator === '#') ? this.encodeReserved(value) : encodeURIComponent(value); + + if (key) { + return encodeURIComponent(key) + '=' + value; + } else { + return value; + } + }; + + exports.encodeReserved = function (str) { + return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) { + if (!/%[0-9A-Fa-f]/.test(part)) { + part = encodeURI(part); + } + return part; + }).join(''); + }; + + +/***/ }, +/* 4 */ /***/ function(module, exports, __webpack_require__) { /** @@ -382,9 +544,9 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var Promise = __webpack_require__(4)(_); - var interceptor = __webpack_require__(6)(_); - var defaultClient = __webpack_require__(7)(_); + var Promise = __webpack_require__(5)(_); + var interceptor = __webpack_require__(7)(_); + var defaultClient = __webpack_require__(8)(_); var jsonType = {'Content-Type': 'application/json'}; function Http(url, options) { @@ -405,7 +567,7 @@ return /******/ (function(modules) { // webpackBootstrap client = interceptor(i, this.vm)(client); }, this); - promise = extendPromise(client(request).bind(this.vm).then(function (response) { + promise = client(request).bind(this.vm).then(function (response) { response.ok = response.status >= 200 && response.status < 300; return response.ok ? response : Promise.reject(response); @@ -417,55 +579,19 @@ return /******/ (function(modules) { // webpackBootstrap } return Promise.reject(response); - })); + }); if (request.success) { - promise = promise.success(request.success); + promise.success(request.success); } if (request.error) { - promise = promise.error(request.error); + promise.error(request.error); } return promise; } - function extendPromise(promise) { - - promise.success = function (fn) { - - _.warn('The `success` method has been deprecated. Use the `then` method instead.'); - - return extendPromise(promise.then(function (response) { - return fn.call(this, response.data, response.status, response) || response; - })); - - }; - - promise.error = function (fn) { - - _.warn('The `error` method has been deprecated. Use the `catch` method instead.'); - - return extendPromise(promise.then(undefined, function (response) { - return fn.call(this, response.data, response.status, response) || response; - })); - - }; - - promise.always = function (fn) { - - _.warn('The `always` method has been deprecated. Use the `finally` method instead.'); - - var cb = function (response) { - return fn.call(this, response.data, response.status, response) || response; - }; - - return extendPromise(promise.then(cb, cb)); - }; - - return promise; - } - Http.options = { method: 'get', data: '', @@ -481,13 +607,13 @@ return /******/ (function(modules) { // webpackBootstrap }; Http.interceptors = [ - __webpack_require__(9)(_), __webpack_require__(10)(_), __webpack_require__(11)(_), - __webpack_require__(13)(_), + __webpack_require__(12)(_), __webpack_require__(14)(_), __webpack_require__(15)(_), - __webpack_require__(16)(_) + __webpack_require__(16)(_), + __webpack_require__(17)(_) ]; Http.headers = { @@ -523,7 +649,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 4 */ +/* 5 */ /***/ function(module, exports, __webpack_require__) { /** @@ -532,7 +658,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var Promise = window.Promise || __webpack_require__(5)(_); + var Promise = window.Promise || __webpack_require__(6)(_); var Adapter = function (executor) { @@ -542,6 +668,7 @@ return /******/ (function(modules) { // webpackBootstrap this.promise = new Promise(executor); } + this.context = undefined; }; Adapter.all = function (iterable) { @@ -605,12 +732,41 @@ return /******/ (function(modules) { // webpackBootstrap ); }; + p.success = function (callback) { + + _.warn('The `success` method has been deprecated. Use the `then` method instead.'); + + return this.then(function (response) { + return callback.call(this, response.data, response.status, response) || response; + }); + }; + + p.error = function (callback) { + + _.warn('The `error` method has been deprecated. Use the `catch` method instead.'); + + return this.catch(function (response) { + return callback.call(this, response.data, response.status, response) || response; + }); + }; + + p.always = function (callback) { + + _.warn('The `always` method has been deprecated. Use the `finally` method instead.'); + + var cb = function (response) { + return callback.call(this, response.data, response.status, response) || response; + }; + + return this.then(cb, cb); + }; + return Adapter; }; /***/ }, -/* 5 */ +/* 6 */ /***/ function(module, exports) { /** @@ -796,7 +952,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 6 */ +/* 7 */ /***/ function(module, exports, __webpack_require__) { /** @@ -805,7 +961,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var Promise = __webpack_require__(4)(_); + var Promise = __webpack_require__(5)(_); return function (handler, vm) { return function (client) { @@ -849,7 +1005,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 7 */ +/* 8 */ /***/ function(module, exports, __webpack_require__) { /** @@ -858,7 +1014,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var xhrClient = __webpack_require__(8)(_); + var xhrClient = __webpack_require__(9)(_); return function (request) { return (request.client || xhrClient)(request); @@ -868,7 +1024,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 8 */ +/* 9 */ /***/ function(module, exports, __webpack_require__) { /** @@ -877,7 +1033,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var Promise = __webpack_require__(4)(_); + var Promise = __webpack_require__(5)(_); return function (request) { return new Promise(function (resolve) { @@ -968,7 +1124,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 9 */ +/* 10 */ /***/ function(module, exports) { /** @@ -994,7 +1150,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 10 */ +/* 11 */ /***/ function(module, exports) { /** @@ -1034,7 +1190,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 11 */ +/* 12 */ /***/ function(module, exports, __webpack_require__) { /** @@ -1043,7 +1199,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var jsonpClient = __webpack_require__(12)(_); + var jsonpClient = __webpack_require__(13)(_); return { @@ -1062,7 +1218,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 12 */ +/* 13 */ /***/ function(module, exports, __webpack_require__) { /** @@ -1071,7 +1227,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { - var Promise = __webpack_require__(4)(_); + var Promise = __webpack_require__(5)(_); return function (request) { return new Promise(function (resolve) { @@ -1119,7 +1275,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 13 */ +/* 14 */ /***/ function(module, exports) { /** @@ -1146,7 +1302,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 14 */ +/* 15 */ /***/ function(module, exports) { /** @@ -1190,7 +1346,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 15 */ +/* 16 */ /***/ function(module, exports) { /** @@ -1224,7 +1380,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 16 */ +/* 17 */ /***/ function(module, exports, __webpack_require__) { /** @@ -1234,7 +1390,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = function (_) { var originUrl = _.url.parse(location.href); - var xdrClient = __webpack_require__(12)(_); + var xdrClient = __webpack_require__(13)(_); var xhrCors = 'withCredentials' in new XMLHttpRequest(); return { @@ -1270,7 +1426,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 17 */ +/* 18 */ /***/ function(module, exports) { /** diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index c75553c8..8fcabc61 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -1,7 +1,7 @@ /** - * vue-resource v0.2.0 + * vue-resource v0.5.0 * https://github.com/vuejs/vue-resource * Released under the MIT License. */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.VueResource=e():t.VueResource=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){function r(t){var e=n(1)(t);t.url=n(2)(e),t.http=n(3)(e),t.resource=n(17)(e),t.promise=n(4)(e),Object.defineProperties(t.prototype,{$url:{get:function(){return e.options(t.url,this,this.$options.url)}},$http:{get:function(){return e.options(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}}})}window.Vue&&Vue.use(r),t.exports=r},function(t,e){t.exports=function(t){function e(t,r,o){for(var i in r)o&&(n.isPlainObject(r[i])||n.isArray(r[i]))?(n.isPlainObject(r[i])&&!n.isPlainObject(t[i])&&(t[i]={}),n.isArray(r[i])&&!n.isArray(t[i])&&(t[i]=[]),e(t[i],r[i],o)):void 0!==r[i]&&(t[i]=r[i])}var n=t.util.extend({},t.util),r=t.config,o=window.console;return n.warn=function(e){o&&t.util.warn&&(!r.silent||r.debug)&&o.warn("[VueResource warn]: "+e)},n.error=function(t){o&&o.error(t)},n.trim=function(t){return t.replace(/^\s*|\s*$/g,"")},n.toLower=function(t){return t?t.toLowerCase():""},n.isString=function(t){return"string"==typeof t},n.isFunction=function(t){return"function"==typeof t},n.options=function(t,e,r){return r=r||{},n.isFunction(r)&&(r=r.call(e)),n.extend(t.bind({vm:e,options:r}),t,{options:r})},n.each=function(t,e){var r,o;if("number"==typeof t.length)for(r=0;r=200&&t.status<300,t.ok?t:o.reject(t)},function(e){return e instanceof Error&&t.error(e),o.reject(e)})),c.success&&(a=a.success(c.success)),c.error&&(a=a.error(c.error)),a}function r(e){return e.success=function(n){return t.warn("The `success` method has been deprecated. Use the `then` method instead."),r(e.then(function(t){return n.call(this,t.data,t.status,t)||t}))},e.error=function(n){return t.warn("The `error` method has been deprecated. Use the `catch` method instead."),r(e.then(void 0,function(t){return n.call(this,t.data,t.status,t)||t}))},e.always=function(n){t.warn("The `always` method has been deprecated. Use the `finally` method instead.");var o=function(t){return n.call(this,t.data,t.status,t)||t};return r(e.then(o,o))},e}var o=n(4)(t),i=n(6)(t),u=n(7)(t),s={"Content-Type":"application/json"};return e.options={method:"get",data:"",params:{},headers:{},xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(9)(t),n(10)(t),n(11)(t),n(13)(t),n(14)(t),n(15)(t),n(16)(t)],e.headers={put:s,post:s,patch:s,"delete":s,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),t.isObject(o)&&(i=o,o=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e,n){t.exports=function(t){var e=window.Promise||n(5)(t),r=function(t){t instanceof e?this.promise=t:this.promise=new e(t)};r.all=function(t){return new r(e.all(t))},r.resolve=function(t){return new r(e.resolve(t))},r.reject=function(t){return new r(e.reject(t))},r.race=function(t){return new r(e.race(t))};var o=r.prototype;return o.bind=function(t){return this.context=t,this},o.then=function(t,e){return t&&t.bind&&this.context&&(t=t.bind(this.context)),e&&e.bind&&this.context&&(e=e.bind(this.context)),this.promise=this.promise.then(t,e),this},o["catch"]=function(t){return t&&t.bind&&this.context&&(t=t.bind(this.context)),this.promise=this.promise["catch"](t),this},o["finally"]=function(t){return this.then(function(e){return t.call(this),e},function(n){return t.call(this),e.reject(n)})},r}},function(t,e){t.exports=function(t){function e(t){this.state=o,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var n=0,r=1,o=2;e.reject=function(t){return new e(function(e,n){n(t)})},e.resolve=function(t){return new e(function(e,n){e(t)})},e.all=function(t){return new e(function(n,r){function o(e){return function(r){u[e]=r,i+=1,i===t.length&&n(u)}}var i=0,u=[];0===t.length&&n(u);for(var s=0;s=200&&t.status<300,t.ok?t:r.reject(t)},function(e){return e instanceof Error&&t.error(e),r.reject(e)}),u.success&&a.success(u.success),u.error&&a.error(u.error),a}var r=n(5)(t),o=n(7)(t),i=n(8)(t),s={"Content-Type":"application/json"};return e.options={method:"get",data:"",params:{},headers:{},xhr:null,jsonp:"callback",beforeSend:null,crossOrigin:null,emulateHTTP:!1,emulateJSON:!1,timeout:0},e.interceptors=[n(10)(t),n(11)(t),n(12)(t),n(14)(t),n(15)(t),n(16)(t),n(17)(t)],e.headers={put:s,post:s,patch:s,"delete":s,common:{Accept:"application/json, text/plain, */*"},custom:{"X-Requested-With":"XMLHttpRequest"}},["get","put","post","patch","delete","jsonp"].forEach(function(n){e[n]=function(e,r,o,i){return t.isFunction(r)&&(i=o,o=r,r=void 0),t.isObject(o)&&(i=o,o=void 0),this(e,t.extend({method:n,data:r,success:o},i))}}),t.http=e}},function(t,e,n){t.exports=function(t){var e=window.Promise||n(6)(t),r=function(t){t instanceof e?this.promise=t:this.promise=new e(t),this.context=void 0};r.all=function(t){return new r(e.all(t))},r.resolve=function(t){return new r(e.resolve(t))},r.reject=function(t){return new r(e.reject(t))},r.race=function(t){return new r(e.race(t))};var o=r.prototype;return o.bind=function(t){return this.context=t,this},o.then=function(t,e){return t&&t.bind&&this.context&&(t=t.bind(this.context)),e&&e.bind&&this.context&&(e=e.bind(this.context)),this.promise=this.promise.then(t,e),this},o["catch"]=function(t){return t&&t.bind&&this.context&&(t=t.bind(this.context)),this.promise=this.promise["catch"](t),this},o["finally"]=function(t){return this.then(function(e){return t.call(this),e},function(n){return t.call(this),e.reject(n)})},o.success=function(e){return t.warn("The `success` method has been deprecated. Use the `then` method instead."),this.then(function(t){return e.call(this,t.data,t.status,t)||t})},o.error=function(e){return t.warn("The `error` method has been deprecated. Use the `catch` method instead."),this["catch"](function(t){return e.call(this,t.data,t.status,t)||t})},o.always=function(e){t.warn("The `always` method has been deprecated. Use the `finally` method instead.");var n=function(t){return e.call(this,t.data,t.status,t)||t};return this.then(n,n)},r}},function(t,e){t.exports=function(t){function e(t){this.state=o,this.value=void 0,this.deferred=[];var e=this;try{t(function(t){e.resolve(t)},function(t){e.reject(t)})}catch(n){e.reject(n)}}var n=0,r=1,o=2;e.reject=function(t){return new e(function(e,n){n(t)})},e.resolve=function(t){return new e(function(e,n){e(t)})},e.all=function(t){return new e(function(n,r){function o(e){return function(r){s[e]=r,i+=1,i===t.length&&n(s)}}var i=0,s=[];0===t.length&&n(s);for(var u=0;u