UNPKG

4.97 kBJavaScriptView Raw
1/*
2 * Copyright (c) 2012 VMware, Inc. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 * IN THE SOFTWARE.
21 */
22
23(function (define) {
24 'use strict';
25
26 define(function (require) {
27
28 var defaultClient, when;
29
30 defaultClient = require('../rest');
31 when = require('when');
32
33 /**
34 * Interceptors have the ability to intercept the request and/org response
35 * objects. They may augment, prune, transform or replace the
36 * request/response as needed. Clients may be composed by chaining
37 * together multiple interceptors.
38 *
39 * Configured interceptors are functional in nature. Wrapping a client in
40 * an interceptor will not affect the client, merely the data that flows in
41 * and out of that client. A common configuration can be created once and
42 * shared; specialization can be created by further wrapping that client
43 * with custom interceptors.
44 *
45 * @param {Client} [client] client to wrap
46 * @param {Object} [config] configuration for the interceptor, properties will be specific to the interceptor implementation
47 * @returns {Client} A client wrapped with the interceptor
48 *
49 * @class Interceptor
50 */
51
52 function defaultRequestHandler(request /*, config */) {
53 return request;
54 }
55
56 function defaultResponseHandler(response /*, config, interceptor */) {
57 return response;
58 }
59
60 function whenFirst(promisesOrValues) {
61 // TODO this concept is likely to be added to when in the near future
62 var d = when.defer();
63 promisesOrValues.forEach(function (promiseOrValue) {
64 when.chain(promiseOrValue, d.resolver);
65 });
66 return d.promise;
67 }
68
69 /**
70 * Create a new interceptor for the provided handlers.
71 *
72 * @param {Function} [handlers.request] request handler
73 * @param {Function} [handlers.response] response handler regardless of error state
74 * @param {Function} [handlers.success] response handler when the request is not in error
75 * @param {Function} [handlers.error] response handler when the request is in error, may be used to 'unreject' an error state
76 * @param {Function} [handlers.client] the client to use if otherwise not specified, defaults to platform default client
77 *
78 * @returns {Interceptor}
79 */
80 return function (handlers) {
81
82 var requestHandler, successResponseHandler, errorResponseHandler;
83
84 handlers = handlers || {};
85
86 requestHandler = handlers.request || defaultRequestHandler;
87 successResponseHandler = handlers.success || handlers.response || defaultResponseHandler;
88 errorResponseHandler   = handlers.error   || function () {
89 // Propagate the rejection, with the result of the handler
90 return when.reject((handlers.response || defaultResponseHandler).apply(this, arguments));
91 };
92
93 return function (client, config) {
94 var interceptor;
95
96 if (typeof client === 'object') {
97 config = client;
98 }
99 if (typeof client !== 'function') {
100 client = handlers.client || defaultClient;
101 }
102 config = config || {};
103
104 interceptor = function (request) {
105 request = request || {};
106 return when(requestHandler(request, config)).then(function (request) {
107 var response, abort;
108 if (request instanceof Array) {
109 // unpack compound value
110 abort = request[1];
111 request = request[0];
112 }
113 response = when(request, function (request) {
114 return when(
115 client(request),
116 function (response) {
117 return successResponseHandler(response, config, interceptor);
118 },
119 function (response) {
120 return errorResponseHandler(response, config, interceptor);
121 }
122 );
123 });
124 return abort ? whenFirst([response, abort]) : response;
125 });
126 };
127 interceptor.skip = function () {
128 return client;
129 };
130
131 return interceptor;
132 };
133 };
134
135 });
136
137}(
138 typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); }
139 // Boilerplate for AMD and Node
140));