1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | const http = require('http');
|
12 | const https = require('https');
|
13 | const querystring = require('querystring');
|
14 | const { URL } = require('url');
|
15 |
|
16 | const ResponseType = Object.freeze({
|
17 | ArrayBuffer: Symbol('arraybuffer'),
|
18 | JSON: Symbol('json'),
|
19 | Text: Symbol('text'),
|
20 | Stream: Symbol('stream'),
|
21 | });
|
22 |
|
23 | const request = async (opts) => {
|
24 | const qs = querystring.encode(opts.qs);
|
25 | const completeUrl = new URL(opts.uri + (qs.length ? `?${qs}` : ''));
|
26 |
|
27 | const reqOpts = {
|
28 | method: opts.method,
|
29 | host: completeUrl.hostname,
|
30 | port: completeUrl.port,
|
31 | path: completeUrl.pathname + completeUrl.search + completeUrl.hash,
|
32 | headers: opts.headers,
|
33 | agent: opts.agent,
|
34 | };
|
35 |
|
36 | let responseType;
|
37 | if (opts.responseType) {
|
38 | responseType = opts.responseType;
|
39 | } else {
|
40 | responseType = ResponseType.JSON;
|
41 | }
|
42 |
|
43 | if (opts.body) {
|
44 | reqOpts.headers['content-length'] = Buffer.byteLength(opts.body);
|
45 | }
|
46 |
|
47 | const adapter = (completeUrl.protocol === 'https:') ? https : http;
|
48 |
|
49 | return new Promise((resolve, reject) => {
|
50 | const req = adapter.request(reqOpts, (res) => {
|
51 | if (responseType === ResponseType.Stream) {
|
52 | return resolve({
|
53 | statusCode: res.statusCode,
|
54 | headers: res.headers,
|
55 | data: res,
|
56 | });
|
57 | }
|
58 | const data = [];
|
59 | res.on('data', (chunk) => data.push(chunk));
|
60 | res.on('end', () => {
|
61 | let result = Buffer.concat(data);
|
62 | if (responseType === ResponseType.Text || !result.length) {
|
63 | result = result.toString();
|
64 | } else if (responseType === ResponseType.JSON) {
|
65 | const contentType = res.headers['content-type'];
|
66 | if (!/^application\/json/.test(contentType)) {
|
67 | return reject(new Error('Invalid content-type. ' +
|
68 | `Expected application/json but received ${contentType}`));
|
69 | }
|
70 | result = JSON.parse(result);
|
71 | }
|
72 | resolve({
|
73 | statusCode: res.statusCode,
|
74 | headers: res.headers,
|
75 | data: result,
|
76 | });
|
77 | });
|
78 | });
|
79 |
|
80 | req.on('error', reject);
|
81 |
|
82 | if (opts.body) {
|
83 | req.write(opts.body);
|
84 | }
|
85 | req.end();
|
86 | });
|
87 | };
|
88 |
|
89 | request.responseType = ResponseType;
|
90 |
|
91 | module.exports = request;
|