UNPKG

6.42 kBJavaScriptView Raw
1var merge = require('./merge')
2var resolveUrl = require('./resolveUrl')
3
4function client (url, options, middleware) {
5 var args = parseClientArguments(url, options, middleware)
6 return new Httpism(args.url, args.options || {}, args.middleware)
7}
8
9function Httpism (url, options, middleware) {
10 this.url = url
11 this._options = options
12 this.middleware = middleware
13}
14
15Httpism.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
20Httpism.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
61function 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
105function 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
117function 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
132function insertMiddlewareIntoIndex (middleware, m, index) {
133 middleware.splice(index, 0, m)
134}
135
136Httpism.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
154Httpism.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
159Httpism.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
164Httpism.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
186Httpism.prototype.removeMiddleware = function (name) {
187 console.warn('httpism.removeMiddleware() is deprecated please use httpism.remove()')
188 this.remove(name)
189}
190
191Httpism.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
198function addMethod (method) {
199 Httpism.prototype[method] = function (url, options) {
200 return this.request(method, url, undefined, options)
201 }
202}
203
204function addMethodWithBody (method) {
205 Httpism.prototype[method] = function (url, body, options) {
206 return this.request(method, url, body, options)
207 }
208}
209
210addMethod('get')
211addMethod('delete')
212addMethod('head')
213addMethodWithBody('post')
214addMethodWithBody('put')
215addMethodWithBody('patch')
216addMethodWithBody('options')
217
218function 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
242function 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
248module.exports = client