1 | var merge = require('./merge')
|
2 | var resolveUrl = require('./resolveUrl')
|
3 |
|
4 | function client (url, options, middleware) {
|
5 | var args = parseClientArguments(url, options, middleware)
|
6 | return new Httpism(args.url, args.options || {}, args.middleware)
|
7 | }
|
8 |
|
9 | function Httpism (url, options, middleware) {
|
10 | this.url = url
|
11 | this._options = options
|
12 | this.middleware = middleware
|
13 | }
|
14 |
|
15 | Httpism.prototype.send = function (method, url, body, _options) {
|
16 | console.warn('httpism.send() is deprecated please use httpism.request()')
|
17 | return this.request.apply(this, arguments)
|
18 | }
|
19 |
|
20 | Httpism.prototype.request = function (method, url, body, _options) {
|
21 | var request
|
22 |
|
23 | if (method instanceof Object) {
|
24 | request = method
|
25 | } else {
|
26 | var options = mergeClientOptions(_options, this._options)
|
27 | request = {
|
28 | method: method,
|
29 | url: resolveUrl(this.url, url),
|
30 | headers: lowerCaseHeaders(options.headers || {}),
|
31 | body: body,
|
32 | options: options
|
33 | }
|
34 | }
|
35 |
|
36 | var self = this
|
37 |
|
38 | function sendToMiddleware (index, req) {
|
39 | if (index < self.middleware.length) {
|
40 | var middleware = self.middleware[index]
|
41 | return middleware(req, function (nextRequest) { return sendToMiddleware(index + 1, nextRequest || req) }, self)
|
42 | }
|
43 | }
|
44 |
|
45 | return sendToMiddleware(0, request).then(function (response) {
|
46 | if (request.options.response === true) {
|
47 | return response
|
48 | } else {
|
49 | responseCompatibility(response)
|
50 | return response.body
|
51 | }
|
52 | }, function (e) {
|
53 | if (e.redirectResponse) {
|
54 | return e.redirectResponse
|
55 | } else {
|
56 | throw e
|
57 | }
|
58 | })
|
59 | }
|
60 |
|
61 | function responseCompatibility (response) {
|
62 | function responseWarning () {
|
63 | console.warn('httpism >= 3.0.0 returns the response body by default, please pass the {response: true} option if you want the whole response')
|
64 | }
|
65 |
|
66 | if (response.body instanceof Object) {
|
67 | if (response.body && !response.body.hasOwnProperty('body')) {
|
68 | Object.defineProperty(response.body, 'body', {
|
69 | get: function () {
|
70 | responseWarning()
|
71 | return this
|
72 | }
|
73 | })
|
74 | }
|
75 |
|
76 | if (response.body && !response.body.hasOwnProperty('url')) {
|
77 | Object.defineProperty(response.body, 'url', {
|
78 | get: function () {
|
79 | responseWarning()
|
80 | return response.url
|
81 | }
|
82 | })
|
83 | }
|
84 |
|
85 | if (response.body && !response.body.hasOwnProperty('statusCode')) {
|
86 | Object.defineProperty(response.body, 'statusCode', {
|
87 | get: function () {
|
88 | responseWarning()
|
89 | return response.statusCode
|
90 | }
|
91 | })
|
92 | }
|
93 |
|
94 | if (response.body && !response.body.hasOwnProperty('headers')) {
|
95 | Object.defineProperty(response.body, 'headers', {
|
96 | get: function () {
|
97 | responseWarning()
|
98 | return response.headers
|
99 | }
|
100 | })
|
101 | }
|
102 | }
|
103 | }
|
104 |
|
105 | function lowerCaseHeaders (headers) {
|
106 | Object.keys(headers).forEach(function (key) {
|
107 | var lower = key.toLowerCase()
|
108 | if (key.toLowerCase() !== key) {
|
109 | headers[lower] = headers[key]
|
110 | delete headers[key]
|
111 | }
|
112 | })
|
113 |
|
114 | return headers
|
115 | }
|
116 |
|
117 | function findMiddlewareIndexes (names, middleware) {
|
118 | return names.map(function (name) {
|
119 | for (var n = 0; n < middleware.length; n++) {
|
120 | var m = middleware[n]
|
121 | if (m.httpismMiddleware && m.httpismMiddleware.name === name) {
|
122 | return n
|
123 | }
|
124 | }
|
125 |
|
126 | return -1
|
127 | }).filter(function (i) {
|
128 | return i >= 0
|
129 | })
|
130 | }
|
131 |
|
132 | function insertMiddlewareIntoIndex (middleware, m, index) {
|
133 | middleware.splice(index, 0, m)
|
134 | }
|
135 |
|
136 | Httpism.prototype.client = function (url, options, middleware) {
|
137 | var args = parseClientArguments(url, options, middleware)
|
138 |
|
139 | var client = new Httpism(
|
140 | resolveUrl(this.url, args.url),
|
141 | mergeClientOptions(args.options, this._options),
|
142 | this.middleware.slice()
|
143 | )
|
144 |
|
145 | if (args.middleware) {
|
146 | args.middleware.forEach(function (m) {
|
147 | client.use(m)
|
148 | })
|
149 | }
|
150 |
|
151 | return client
|
152 | }
|
153 |
|
154 | Httpism.prototype.api = function (url, options, middleware) {
|
155 | console.warn('httpism >= 3.0.0 renamed httpism.api() to httpism.client(), please update your usage')
|
156 | return this.client(url, options, middleware)
|
157 | }
|
158 |
|
159 | Httpism.prototype.insertMiddleware = function (m) {
|
160 | console.warn('httpism >= 3.0.0 renamed httpism.insertMiddleware() to httpism.use(), please update your usage')
|
161 | return this.use(m)
|
162 | }
|
163 |
|
164 | Httpism.prototype.use = function (m) {
|
165 | var meta = m.httpismMiddleware
|
166 |
|
167 | if (meta && (meta.before || meta.after)) {
|
168 | var position = meta.before || meta.after
|
169 | var names = typeof position === 'string' ? [position] : position
|
170 | var indexes = findMiddlewareIndexes(names, this.middleware)
|
171 | if (indexes.length) {
|
172 | var index = meta.before ? Math.min.apply(Math, indexes) : Math.max.apply(Math, indexes) + 1
|
173 |
|
174 | if (index >= 0) {
|
175 | insertMiddlewareIntoIndex(this.middleware, m, index)
|
176 | return
|
177 | }
|
178 | }
|
179 |
|
180 | throw new Error('no such middleware: ' + (meta.before || meta.after))
|
181 | } else {
|
182 | this.middleware.unshift(m)
|
183 | }
|
184 | }
|
185 |
|
186 | Httpism.prototype.removeMiddleware = function (name) {
|
187 | console.warn('httpism.removeMiddleware() is deprecated please use httpism.remove()')
|
188 | this.remove(name)
|
189 | }
|
190 |
|
191 | Httpism.prototype.remove = function (name) {
|
192 | var indexes = findMiddlewareIndexes([name], this.middleware)
|
193 | for (var i = indexes.length - 1; i >= 0; i--) {
|
194 | this.middleware.splice(indexes[i], 1)
|
195 | }
|
196 | }
|
197 |
|
198 | function addMethod (method) {
|
199 | Httpism.prototype[method] = function (url, options) {
|
200 | return this.request(method, url, undefined, options)
|
201 | }
|
202 | }
|
203 |
|
204 | function addMethodWithBody (method) {
|
205 | Httpism.prototype[method] = function (url, body, options) {
|
206 | return this.request(method, url, body, options)
|
207 | }
|
208 | }
|
209 |
|
210 | addMethod('get')
|
211 | addMethod('delete')
|
212 | addMethod('head')
|
213 | addMethodWithBody('post')
|
214 | addMethodWithBody('put')
|
215 | addMethodWithBody('patch')
|
216 | addMethodWithBody('options')
|
217 |
|
218 | function parseClientArguments () {
|
219 | var url, options, middleware
|
220 |
|
221 | for (var n = 0; n < arguments.length; n++) {
|
222 | var arg = arguments[n]
|
223 |
|
224 | if (typeof arg === 'string') {
|
225 | url = arg
|
226 | } else if (typeof arg === 'function') {
|
227 | middleware = [arg]
|
228 | } else if (arg instanceof Array) {
|
229 | middleware = arg
|
230 | } else if (arg instanceof Object) {
|
231 | options = arg
|
232 | }
|
233 | }
|
234 |
|
235 | return {
|
236 | url: url,
|
237 | options: options,
|
238 | middleware: middleware
|
239 | }
|
240 | }
|
241 |
|
242 | function mergeClientOptions (x, y) {
|
243 | var z = merge(x, y)
|
244 | if (z && z.headers) { z.headers = merge(x && x.headers, y && y.headers) }
|
245 | return z
|
246 | }
|
247 |
|
248 | module.exports = client
|