UNPKG

12.3 kBHTMLView Raw
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="utf-8">
5 <title>client.js - Documentation</title>
6
7 <script src="scripts/prettify/prettify.js"></script>
8 <script src="scripts/prettify/lang-css.js"></script>
9 <!--[if lt IE 9]>
10 <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11 <![endif]-->
12 <link type="text/css" rel="stylesheet" href="styles/prettify.css">
13 <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
14 <meta name="viewport" content="width=device-width, initial-scale=1.0">
15</head>
16<body>
17
18<input type="checkbox" id="nav-trigger" class="nav-trigger" />
19<label for="nav-trigger" class="navicon-button x">
20 <div class="navicon"></div>
21</label>
22
23<label for="nav-trigger" class="overlay"></label>
24
25<nav>
26 <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="HttpTransportBuilder.html">HttpTransportBuilder</a><ul class='methods'><li data-type='method'><a href="HttpTransportBuilder.html#createClient">createClient</a></li><li data-type='method'><a href="HttpTransportBuilder.html#retries">retries</a></li><li data-type='method'><a href="HttpTransportBuilder.html#retryDelay">retryDelay</a></li><li data-type='method'><a href="HttpTransportBuilder.html#use">use</a></li><li data-type='method'><a href="HttpTransportBuilder.html#userAgent">userAgent</a></li></ul></li><li><a href="HttpTransportClient.html">HttpTransportClient</a><ul class='methods'><li data-type='method'><a href="HttpTransportClient.html#asBody">asBody</a></li><li data-type='method'><a href="HttpTransportClient.html#asResponse">asResponse</a></li><li data-type='method'><a href="HttpTransportClient.html#delete">delete</a></li><li data-type='method'><a href="HttpTransportClient.html#get">get</a></li><li data-type='method'><a href="HttpTransportClient.html#head">head</a></li><li data-type='method'><a href="HttpTransportClient.html#headers">headers</a></li><li data-type='method'><a href="HttpTransportClient.html#patch">patch</a></li><li data-type='method'><a href="HttpTransportClient.html#post">post</a></li><li data-type='method'><a href="HttpTransportClient.html#put">put</a></li><li data-type='method'><a href="HttpTransportClient.html#query">query</a></li><li data-type='method'><a href="HttpTransportClient.html#retry">retry</a></li><li data-type='method'><a href="HttpTransportClient.html#retryDelay">retryDelay</a></li><li data-type='method'><a href="HttpTransportClient.html#timeout">timeout</a></li><li data-type='method'><a href="HttpTransportClient.html#use">use</a></li></ul></li></ul>
27</nav>
28
29<div id="main">
30
31 <h1 class="page-title">client.js</h1>
32
33
34
35
36
37
38
39 <section>
40 <article>
41 <pre class="prettyprint source linenums"><code>'use strict';
42
43const compose = require('koa-compose');
44const context = require('./context');
45const rejectedPromise = require('./rejectedPromise');
46const bind = require('./bind');
47
48/** Core client */
49class HttpTransportClient {
50 /**
51 * Create a HttpTransport.
52 * @param {Transport} transport - Transport instance.
53 * @param {object} defaults - default configuration
54 */
55 constructor(transport, defaults) {
56 this._transport = transport;
57 this._instancePlugins = defaults.plugins || [];
58 this._defaults = defaults;
59 this._initContext();
60 bind(this);
61 }
62
63 /**
64 * Registers a per request plugin
65 *
66 * @return a HttpTransport instance
67 * @param {function} fn - per request plugin
68 * @example
69 * const toError = require('@bbc/http-transport-to-error');
70 * const httpTransport = require('@bbc/http-transport');
71 *
72 * httpTransport.createClient()
73 * .use(toError(404));
74 */
75 use(plugin) {
76 validatePlugin(plugin);
77 this._ctx.addPlugin(plugin);
78 return this;
79 }
80
81 /**
82 * Make a HTTP GET request
83 *
84 * @param {string} baseUrl
85 * @return a HttpTransport instance
86 * @example
87 * const httpTransport = require('@bbc/http-transport');
88 *
89 * const response = await httpTransport.createClient()
90 * .get(url)
91 * .asResponse();
92 */
93 get(baseUrl) {
94 this._ctx.req.method('GET').baseUrl(baseUrl);
95 return this;
96 }
97
98 /**
99 * Make a HTTP POST request
100 *
101 * @param {string} baseUrl
102 * @param {object} request body
103 * @return a HttpTransport instance
104 * @example
105 * const httpTransport = require('@bbc/http-transport');
106 *
107 * const response = await httpTransport.createClient()
108 * .post(baseUrl, requestBody)
109 * .asResponse();
110 */
111 post(baseUrl, body) {
112 this._ctx.req
113 .method('POST')
114 .body(body)
115 .baseUrl(baseUrl);
116 return this;
117 }
118
119 /**
120 * Make a HTTP PUT request
121 *
122 * @param {string} baseUrl
123 * @param {object} request body
124 * @return a HttpTransport instance
125 * @example
126 * const httpTransport = require('@bbc/http-transport');
127 *
128 * const response = await httpTransport.createClient()
129 * .put(baseUrl, requestBody)
130 * .asResponse();
131 */
132 put(baseUrl, body) {
133 this._ctx.req
134 .method('PUT')
135 .body(body)
136 .baseUrl(baseUrl);
137 return this;
138 }
139
140 /**
141 * Make a HTTP DELETE request
142 *
143 * @param {string} baseUrl
144 * @return a HttpTransport instance
145 * @example
146 * const httpTransport = require('@bbc/http-transport');
147 *
148 * const response = await httpTransport.createClient()
149 * .delete(baseUrl)
150 * .asResponse();
151 */
152 delete(baseUrl) {
153 this._ctx.req.method('DELETE').baseUrl(baseUrl);
154 return this;
155 }
156
157 /**
158 * Make a HTTP PATCH request
159 *
160 * @param {string} baseUrl
161 * @param {object} request body
162 * @return a HttpTransport instance
163 * @example
164 * const httpTransport = require('@bbc/http-transport');
165 *
166 * const response = await httpTransport.createClient()
167 * .put(baseUrl, requestBody)
168 * .asResponse();
169 */
170 patch(baseUrl, body) {
171 this._ctx.req
172 .method('PATCH')
173 .body(body)
174 .baseUrl(baseUrl);
175 return this;
176 }
177
178 /**
179 * Make a HTTP HEAD request
180 *
181 * @param {string} baseUrl
182 * @return a HttpTransport instance
183 * @example
184 * const httpTransport = require('@bbc/http-transport');
185 *
186 * const response = await httpTransport.createClient()
187 * .head(baseUrl)
188 * .asResponse();
189 */
190 head(baseUrl) {
191 this._ctx.req.method('HEAD').baseUrl(baseUrl);
192 return this;
193 }
194
195 /**
196 * Sets the request headers
197 *
198 * @param {string|object} name - header name or headers object
199 * @param {string|object} value - header value
200 * @return a HttpTransport instance
201 * @example
202 * const httpTransport = require('@bbc/http-transport');
203 *
204 * const response = await httpTransport.createClient()
205 * .headers({
206 * 'User-Agent' : 'someUserAgent'
207 * })
208 * .asResponse();
209 */
210 headers() {
211 const args = normalise(arguments);
212 Object.keys(args).forEach((key) => {
213 this._ctx.req.addHeader(key, args[key]);
214 });
215 return this;
216 }
217
218 /**
219 * Sets the query strings
220 *
221 * @param {string|object} name - query name or query object
222 * @param {string|object} value - query value
223 * @return a HttpTransport instance
224 * @example
225 * const httpTransport = require('@bbc/http-transport');
226 *
227 * const response = await httpTransport.createClient()
228 * .query({
229 * 'perPage' : 1
230 * })
231 * .asResponse();
232 */
233 query() {
234 const args = normalise(arguments);
235 Object.keys(args).forEach((key) => {
236 this._ctx.req.addQuery(key, args[key]);
237 });
238 return this;
239 }
240
241 /**
242 * Sets a request timeout
243 *
244 * @param {integer} time - timeout in seconds
245 * @return a HttpTransport instance
246 * @example
247 * const httpTransport = require('@bbc/http-transport');
248 *
249 * const response = await httpTransport.createClient()
250 * .timeout(1)
251 * .asResponse();
252 */
253 timeout(time) {
254 this._ctx.req.timeout(time);
255 return this;
256 }
257
258 /**
259 * Set the number of retries on failure for the request
260 *
261 * @param {integer} retries - number of times to retry a failed request
262 * @return a HttpTransport instance
263 * @example
264 * const httpTransport = require('@bbc/http-transport');
265 *
266 * const response = await httpTransport.createClient()
267 * .retry(5) // for this request only
268 * .asResponse();
269 */
270 retry(retries) {
271 this._ctx.retries = retries;
272 return this;
273 }
274
275 /**
276 * Set the delay between retries in ms
277 *
278 * @param {integer} delay - number of ms to wait between retries (default: 100)
279 * @return a HttpTransport instance
280 * @example
281 * const httpTransport = require('@bbc/http-transport');
282 *
283 * const response = await httpTransport.createClient()
284 * .retry(2)
285 * .retryDelay(200)
286 * .asResponse();
287 */
288 retryDelay(delay) {
289 this._ctx.retryDelay = delay;
290 return this;
291 }
292
293 /**
294 * Initiates the request, returning the response body, if successful.
295 *
296 * @return a Promise. If the Promise fulfils,
297 * the fulfilment value is the response body. The body type defaults to string.
298 * If the content-type response header contains 'json'
299 * or the json: true option has been set on transport layer
300 * then the body type will be json.
301 *
302 * @example
303 * const httpTransport = require('@bbc/http-transport');
304 *
305 * const body = await httpTransport.createClient()
306 * .asBody();
307 *
308 * console.log(body);
309 */
310 async asBody() {
311 const res = await this.asResponse();
312 return res.body;
313 }
314
315 /**
316 * Initiates the request, returning a http transport response object, if successful.
317 *
318 * @return a Promise. If the Promise fulfils,
319 * the fulfilment value is response object.
320 * @example
321 * const httpTransport = require('@bbc/http-transport');
322 *
323 * const response = await httpTransport.createClient()
324 * .asResponse()
325 *
326 * console.log(response);
327 *
328 */
329 async asResponse() {
330 const currentContext = this._ctx;
331 this._initContext();
332
333 const ctx = await retry(this._executeRequest, currentContext);
334 return ctx.res;
335 }
336
337 _getPlugins(ctx) {
338 return this._instancePlugins.concat(ctx.plugins);
339 }
340
341 _applyPlugins(ctx, next) {
342 const fn = compose(this._getPlugins(ctx));
343 return fn(ctx, next);
344 }
345
346 async _executeRequest(ctx) {
347 await this._applyPlugins(ctx, this._handleRequest);
348 return ctx;
349 }
350
351 async _handleRequest(ctx, next) {
352 await this._transport.execute(ctx);
353 return next();
354 }
355
356 _initContext() {
357 this._ctx = context.create(this._defaults);
358 this.headers('User-Agent', this._ctx.userAgent);
359 }
360}
361
362function isCriticalError(err) {
363 if (err &amp;&amp; err.statusCode &lt; 500) {
364 return false;
365 }
366 return true;
367}
368
369function toRetry(err) {
370 return {
371 reason: err.message,
372 statusCode: err.statusCode
373 };
374}
375
376function retry(fn, ctx) {
377 ctx.retryAttempts = [];
378 const maxAttempts = ctx.retries;
379
380 function attempt(i) {
381 return fn(ctx)
382 .catch((err) => {
383 if (maxAttempts > 0) {
384 const delayBy = rejectedPromise(ctx.retryDelay);
385 return delayBy(err);
386 }
387 throw err;
388 })
389 .catch((err) => {
390 if (i &lt; maxAttempts &amp;&amp; isCriticalError(err)) {
391 ctx.retryAttempts.push(toRetry(err));
392 return attempt(++i);
393 }
394 throw err;
395 });
396 }
397 return attempt(0);
398}
399
400function toObject(arr) {
401 const obj = {};
402 for (let i = 0; i &lt; arr.length; i += 2) {
403 obj[arr[i]] = arr[i + 1];
404 }
405 return obj;
406}
407
408function isObject(value) {
409 return value !== null &amp;&amp; typeof value === 'object';
410}
411
412function normalise(args) {
413 args = Array.from(args);
414 if (isObject(args[0])) {
415 return args[0];
416 }
417 return toObject(args);
418}
419
420function validatePlugin(plugin) {
421 if (typeof plugin !== 'function') throw new TypeError('Plugin is not a function');
422}
423
424module.exports = HttpTransportClient;
425</code></pre>
426 </article>
427 </section>
428
429
430
431
432</div>
433
434<br class="clear">
435
436<footer>
437 Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.11</a> on Fri Sep 22 2023 15:20:00 GMT+0100 (British Summer Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
438</footer>
439
440<script>prettyPrint();</script>
441<script src="scripts/linenumber.js"></script>
442</body>
443</html>