caccl-send-request 1.0.14 → 2.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,12 +8,6 @@ The default request sender used throughout the CACCL project.
8
8
  **C**onnection
9
9
  **L**ibrary
10
10
 
11
- ## Overriding caccl-send-request
12
-
13
- Throughout the `caccl` project, the default sendRequest function is this `caccl-send-request` module.
14
-
15
- However, if you want to override the sendRequest function, just create your own function that follows the description below. Your function should follow our description _exactly_, including sending of cross-origin credentials.
16
-
17
11
  ## Description
18
12
 
19
13
  Sends an http request, handles paging, retries failed requests, and processes the response.
@@ -28,7 +22,7 @@ headers | object | headers to include in the request | {}
28
22
  numRetries | number | number of times to retry the request if it fails | 0
29
23
  ignoreSSLIssues | boolean | if true, ignores self-signed certificate issues | false usually, true if host is `localhost:8088`
30
24
 
31
- Returns:
25
+ Returns:
32
26
  `Promise.<CACCLError|object>` Returns promise that resolves with `{ body, status, headers }` on success, rejects with CACCLError (see `caccl-error` on npm) on failure.
33
27
 
34
- **Note:** This function sends cross-origin credentials if `process.env.DEV` is true or if `process.env.NODE_ENV` equals `development`.
28
+ **Note:** This function sends cross-origin credentials if `process.env.NODE_ENV` equals `development`.
@@ -0,0 +1,5 @@
1
+ declare enum ErrorCode {
2
+ NotConnected = "CSR1",
3
+ SelfSigned = "CSR2"
4
+ }
5
+ export default ErrorCode;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ // Highest error code: CSR2
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ var ErrorCode;
5
+ (function (ErrorCode) {
6
+ ErrorCode["NotConnected"] = "CSR1";
7
+ ErrorCode["SelfSigned"] = "CSR2";
8
+ })(ErrorCode || (ErrorCode = {}));
9
+ ;
10
+ exports.default = ErrorCode;
11
+ //# sourceMappingURL=ErrorCode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorCode.js","sourceRoot":"","sources":["../src/ErrorCode.ts"],"names":[],"mappings":";AAAA,2BAA2B;;AAE3B,IAAK,SAGJ;AAHD,WAAK,SAAS;IACZ,kCAAqB,CAAA;IACrB,gCAAmB,CAAA;AACrB,CAAC,EAHI,SAAS,KAAT,SAAS,QAGb;AAAA,CAAC;AAEF,kBAAe,SAAS,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Sends and retries an http request
3
+ * @author Gabriel Abrams
4
+ * @param opts object containing all arguments
5
+ * @param opts.path path to send request to
6
+ * @param [opts.host] host to send request to
7
+ * @param [opts.method=GET] http method to use
8
+ * @param [opts.params] body/data to include in the request
9
+ * @param [opts.headers] headers to include in the request
10
+ * @param [opts.numRetries=0] number of times to retry the request if it
11
+ * fails
12
+ * @param [opts.ignoreSSLIssues] if true, ignores SSL certificate
13
+ * issues. If host is localhost:8088, this will default to true
14
+ * @returns { body, status, headers } on success
15
+ */
16
+ declare const sendRequest: (opts: {
17
+ path: string;
18
+ host?: string;
19
+ method?: ('GET' | 'POST' | 'PUT' | 'DELETE');
20
+ params?: {
21
+ [x: string]: any;
22
+ };
23
+ headers?: {
24
+ [x: string]: any;
25
+ };
26
+ numRetries?: number;
27
+ ignoreSSLIssues?: boolean;
28
+ }) => Promise<{
29
+ body: any;
30
+ status: number;
31
+ headers: {
32
+ [x: string]: any;
33
+ };
34
+ }>;
35
+ export default sendRequest;
package/lib/index.js ADDED
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (_) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __importDefault = (this && this.__importDefault) || function (mod) {
50
+ return (mod && mod.__esModule) ? mod : { "default": mod };
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ // Import libs
54
+ var axios_1 = __importDefault(require("axios"));
55
+ var qs_1 = __importDefault(require("qs"));
56
+ // Import other CACCL libs
57
+ var caccl_error_1 = __importDefault(require("caccl-error"));
58
+ // Import shared types
59
+ var ErrorCode_1 = __importDefault(require("./ErrorCode"));
60
+ // Check if we should send cross-domain credentials
61
+ var sendCrossDomainCredentials = (process.env.NODE_ENV === 'development');
62
+ /**
63
+ * Sends and retries an http request
64
+ * @author Gabriel Abrams
65
+ * @param opts object containing all arguments
66
+ * @param opts.path path to send request to
67
+ * @param [opts.host] host to send request to
68
+ * @param [opts.method=GET] http method to use
69
+ * @param [opts.params] body/data to include in the request
70
+ * @param [opts.headers] headers to include in the request
71
+ * @param [opts.numRetries=0] number of times to retry the request if it
72
+ * fails
73
+ * @param [opts.ignoreSSLIssues] if true, ignores SSL certificate
74
+ * issues. If host is localhost:8088, this will default to true
75
+ * @returns { body, status, headers } on success
76
+ */
77
+ var sendRequest = function (opts) { return __awaiter(void 0, void 0, void 0, function () {
78
+ var numRetries, method, stringifiedParams, query, url, ignoreSSLIssues, headers, data, response, err_1;
79
+ return __generator(this, function (_a) {
80
+ switch (_a.label) {
81
+ case 0:
82
+ numRetries = (opts.numRetries ? opts.numRetries : 0);
83
+ method = (opts.method || 'GET');
84
+ stringifiedParams = qs_1.default.stringify(opts.params || {}, {
85
+ encodeValuesOnly: true,
86
+ arrayFormat: 'brackets',
87
+ });
88
+ query = (method === 'GET' ? "?".concat(stringifiedParams) : '');
89
+ if (!opts.host) {
90
+ // No host included at all. Just send to a path
91
+ url = "".concat(opts.path).concat(query);
92
+ }
93
+ else {
94
+ url = "https://".concat(opts.host).concat(opts.path).concat(query);
95
+ }
96
+ ignoreSSLIssues = (opts.ignoreSSLIssues !== undefined
97
+ ? opts.ignoreSSLIssues
98
+ : opts.host === 'localhost:8088');
99
+ headers = opts.headers || {};
100
+ data = null;
101
+ if (!headers['Content-Type']) {
102
+ // Form encoded
103
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
104
+ // Add data if applicable
105
+ data = (method !== 'GET' ? stringifiedParams : null);
106
+ }
107
+ else {
108
+ // JSON encode
109
+ data = opts.params;
110
+ }
111
+ _a.label = 1;
112
+ case 1:
113
+ _a.trys.push([1, 3, , 4]);
114
+ return [4 /*yield*/, (0, axios_1.default)({
115
+ method: method,
116
+ url: url,
117
+ data: data,
118
+ headers: headers,
119
+ withCredentials: sendCrossDomainCredentials,
120
+ })];
121
+ case 2:
122
+ response = _a.sent();
123
+ // Process response
124
+ return [2 /*return*/, {
125
+ body: response.data,
126
+ status: response.status,
127
+ headers: response.headers,
128
+ }];
129
+ case 3:
130
+ err_1 = _a.sent();
131
+ // Axios throws an error if the request status indicates an error
132
+ // sendRequest is supposed to resolve if the request went through, whether
133
+ // the status indicates an error or not.
134
+ if (err_1.response) {
135
+ // Resolve with response
136
+ return [2 /*return*/, {
137
+ body: err_1.response.data,
138
+ status: err_1.response.status,
139
+ headers: err_1.response.headers,
140
+ }];
141
+ }
142
+ // Request failed! Check if we have more attempts
143
+ if (numRetries > 0) {
144
+ // Update opts with one less retry
145
+ return [2 /*return*/, sendRequest(__assign(__assign({}, opts), { numRetries: opts.numRetries - 1 }))];
146
+ }
147
+ // Self-signed certificate error:
148
+ if (err_1.message.includes('self signed certificate')) {
149
+ throw new caccl_error_1.default({
150
+ message: 'We refused to send a request because the receiver has self-signed certificates.',
151
+ code: ErrorCode_1.default.SelfSigned,
152
+ });
153
+ }
154
+ // No tries left
155
+ throw new caccl_error_1.default({
156
+ message: 'We encountered an error when trying to send a network request. If this issue persists, contact an admin.',
157
+ code: ErrorCode_1.default.NotConnected,
158
+ });
159
+ case 4: return [2 /*return*/];
160
+ }
161
+ });
162
+ }); };
163
+ exports.default = sendRequest;
164
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "caccl-send-request",
3
- "version": "1.0.14",
3
+ "version": "2.0.0-beta.10",
4
4
  "description": "The default request sender used throughout the CACCL project.",
5
- "main": "index.js",
5
+ "main": "./lib/index.js",
6
+ "types": "./lib/index.d.ts",
6
7
  "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
8
+ "build": "tsc --project ./tsconfig.json"
8
9
  },
9
10
  "repository": {
10
11
  "type": "git",
@@ -25,16 +26,19 @@
25
26
  },
26
27
  "homepage": "https://github.com/harvard-edtech/caccl-send-request#readme",
27
28
  "devDependencies": {
28
- "eslint": "^5.16.0",
29
- "eslint-config-airbnb": "^17.1.1",
30
- "eslint-plugin-import": "^2.21.2",
31
- "eslint-plugin-jsx-a11y": "^6.2.3",
32
- "eslint-plugin-react": "^7.20.0"
29
+ "@types/browserify": "^12.0.37",
30
+ "@types/node": "^17.0.17",
31
+ "@types/qs": "^6.9.7",
32
+ "eslint": "^8.9.0",
33
+ "eslint-config-airbnb": "^19.0.4",
34
+ "eslint-plugin-import": "^2.22.1",
35
+ "eslint-plugin-jsx-a11y": "^6.4.1",
36
+ "eslint-plugin-react": "^7.22.0",
37
+ "typescript": "^4.5.5"
33
38
  },
34
39
  "dependencies": {
35
- "axios": "^0.19.2",
36
- "caccl-error": "^1.0.6",
37
- "https": "^1.0.0",
38
- "qs": "^6.9.4"
40
+ "axios": "^0.21.4",
41
+ "caccl-error": "^2.0.0-beta.10",
42
+ "qs": "^6.9.6"
39
43
  }
40
44
  }
@@ -0,0 +1,8 @@
1
+ // Highest error code: CSR2
2
+
3
+ enum ErrorCode {
4
+ NotConnected = 'CSR1',
5
+ SelfSigned = 'CSR2',
6
+ };
7
+
8
+ export default ErrorCode;
package/src/index.ts ADDED
@@ -0,0 +1,140 @@
1
+ // Import libs
2
+ import axios from 'axios';
3
+ import qs from 'qs';
4
+
5
+ // Import other CACCL libs
6
+ import CACCLError from 'caccl-error';
7
+
8
+ // Import shared types
9
+ import ErrorCode from './ErrorCode';
10
+
11
+ // Check if we should send cross-domain credentials
12
+ const sendCrossDomainCredentials = (process.env.NODE_ENV === 'development');
13
+
14
+ /**
15
+ * Sends and retries an http request
16
+ * @author Gabriel Abrams
17
+ * @param opts object containing all arguments
18
+ * @param opts.path path to send request to
19
+ * @param [opts.host] host to send request to
20
+ * @param [opts.method=GET] http method to use
21
+ * @param [opts.params] body/data to include in the request
22
+ * @param [opts.headers] headers to include in the request
23
+ * @param [opts.numRetries=0] number of times to retry the request if it
24
+ * fails
25
+ * @param [opts.ignoreSSLIssues] if true, ignores SSL certificate
26
+ * issues. If host is localhost:8088, this will default to true
27
+ * @returns { body, status, headers } on success
28
+ */
29
+ const sendRequest = async (
30
+ opts: {
31
+ path: string,
32
+ host?: string,
33
+ method?: ('GET' | 'POST' | 'PUT' | 'DELETE'),
34
+ params?: { [k in string]: any },
35
+ headers?: { [k in string]: any },
36
+ numRetries?: number,
37
+ ignoreSSLIssues?: boolean,
38
+ },
39
+ ): Promise<{
40
+ body: any,
41
+ status: number,
42
+ headers: { [k in string]: any },
43
+ }> => {
44
+ // Set max number of retries if not defined
45
+ const numRetries = (opts.numRetries ? opts.numRetries : 0);
46
+
47
+ // Process method
48
+ const method: ('GET' | 'POST' | 'PUT' | 'DELETE') = (opts.method || 'GET');
49
+
50
+ // Stringify parameters
51
+ const stringifiedParams = qs.stringify(opts.params || {}, {
52
+ encodeValuesOnly: true,
53
+ arrayFormat: 'brackets',
54
+ });
55
+
56
+ // Create url (include query if GET)
57
+ const query = (method === 'GET' ? `?${stringifiedParams}` : '');
58
+ let url;
59
+ if (!opts.host) {
60
+ // No host included at all. Just send to a path
61
+ url = `${opts.path}${query}`;
62
+ } else {
63
+ url = `https://${opts.host}${opts.path}${query}`;
64
+ }
65
+
66
+ // Default ignoreSSLIssues
67
+ const ignoreSSLIssues = (
68
+ opts.ignoreSSLIssues !== undefined
69
+ ? opts.ignoreSSLIssues
70
+ : opts.host === 'localhost:8088'
71
+ );
72
+
73
+ // Update headers
74
+ const headers = opts.headers || {};
75
+ let data = null;
76
+ if (!headers['Content-Type']) {
77
+ // Form encoded
78
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
79
+ // Add data if applicable
80
+ data = (method !== 'GET' ? stringifiedParams : null);
81
+ } else {
82
+ // JSON encode
83
+ data = opts.params;
84
+ }
85
+
86
+ // Send request
87
+ try {
88
+ const response = await axios({
89
+ method,
90
+ url,
91
+ data,
92
+ headers,
93
+ withCredentials: sendCrossDomainCredentials,
94
+ });
95
+
96
+ // Process response
97
+ return {
98
+ body: response.data,
99
+ status: response.status,
100
+ headers: response.headers,
101
+ };
102
+ } catch (err) {
103
+ // Axios throws an error if the request status indicates an error
104
+ // sendRequest is supposed to resolve if the request went through, whether
105
+ // the status indicates an error or not.
106
+ if (err.response) {
107
+ // Resolve with response
108
+ return {
109
+ body: err.response.data,
110
+ status: err.response.status,
111
+ headers: err.response.headers,
112
+ };
113
+ }
114
+
115
+ // Request failed! Check if we have more attempts
116
+ if (numRetries > 0) {
117
+ // Update opts with one less retry
118
+ return sendRequest({
119
+ ...opts,
120
+ numRetries: opts.numRetries - 1,
121
+ });
122
+ }
123
+
124
+ // Self-signed certificate error:
125
+ if (err.message.includes('self signed certificate')) {
126
+ throw new CACCLError({
127
+ message: 'We refused to send a request because the receiver has self-signed certificates.',
128
+ code: ErrorCode.SelfSigned,
129
+ });
130
+ }
131
+
132
+ // No tries left
133
+ throw new CACCLError({
134
+ message: 'We encountered an error when trying to send a network request. If this issue persists, contact an admin.',
135
+ code: ErrorCode.NotConnected,
136
+ });
137
+ }
138
+ };
139
+
140
+ export default sendRequest;
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonjs",
4
+ "esModuleInterop": true,
5
+ "noImplicitAny": true,
6
+ "noEmitOnError": true,
7
+ "removeComments": false,
8
+ "declaration": true,
9
+ "sourceMap": true,
10
+ "target": "es5",
11
+ "outDir": "./lib"
12
+ },
13
+ "include": [
14
+ "./src"
15
+ ],
16
+ "ts-node": {
17
+ "files": true
18
+ }
19
+ }
package/errorCodes.js DELETED
@@ -1,6 +0,0 @@
1
- // Highest error code: CSR2
2
-
3
- module.exports = {
4
- notConnected: 'CSR1',
5
- selfSigned: 'CSR2',
6
- };
package/index.js DELETED
@@ -1,129 +0,0 @@
1
- const axios = require('axios');
2
- const qs = require('qs');
3
- const CACCLError = require('caccl-error');
4
- const https = require('https');
5
-
6
- const errorCodes = require('./errorCodes');
7
-
8
- // Create an agent to ignore unauthorize ssl issues
9
- const ignoreSSLIssuesAgent = new https.Agent({ rejectUnauthorized: false });
10
-
11
- // Check if we should send cross-domain credentials
12
- const sendCrossDomainCredentials = !!(
13
- process.env.DEV
14
- || process.env.NODE_ENV === 'development'
15
- );
16
-
17
- /**
18
- * Sends and retries an http request
19
- * @author Gabriel Abrams
20
- * @param {string} host - host to send request to
21
- * @param {string} path - path to send request to
22
- * @param {string} [method=GET] - http method to use
23
- * @param {object} [params] - body/data to include in the request
24
- * @param {object} [headers] - headers to include in the request
25
- * @param {number} [numRetries=0] - number of times to retry the request if it
26
- * fails
27
- * @param {boolean} [ignoreSSLIssues=false] - if true, ignores SSL certificate
28
- * issues. If host is localhost:8088, this will default to true
29
- * @return {Promise.<CACCLErrror|object>} Returns { body, status, headers } on
30
- * success, CACCLError on failure
31
- */
32
- const sendRequest = (options) => {
33
- // Set max number of retries if not defined
34
- const numRetries = (options.numRetries ? options.numRetries : 0);
35
-
36
- // Use default method if applicable
37
- const method = options.method || 'GET';
38
-
39
- // Stringify parameters
40
- const stringifiedParams = qs.stringify(options.params || {}, {
41
- encodeValuesOnly: true,
42
- arrayFormat: 'brackets',
43
- });
44
-
45
- // Create url (include query if GET)
46
- const query = (method === 'GET' ? `?${stringifiedParams}` : '');
47
- let url;
48
- if (!options.host) {
49
- // No host included at all. Just send to a path
50
- url = `${options.path}${query}`;
51
- } else {
52
- url = `https://${options.host}${options.path}${query}`;
53
- }
54
-
55
- // Default ignoreSSLIssues
56
- const ignoreSSLIssues = (
57
- options.ignoreSSLIssues !== undefined
58
- ? options.ignoreSSLIssues
59
- : options.host === 'localhost:8088'
60
- );
61
-
62
- // Prep to ignore ssl issues
63
- const httpsAgent = (
64
- ignoreSSLIssues
65
- ? ignoreSSLIssuesAgent
66
- : undefined
67
- );
68
-
69
- // Update headers
70
- const headers = options.headers || {};
71
- let data = null;
72
- if (!headers['Content-Type']) {
73
- // Form encoded
74
- headers['Content-Type'] = 'application/x-www-form-urlencoded';
75
- // Add data if applicable
76
- data = (method !== 'GET' ? stringifiedParams : null);
77
- } else {
78
- // JSON encode
79
- data = options.params;
80
- }
81
-
82
- // Send request
83
- return axios({
84
- method,
85
- url,
86
- data,
87
- httpsAgent,
88
- headers,
89
- withCredentials: sendCrossDomainCredentials,
90
- })
91
- .catch((err) => {
92
- // Axios throws an error if the request status indicates an error
93
- // sendRequest is supposed to resolve if the request went through, whether
94
- // the status indicates an error or not.
95
- if (err.response) {
96
- // Resolve with response
97
- return Promise.resolve(err.response);
98
- }
99
- // Request failed! Check if we have more attempts
100
- if (numRetries > 0) {
101
- // Update options with one less retry
102
- const newOptions = options;
103
- newOptions.numRetries -= 1;
104
- return sendRequest(newOptions);
105
- }
106
-
107
- // Self-signed certificate error:
108
- if (err.message.includes('self signed certificate')) {
109
- throw new CACCLError({
110
- message: 'We refused to send a request because the receiver has self-signed certificates.',
111
- code: errorCodes.selfSigned,
112
- });
113
- }
114
-
115
- // No tries left
116
- throw new CACCLError({
117
- message: 'We encountered an error when trying to send a network request. If this issue persists, contact an admin.',
118
- code: errorCodes.notConnected,
119
- });
120
- })
121
- .then((response) => {
122
- return {
123
- body: response.data,
124
- status: response.status,
125
- headers: response.headers,
126
- };
127
- });
128
- };
129
- module.exports = sendRequest;