@faasjs/request 0.0.2-beta.302 → 0.0.2-beta.320
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/{lib → dist}/index.d.ts +77 -76
- package/dist/index.js +214 -0
- package/dist/index.mjs +181 -0
- package/package.json +9 -13
- package/lib/index.es.js +0 -176
- package/lib/index.js +0 -204
package/{lib → dist}/index.d.ts
RENAMED
|
@@ -1,76 +1,77 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
headers?: http.OutgoingHttpHeaders;
|
|
5
|
-
method?: string;
|
|
6
|
-
host?: string;
|
|
7
|
-
path?: string;
|
|
8
|
-
query?: http.OutgoingHttpHeaders;
|
|
9
|
-
body?: {
|
|
10
|
-
[key: string]: any;
|
|
11
|
-
};
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
request?: Request;
|
|
15
|
-
statusCode?: number;
|
|
16
|
-
statusMessage?: string;
|
|
17
|
-
headers: http.OutgoingHttpHeaders;
|
|
18
|
-
body: T;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/** 请求头 */
|
|
22
|
-
headers?: http.OutgoingHttpHeaders;
|
|
23
|
-
/** 请求方法,默认为 GET */
|
|
24
|
-
method?: string;
|
|
25
|
-
/** 请求参数,放置于 path 后,若需放置在 body 中,请使用 body 参数 */
|
|
26
|
-
query?: {
|
|
27
|
-
[key: string]: any;
|
|
28
|
-
};
|
|
29
|
-
/** 请求体 */
|
|
30
|
-
body?: {
|
|
31
|
-
[key: string]: any;
|
|
32
|
-
} | string;
|
|
33
|
-
/** 最长耗时,单位为毫秒 */
|
|
34
|
-
timeout?: number;
|
|
35
|
-
/** HTTP 认证头,格式为 user:password */
|
|
36
|
-
auth?: string;
|
|
37
|
-
/** 上传文件的完整路径 */
|
|
38
|
-
file?: string;
|
|
39
|
-
/** 下载流,用于直接将响应内容保存到本地文件,通过 fs.createWriteStream 创建 */
|
|
40
|
-
downloadStream?: NodeJS.WritableStream;
|
|
41
|
-
pfx?: Buffer;
|
|
42
|
-
passphrase?: string;
|
|
43
|
-
agent?: boolean;
|
|
44
|
-
/** body 解析器,默认为 JSON.parse */
|
|
45
|
-
parse?: (body: string) => any;
|
|
46
|
-
};
|
|
47
|
-
declare type Mock = (url: string, options: RequestOptions) => Promise<Response>;
|
|
48
|
-
/**
|
|
49
|
-
* 设置模拟请求
|
|
50
|
-
* @param handler {function | null} 模拟函数,若设置为 null 则表示清除模拟函数
|
|
51
|
-
* @example setMock(async (url, options) => Promise.resolve({ headers: {}, statusCode: 200, body: { data: 'ok' } }))
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 发起网络请求
|
|
57
|
-
* @param {string} url 请求路径或完整网址
|
|
58
|
-
* @param {object=} [options={}] 参数和配置
|
|
59
|
-
* @param {string} [options.method=GET] 请求方法
|
|
60
|
-
* @param {object} [options.query={}] 请求参数,放置于 path 后,若需放置在 body 中,请使用 body 参数
|
|
61
|
-
* @param {object} [options.headers={}] 请求头
|
|
62
|
-
* @param {object=} options.body 请求体
|
|
63
|
-
* @param {number=} options.timeout 最长耗时,单位为毫秒
|
|
64
|
-
* @param {string=} options.auth HTTP 认证头,格式为 user:password
|
|
65
|
-
* @param {string=} options.file 上传文件的完整路径
|
|
66
|
-
* @param {WritableStream=} options.downloadStream 下载流,用于直接将响应内容保存到本地文件
|
|
67
|
-
* @param {Buffer=} options.pfx pfx
|
|
68
|
-
* @param {string=} options.passphrase passphrase
|
|
69
|
-
* @param {boolean=} options.agent agent
|
|
70
|
-
* @param {parse=} options.parse body 解析器,默认为 JSON.parse
|
|
71
|
-
*
|
|
72
|
-
* @returns {promise}
|
|
73
|
-
* @url https://faasjs.com/doc/request.html
|
|
74
|
-
*/
|
|
75
|
-
|
|
76
|
-
|
|
1
|
+
import * as http from 'http';
|
|
2
|
+
|
|
3
|
+
declare type Request = {
|
|
4
|
+
headers?: http.OutgoingHttpHeaders;
|
|
5
|
+
method?: string;
|
|
6
|
+
host?: string;
|
|
7
|
+
path?: string;
|
|
8
|
+
query?: http.OutgoingHttpHeaders;
|
|
9
|
+
body?: {
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
declare type Response<T = any> = {
|
|
14
|
+
request?: Request;
|
|
15
|
+
statusCode?: number;
|
|
16
|
+
statusMessage?: string;
|
|
17
|
+
headers: http.OutgoingHttpHeaders;
|
|
18
|
+
body: T;
|
|
19
|
+
};
|
|
20
|
+
declare type RequestOptions = {
|
|
21
|
+
/** 请求头 */
|
|
22
|
+
headers?: http.OutgoingHttpHeaders;
|
|
23
|
+
/** 请求方法,默认为 GET */
|
|
24
|
+
method?: string;
|
|
25
|
+
/** 请求参数,放置于 path 后,若需放置在 body 中,请使用 body 参数 */
|
|
26
|
+
query?: {
|
|
27
|
+
[key: string]: any;
|
|
28
|
+
};
|
|
29
|
+
/** 请求体 */
|
|
30
|
+
body?: {
|
|
31
|
+
[key: string]: any;
|
|
32
|
+
} | string;
|
|
33
|
+
/** 最长耗时,单位为毫秒 */
|
|
34
|
+
timeout?: number;
|
|
35
|
+
/** HTTP 认证头,格式为 user:password */
|
|
36
|
+
auth?: string;
|
|
37
|
+
/** 上传文件的完整路径 */
|
|
38
|
+
file?: string;
|
|
39
|
+
/** 下载流,用于直接将响应内容保存到本地文件,通过 fs.createWriteStream 创建 */
|
|
40
|
+
downloadStream?: NodeJS.WritableStream;
|
|
41
|
+
pfx?: Buffer;
|
|
42
|
+
passphrase?: string;
|
|
43
|
+
agent?: boolean;
|
|
44
|
+
/** body 解析器,默认为 JSON.parse */
|
|
45
|
+
parse?: (body: string) => any;
|
|
46
|
+
};
|
|
47
|
+
declare type Mock = (url: string, options: RequestOptions) => Promise<Response>;
|
|
48
|
+
/**
|
|
49
|
+
* 设置模拟请求
|
|
50
|
+
* @param handler {function | null} 模拟函数,若设置为 null 则表示清除模拟函数
|
|
51
|
+
* @example setMock(async (url, options) => Promise.resolve({ headers: {}, statusCode: 200, body: { data: 'ok' } }))
|
|
52
|
+
*/
|
|
53
|
+
declare function setMock(handler: Mock | null): void;
|
|
54
|
+
declare function querystringify(obj: any): string;
|
|
55
|
+
/**
|
|
56
|
+
* 发起网络请求
|
|
57
|
+
* @param {string} url 请求路径或完整网址
|
|
58
|
+
* @param {object=} [options={}] 参数和配置
|
|
59
|
+
* @param {string} [options.method=GET] 请求方法
|
|
60
|
+
* @param {object} [options.query={}] 请求参数,放置于 path 后,若需放置在 body 中,请使用 body 参数
|
|
61
|
+
* @param {object} [options.headers={}] 请求头
|
|
62
|
+
* @param {object=} options.body 请求体
|
|
63
|
+
* @param {number=} options.timeout 最长耗时,单位为毫秒
|
|
64
|
+
* @param {string=} options.auth HTTP 认证头,格式为 user:password
|
|
65
|
+
* @param {string=} options.file 上传文件的完整路径
|
|
66
|
+
* @param {WritableStream=} options.downloadStream 下载流,用于直接将响应内容保存到本地文件
|
|
67
|
+
* @param {Buffer=} options.pfx pfx
|
|
68
|
+
* @param {string=} options.passphrase passphrase
|
|
69
|
+
* @param {boolean=} options.agent agent
|
|
70
|
+
* @param {parse=} options.parse body 解析器,默认为 JSON.parse
|
|
71
|
+
*
|
|
72
|
+
* @returns {promise}
|
|
73
|
+
* @url https://faasjs.com/doc/request.html
|
|
74
|
+
*/
|
|
75
|
+
declare function request<T = any>(url: string, { headers, method, query, body, timeout, auth, file, downloadStream, pfx, passphrase, agent, parse }?: RequestOptions): Promise<Response<T>>;
|
|
76
|
+
|
|
77
|
+
export { Request, RequestOptions, Response, request as default, querystringify, request, setMock };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
11
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
|
+
var __spreadValues = (a, b) => {
|
|
13
|
+
for (var prop in b || (b = {}))
|
|
14
|
+
if (__hasOwnProp.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
if (__getOwnPropSymbols)
|
|
17
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
18
|
+
if (__propIsEnum.call(b, prop))
|
|
19
|
+
__defNormalProp(a, prop, b[prop]);
|
|
20
|
+
}
|
|
21
|
+
return a;
|
|
22
|
+
};
|
|
23
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
24
|
+
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
|
25
|
+
var __export = (target, all) => {
|
|
26
|
+
for (var name in all)
|
|
27
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
28
|
+
};
|
|
29
|
+
var __reExport = (target, module2, copyDefault, desc) => {
|
|
30
|
+
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
|
31
|
+
for (let key of __getOwnPropNames(module2))
|
|
32
|
+
if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default"))
|
|
33
|
+
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
|
|
34
|
+
}
|
|
35
|
+
return target;
|
|
36
|
+
};
|
|
37
|
+
var __toESM = (module2, isNodeMode) => {
|
|
38
|
+
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", !isNodeMode && module2 && module2.__esModule ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
|
|
39
|
+
};
|
|
40
|
+
var __toCommonJS = /* @__PURE__ */ ((cache) => {
|
|
41
|
+
return (module2, temp) => {
|
|
42
|
+
return cache && cache.get(module2) || (temp = __reExport(__markAsModule({}), module2, 1), cache && cache.set(module2, temp), temp);
|
|
43
|
+
};
|
|
44
|
+
})(typeof WeakMap !== "undefined" ? /* @__PURE__ */ new WeakMap() : 0);
|
|
45
|
+
|
|
46
|
+
// src/index.ts
|
|
47
|
+
var src_exports = {};
|
|
48
|
+
__export(src_exports, {
|
|
49
|
+
default: () => src_default,
|
|
50
|
+
querystringify: () => querystringify,
|
|
51
|
+
request: () => request,
|
|
52
|
+
setMock: () => setMock
|
|
53
|
+
});
|
|
54
|
+
var http = __toESM(require("http"));
|
|
55
|
+
var https = __toESM(require("https"));
|
|
56
|
+
var import_url = require("url");
|
|
57
|
+
var import_fs = require("fs");
|
|
58
|
+
var import_path = require("path");
|
|
59
|
+
var import_logger = require("@faasjs/logger");
|
|
60
|
+
var mock = null;
|
|
61
|
+
function setMock(handler) {
|
|
62
|
+
mock = handler;
|
|
63
|
+
}
|
|
64
|
+
function querystringify(obj) {
|
|
65
|
+
const pairs = [];
|
|
66
|
+
let value;
|
|
67
|
+
let key;
|
|
68
|
+
for (key in obj) {
|
|
69
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
70
|
+
value = obj[key];
|
|
71
|
+
if (!value && (value === null || value === void 0 || isNaN(value))) {
|
|
72
|
+
value = "";
|
|
73
|
+
}
|
|
74
|
+
key = encodeURIComponent(key);
|
|
75
|
+
value = encodeURIComponent(value);
|
|
76
|
+
if (key === null || value === null)
|
|
77
|
+
continue;
|
|
78
|
+
pairs.push(key + "=" + value);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return pairs.length ? pairs.join("&") : "";
|
|
82
|
+
}
|
|
83
|
+
async function request(url, {
|
|
84
|
+
headers,
|
|
85
|
+
method,
|
|
86
|
+
query,
|
|
87
|
+
body,
|
|
88
|
+
timeout,
|
|
89
|
+
auth,
|
|
90
|
+
file,
|
|
91
|
+
downloadStream,
|
|
92
|
+
pfx,
|
|
93
|
+
passphrase,
|
|
94
|
+
agent,
|
|
95
|
+
parse
|
|
96
|
+
} = {
|
|
97
|
+
headers: {},
|
|
98
|
+
query: {}
|
|
99
|
+
}) {
|
|
100
|
+
const log = new import_logger.Logger("request");
|
|
101
|
+
if (mock)
|
|
102
|
+
return mock(url, {
|
|
103
|
+
headers,
|
|
104
|
+
method,
|
|
105
|
+
query,
|
|
106
|
+
body
|
|
107
|
+
});
|
|
108
|
+
if (query) {
|
|
109
|
+
if (!url.includes("?"))
|
|
110
|
+
url += "?";
|
|
111
|
+
else if (!url.endsWith("?"))
|
|
112
|
+
url += "&";
|
|
113
|
+
url += querystringify(query);
|
|
114
|
+
}
|
|
115
|
+
const uri = new import_url.URL(url);
|
|
116
|
+
const protocol = uri.protocol === "https:" ? https : http;
|
|
117
|
+
if (!uri.protocol)
|
|
118
|
+
throw Error("Unknown protocol");
|
|
119
|
+
const options = {
|
|
120
|
+
headers: {},
|
|
121
|
+
host: uri.host ? uri.host.replace(/:[0-9]+$/, "") : uri.host,
|
|
122
|
+
method: method ? method.toUpperCase() : "GET",
|
|
123
|
+
path: uri.pathname + uri.search,
|
|
124
|
+
query: {},
|
|
125
|
+
port: uri.port,
|
|
126
|
+
timeout,
|
|
127
|
+
auth,
|
|
128
|
+
pfx,
|
|
129
|
+
passphrase,
|
|
130
|
+
agent
|
|
131
|
+
};
|
|
132
|
+
for (const key in headers)
|
|
133
|
+
if (typeof headers[key] !== "undefined" && headers[key] !== null)
|
|
134
|
+
options.headers[key] = headers[key];
|
|
135
|
+
if (body && typeof body !== "string")
|
|
136
|
+
if (options.headers["Content-Type"] && options.headers["Content-Type"].toString().includes("application/x-www-form-urlencoded"))
|
|
137
|
+
body = querystringify(body);
|
|
138
|
+
else
|
|
139
|
+
body = JSON.stringify(body);
|
|
140
|
+
if (body && !options.headers["Content-Length"])
|
|
141
|
+
options.headers["Content-Length"] = Buffer.byteLength(body);
|
|
142
|
+
return await new Promise(function(resolve, reject) {
|
|
143
|
+
log.debug("request %j", __spreadProps(__spreadValues({}, options), {
|
|
144
|
+
body
|
|
145
|
+
}));
|
|
146
|
+
const req = protocol.request(options, function(res) {
|
|
147
|
+
if (downloadStream) {
|
|
148
|
+
res.pipe(downloadStream);
|
|
149
|
+
downloadStream.on("finish", function() {
|
|
150
|
+
resolve(void 0);
|
|
151
|
+
});
|
|
152
|
+
} else {
|
|
153
|
+
const raw = [];
|
|
154
|
+
res.on("data", (chunk) => {
|
|
155
|
+
raw.push(chunk);
|
|
156
|
+
});
|
|
157
|
+
res.on("end", () => {
|
|
158
|
+
const data = Buffer.concat(raw).toString();
|
|
159
|
+
log.timeEnd(url, "response %s %s %s", res.statusCode, res.headers["content-type"], data);
|
|
160
|
+
const response = Object.create(null);
|
|
161
|
+
response.request = options;
|
|
162
|
+
response.request.body = body;
|
|
163
|
+
response.statusCode = res.statusCode;
|
|
164
|
+
response.statusMessage = res.statusMessage;
|
|
165
|
+
response.headers = res.headers;
|
|
166
|
+
response.body = data;
|
|
167
|
+
if (response.body && response.headers["content-type"] && response.headers["content-type"].includes("application/json"))
|
|
168
|
+
try {
|
|
169
|
+
response.body = parse ? parse(response.body) : JSON.parse(response.body);
|
|
170
|
+
log.debug("response.parse JSON");
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error(error);
|
|
173
|
+
}
|
|
174
|
+
if (response.statusCode >= 200 && response.statusCode < 400)
|
|
175
|
+
resolve(response);
|
|
176
|
+
else {
|
|
177
|
+
log.debug("response.error %j", response);
|
|
178
|
+
reject(response);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
if (body)
|
|
184
|
+
req.write(body);
|
|
185
|
+
if (file) {
|
|
186
|
+
const crlf = "\r\n";
|
|
187
|
+
const boundary = `--${Math.random().toString(16)}`;
|
|
188
|
+
const delimiter = `${crlf}--${boundary}`;
|
|
189
|
+
const headers2 = [`Content-Disposition: form-data; name="file"; filename="${(0, import_path.basename)(file)}"${crlf}`];
|
|
190
|
+
const multipartBody = Buffer.concat([
|
|
191
|
+
Buffer.from(delimiter + crlf + headers2.join("") + crlf),
|
|
192
|
+
(0, import_fs.readFileSync)(file),
|
|
193
|
+
Buffer.from(`${delimiter}--`)
|
|
194
|
+
]);
|
|
195
|
+
req.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
|
|
196
|
+
req.setHeader("Content-Length", multipartBody.length);
|
|
197
|
+
req.write(multipartBody);
|
|
198
|
+
}
|
|
199
|
+
req.on("error", function(e) {
|
|
200
|
+
log.timeEnd(url, "response.error %j", e);
|
|
201
|
+
reject(e);
|
|
202
|
+
});
|
|
203
|
+
log.time(url);
|
|
204
|
+
req.end();
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
var src_default = request;
|
|
208
|
+
module.exports = __toCommonJS(src_exports);
|
|
209
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
210
|
+
0 && (module.exports = {
|
|
211
|
+
querystringify,
|
|
212
|
+
request,
|
|
213
|
+
setMock
|
|
214
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
|
|
21
|
+
// src/index.ts
|
|
22
|
+
import * as http from "http";
|
|
23
|
+
import * as https from "https";
|
|
24
|
+
import { URL } from "url";
|
|
25
|
+
import { readFileSync } from "fs";
|
|
26
|
+
import { basename } from "path";
|
|
27
|
+
import { Logger } from "@faasjs/logger";
|
|
28
|
+
var mock = null;
|
|
29
|
+
function setMock(handler) {
|
|
30
|
+
mock = handler;
|
|
31
|
+
}
|
|
32
|
+
function querystringify(obj) {
|
|
33
|
+
const pairs = [];
|
|
34
|
+
let value;
|
|
35
|
+
let key;
|
|
36
|
+
for (key in obj) {
|
|
37
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
38
|
+
value = obj[key];
|
|
39
|
+
if (!value && (value === null || value === void 0 || isNaN(value))) {
|
|
40
|
+
value = "";
|
|
41
|
+
}
|
|
42
|
+
key = encodeURIComponent(key);
|
|
43
|
+
value = encodeURIComponent(value);
|
|
44
|
+
if (key === null || value === null)
|
|
45
|
+
continue;
|
|
46
|
+
pairs.push(key + "=" + value);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return pairs.length ? pairs.join("&") : "";
|
|
50
|
+
}
|
|
51
|
+
async function request(url, {
|
|
52
|
+
headers,
|
|
53
|
+
method,
|
|
54
|
+
query,
|
|
55
|
+
body,
|
|
56
|
+
timeout,
|
|
57
|
+
auth,
|
|
58
|
+
file,
|
|
59
|
+
downloadStream,
|
|
60
|
+
pfx,
|
|
61
|
+
passphrase,
|
|
62
|
+
agent,
|
|
63
|
+
parse
|
|
64
|
+
} = {
|
|
65
|
+
headers: {},
|
|
66
|
+
query: {}
|
|
67
|
+
}) {
|
|
68
|
+
const log = new Logger("request");
|
|
69
|
+
if (mock)
|
|
70
|
+
return mock(url, {
|
|
71
|
+
headers,
|
|
72
|
+
method,
|
|
73
|
+
query,
|
|
74
|
+
body
|
|
75
|
+
});
|
|
76
|
+
if (query) {
|
|
77
|
+
if (!url.includes("?"))
|
|
78
|
+
url += "?";
|
|
79
|
+
else if (!url.endsWith("?"))
|
|
80
|
+
url += "&";
|
|
81
|
+
url += querystringify(query);
|
|
82
|
+
}
|
|
83
|
+
const uri = new URL(url);
|
|
84
|
+
const protocol = uri.protocol === "https:" ? https : http;
|
|
85
|
+
if (!uri.protocol)
|
|
86
|
+
throw Error("Unknown protocol");
|
|
87
|
+
const options = {
|
|
88
|
+
headers: {},
|
|
89
|
+
host: uri.host ? uri.host.replace(/:[0-9]+$/, "") : uri.host,
|
|
90
|
+
method: method ? method.toUpperCase() : "GET",
|
|
91
|
+
path: uri.pathname + uri.search,
|
|
92
|
+
query: {},
|
|
93
|
+
port: uri.port,
|
|
94
|
+
timeout,
|
|
95
|
+
auth,
|
|
96
|
+
pfx,
|
|
97
|
+
passphrase,
|
|
98
|
+
agent
|
|
99
|
+
};
|
|
100
|
+
for (const key in headers)
|
|
101
|
+
if (typeof headers[key] !== "undefined" && headers[key] !== null)
|
|
102
|
+
options.headers[key] = headers[key];
|
|
103
|
+
if (body && typeof body !== "string")
|
|
104
|
+
if (options.headers["Content-Type"] && options.headers["Content-Type"].toString().includes("application/x-www-form-urlencoded"))
|
|
105
|
+
body = querystringify(body);
|
|
106
|
+
else
|
|
107
|
+
body = JSON.stringify(body);
|
|
108
|
+
if (body && !options.headers["Content-Length"])
|
|
109
|
+
options.headers["Content-Length"] = Buffer.byteLength(body);
|
|
110
|
+
return await new Promise(function(resolve, reject) {
|
|
111
|
+
log.debug("request %j", __spreadProps(__spreadValues({}, options), {
|
|
112
|
+
body
|
|
113
|
+
}));
|
|
114
|
+
const req = protocol.request(options, function(res) {
|
|
115
|
+
if (downloadStream) {
|
|
116
|
+
res.pipe(downloadStream);
|
|
117
|
+
downloadStream.on("finish", function() {
|
|
118
|
+
resolve(void 0);
|
|
119
|
+
});
|
|
120
|
+
} else {
|
|
121
|
+
const raw = [];
|
|
122
|
+
res.on("data", (chunk) => {
|
|
123
|
+
raw.push(chunk);
|
|
124
|
+
});
|
|
125
|
+
res.on("end", () => {
|
|
126
|
+
const data = Buffer.concat(raw).toString();
|
|
127
|
+
log.timeEnd(url, "response %s %s %s", res.statusCode, res.headers["content-type"], data);
|
|
128
|
+
const response = Object.create(null);
|
|
129
|
+
response.request = options;
|
|
130
|
+
response.request.body = body;
|
|
131
|
+
response.statusCode = res.statusCode;
|
|
132
|
+
response.statusMessage = res.statusMessage;
|
|
133
|
+
response.headers = res.headers;
|
|
134
|
+
response.body = data;
|
|
135
|
+
if (response.body && response.headers["content-type"] && response.headers["content-type"].includes("application/json"))
|
|
136
|
+
try {
|
|
137
|
+
response.body = parse ? parse(response.body) : JSON.parse(response.body);
|
|
138
|
+
log.debug("response.parse JSON");
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error(error);
|
|
141
|
+
}
|
|
142
|
+
if (response.statusCode >= 200 && response.statusCode < 400)
|
|
143
|
+
resolve(response);
|
|
144
|
+
else {
|
|
145
|
+
log.debug("response.error %j", response);
|
|
146
|
+
reject(response);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
if (body)
|
|
152
|
+
req.write(body);
|
|
153
|
+
if (file) {
|
|
154
|
+
const crlf = "\r\n";
|
|
155
|
+
const boundary = `--${Math.random().toString(16)}`;
|
|
156
|
+
const delimiter = `${crlf}--${boundary}`;
|
|
157
|
+
const headers2 = [`Content-Disposition: form-data; name="file"; filename="${basename(file)}"${crlf}`];
|
|
158
|
+
const multipartBody = Buffer.concat([
|
|
159
|
+
Buffer.from(delimiter + crlf + headers2.join("") + crlf),
|
|
160
|
+
readFileSync(file),
|
|
161
|
+
Buffer.from(`${delimiter}--`)
|
|
162
|
+
]);
|
|
163
|
+
req.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
|
|
164
|
+
req.setHeader("Content-Length", multipartBody.length);
|
|
165
|
+
req.write(multipartBody);
|
|
166
|
+
}
|
|
167
|
+
req.on("error", function(e) {
|
|
168
|
+
log.timeEnd(url, "response.error %j", e);
|
|
169
|
+
reject(e);
|
|
170
|
+
});
|
|
171
|
+
log.time(url);
|
|
172
|
+
req.end();
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
var src_default = request;
|
|
176
|
+
export {
|
|
177
|
+
src_default as default,
|
|
178
|
+
querystringify,
|
|
179
|
+
request,
|
|
180
|
+
setMock
|
|
181
|
+
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faasjs/request",
|
|
3
|
-
"version": "0.0.2-beta.
|
|
3
|
+
"version": "0.0.2-beta.320",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"main": "
|
|
6
|
-
"
|
|
7
|
-
"
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
8
|
"homepage": "https://faasjs.com/doc/request.html",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -16,24 +16,20 @@
|
|
|
16
16
|
},
|
|
17
17
|
"funding": "https://github.com/sponsors/faasjs",
|
|
18
18
|
"scripts": {
|
|
19
|
-
"
|
|
19
|
+
"build": "rm -rf ./dist && tsup-node src/index.ts --format esm,cjs --dts"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
|
-
"
|
|
22
|
+
"dist"
|
|
23
23
|
],
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@faasjs/logger": "^0.0.2-beta.
|
|
25
|
+
"@faasjs/logger": "^0.0.2-beta.320"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"
|
|
29
|
-
"@types/jest": "*",
|
|
30
|
-
"@types/node": "*",
|
|
31
|
-
"rollup": "*",
|
|
32
|
-
"rollup-plugin-typescript2": "*",
|
|
28
|
+
"tsup": "*",
|
|
33
29
|
"typescript": "*"
|
|
34
30
|
},
|
|
35
31
|
"engines": {
|
|
36
32
|
"npm": ">=8.0.0"
|
|
37
33
|
},
|
|
38
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "4a9f699171ad7e20d922e68b74418d1ec5b7d016"
|
|
39
35
|
}
|
package/lib/index.es.js
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import * as http from 'http';
|
|
2
|
-
import * as https from 'https';
|
|
3
|
-
import { URL } from 'url';
|
|
4
|
-
import { readFileSync } from 'fs';
|
|
5
|
-
import { basename } from 'path';
|
|
6
|
-
import { Logger } from '@faasjs/logger';
|
|
7
|
-
|
|
8
|
-
let mock = null;
|
|
9
|
-
/**
|
|
10
|
-
* 设置模拟请求
|
|
11
|
-
* @param handler {function | null} 模拟函数,若设置为 null 则表示清除模拟函数
|
|
12
|
-
* @example setMock(async (url, options) => Promise.resolve({ headers: {}, statusCode: 200, body: { data: 'ok' } }))
|
|
13
|
-
*/
|
|
14
|
-
function setMock(handler) {
|
|
15
|
-
mock = handler;
|
|
16
|
-
}
|
|
17
|
-
function querystringify(obj) {
|
|
18
|
-
const pairs = [];
|
|
19
|
-
let value;
|
|
20
|
-
let key;
|
|
21
|
-
for (key in obj) {
|
|
22
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
23
|
-
value = obj[key];
|
|
24
|
-
if (!value && (value === null || value === undefined || isNaN(value))) {
|
|
25
|
-
value = '';
|
|
26
|
-
}
|
|
27
|
-
key = encodeURIComponent(key);
|
|
28
|
-
value = encodeURIComponent(value);
|
|
29
|
-
if (key === null || value === null)
|
|
30
|
-
continue;
|
|
31
|
-
pairs.push(key + '=' + value);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return pairs.length ? pairs.join('&') : '';
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* 发起网络请求
|
|
38
|
-
* @param {string} url 请求路径或完整网址
|
|
39
|
-
* @param {object=} [options={}] 参数和配置
|
|
40
|
-
* @param {string} [options.method=GET] 请求方法
|
|
41
|
-
* @param {object} [options.query={}] 请求参数,放置于 path 后,若需放置在 body 中,请使用 body 参数
|
|
42
|
-
* @param {object} [options.headers={}] 请求头
|
|
43
|
-
* @param {object=} options.body 请求体
|
|
44
|
-
* @param {number=} options.timeout 最长耗时,单位为毫秒
|
|
45
|
-
* @param {string=} options.auth HTTP 认证头,格式为 user:password
|
|
46
|
-
* @param {string=} options.file 上传文件的完整路径
|
|
47
|
-
* @param {WritableStream=} options.downloadStream 下载流,用于直接将响应内容保存到本地文件
|
|
48
|
-
* @param {Buffer=} options.pfx pfx
|
|
49
|
-
* @param {string=} options.passphrase passphrase
|
|
50
|
-
* @param {boolean=} options.agent agent
|
|
51
|
-
* @param {parse=} options.parse body 解析器,默认为 JSON.parse
|
|
52
|
-
*
|
|
53
|
-
* @returns {promise}
|
|
54
|
-
* @url https://faasjs.com/doc/request.html
|
|
55
|
-
*/
|
|
56
|
-
async function request(url, { headers, method, query, body, timeout, auth, file, downloadStream, pfx, passphrase, agent, parse } = {
|
|
57
|
-
headers: {},
|
|
58
|
-
query: {}
|
|
59
|
-
}) {
|
|
60
|
-
const log = new Logger('request');
|
|
61
|
-
if (mock)
|
|
62
|
-
return mock(url, {
|
|
63
|
-
headers,
|
|
64
|
-
method,
|
|
65
|
-
query,
|
|
66
|
-
body
|
|
67
|
-
});
|
|
68
|
-
// 序列化 query
|
|
69
|
-
if (query) {
|
|
70
|
-
if (!url.includes('?'))
|
|
71
|
-
url += '?';
|
|
72
|
-
else if (!url.endsWith('?'))
|
|
73
|
-
url += '&';
|
|
74
|
-
url += querystringify(query);
|
|
75
|
-
}
|
|
76
|
-
// 处理 URL 并生成 options
|
|
77
|
-
const uri = new URL(url);
|
|
78
|
-
const protocol = uri.protocol === 'https:' ? https : http;
|
|
79
|
-
if (!uri.protocol)
|
|
80
|
-
throw Error('Unknown protocol');
|
|
81
|
-
const options = {
|
|
82
|
-
headers: {},
|
|
83
|
-
host: uri.host ? uri.host.replace(/:[0-9]+$/, '') : uri.host,
|
|
84
|
-
method: method ? method.toUpperCase() : 'GET',
|
|
85
|
-
path: uri.pathname + uri.search,
|
|
86
|
-
query: {},
|
|
87
|
-
port: uri.port,
|
|
88
|
-
timeout,
|
|
89
|
-
auth,
|
|
90
|
-
pfx,
|
|
91
|
-
passphrase,
|
|
92
|
-
agent
|
|
93
|
-
};
|
|
94
|
-
// 处理 headers
|
|
95
|
-
for (const key in headers)
|
|
96
|
-
if (typeof headers[key] !== 'undefined' && headers[key] !== null)
|
|
97
|
-
options.headers[key] = headers[key];
|
|
98
|
-
// 序列化 body
|
|
99
|
-
if (body && typeof body !== 'string')
|
|
100
|
-
if (options.headers['Content-Type'] &&
|
|
101
|
-
options.headers['Content-Type'].toString().includes('application/x-www-form-urlencoded'))
|
|
102
|
-
body = querystringify(body);
|
|
103
|
-
else
|
|
104
|
-
body = JSON.stringify(body);
|
|
105
|
-
if (body && !options.headers['Content-Length'])
|
|
106
|
-
options.headers['Content-Length'] = Buffer.byteLength(body);
|
|
107
|
-
return await new Promise(function (resolve, reject) {
|
|
108
|
-
log.debug('request %j', {
|
|
109
|
-
...options,
|
|
110
|
-
body
|
|
111
|
-
});
|
|
112
|
-
const req = protocol.request(options, function (res) {
|
|
113
|
-
if (downloadStream) {
|
|
114
|
-
res.pipe(downloadStream);
|
|
115
|
-
downloadStream.on('finish', function () {
|
|
116
|
-
resolve(undefined);
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
const raw = [];
|
|
121
|
-
res.on('data', (chunk) => {
|
|
122
|
-
raw.push(chunk);
|
|
123
|
-
});
|
|
124
|
-
res.on('end', () => {
|
|
125
|
-
const data = Buffer.concat(raw).toString();
|
|
126
|
-
log.timeEnd(url, 'response %s %s %s', res.statusCode, res.headers['content-type'], data);
|
|
127
|
-
const response = Object.create(null);
|
|
128
|
-
response.request = options;
|
|
129
|
-
response.request.body = body;
|
|
130
|
-
response.statusCode = res.statusCode;
|
|
131
|
-
response.statusMessage = res.statusMessage;
|
|
132
|
-
response.headers = res.headers;
|
|
133
|
-
response.body = data;
|
|
134
|
-
if (response.body && response.headers['content-type'] && response.headers['content-type'].includes('application/json'))
|
|
135
|
-
try {
|
|
136
|
-
response.body = (parse) ? parse(response.body) : JSON.parse(response.body);
|
|
137
|
-
log.debug('response.parse JSON');
|
|
138
|
-
}
|
|
139
|
-
catch (error) {
|
|
140
|
-
console.error(error);
|
|
141
|
-
}
|
|
142
|
-
if (response.statusCode >= 200 && response.statusCode < 400)
|
|
143
|
-
resolve(response);
|
|
144
|
-
else {
|
|
145
|
-
log.debug('response.error %j', response);
|
|
146
|
-
reject(response);
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
if (body)
|
|
152
|
-
req.write(body);
|
|
153
|
-
if (file) {
|
|
154
|
-
const crlf = '\r\n';
|
|
155
|
-
const boundary = `--${Math.random().toString(16)}`;
|
|
156
|
-
const delimiter = `${crlf}--${boundary}`;
|
|
157
|
-
const headers = [`Content-Disposition: form-data; name="file"; filename="${basename(file)}"${crlf}`];
|
|
158
|
-
const multipartBody = Buffer.concat([
|
|
159
|
-
Buffer.from(delimiter + crlf + headers.join('') + crlf),
|
|
160
|
-
readFileSync(file),
|
|
161
|
-
Buffer.from(`${delimiter}--`)
|
|
162
|
-
]);
|
|
163
|
-
req.setHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
|
|
164
|
-
req.setHeader('Content-Length', multipartBody.length);
|
|
165
|
-
req.write(multipartBody);
|
|
166
|
-
}
|
|
167
|
-
req.on('error', function (e) {
|
|
168
|
-
log.timeEnd(url, 'response.error %j', e);
|
|
169
|
-
reject(e);
|
|
170
|
-
});
|
|
171
|
-
log.time(url);
|
|
172
|
-
req.end();
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
export { request as default, querystringify, request, setMock };
|
package/lib/index.js
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var http = require('http');
|
|
6
|
-
var https = require('https');
|
|
7
|
-
var url = require('url');
|
|
8
|
-
var fs = require('fs');
|
|
9
|
-
var path = require('path');
|
|
10
|
-
var logger = require('@faasjs/logger');
|
|
11
|
-
|
|
12
|
-
function _interopNamespace(e) {
|
|
13
|
-
if (e && e.__esModule) return e;
|
|
14
|
-
var n = Object.create(null);
|
|
15
|
-
if (e) {
|
|
16
|
-
Object.keys(e).forEach(function (k) {
|
|
17
|
-
if (k !== 'default') {
|
|
18
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
19
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
20
|
-
enumerable: true,
|
|
21
|
-
get: function () { return e[k]; }
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
n["default"] = e;
|
|
27
|
-
return Object.freeze(n);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
var http__namespace = /*#__PURE__*/_interopNamespace(http);
|
|
31
|
-
var https__namespace = /*#__PURE__*/_interopNamespace(https);
|
|
32
|
-
|
|
33
|
-
let mock = null;
|
|
34
|
-
/**
|
|
35
|
-
* 设置模拟请求
|
|
36
|
-
* @param handler {function | null} 模拟函数,若设置为 null 则表示清除模拟函数
|
|
37
|
-
* @example setMock(async (url, options) => Promise.resolve({ headers: {}, statusCode: 200, body: { data: 'ok' } }))
|
|
38
|
-
*/
|
|
39
|
-
function setMock(handler) {
|
|
40
|
-
mock = handler;
|
|
41
|
-
}
|
|
42
|
-
function querystringify(obj) {
|
|
43
|
-
const pairs = [];
|
|
44
|
-
let value;
|
|
45
|
-
let key;
|
|
46
|
-
for (key in obj) {
|
|
47
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
48
|
-
value = obj[key];
|
|
49
|
-
if (!value && (value === null || value === undefined || isNaN(value))) {
|
|
50
|
-
value = '';
|
|
51
|
-
}
|
|
52
|
-
key = encodeURIComponent(key);
|
|
53
|
-
value = encodeURIComponent(value);
|
|
54
|
-
if (key === null || value === null)
|
|
55
|
-
continue;
|
|
56
|
-
pairs.push(key + '=' + value);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return pairs.length ? pairs.join('&') : '';
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* 发起网络请求
|
|
63
|
-
* @param {string} url 请求路径或完整网址
|
|
64
|
-
* @param {object=} [options={}] 参数和配置
|
|
65
|
-
* @param {string} [options.method=GET] 请求方法
|
|
66
|
-
* @param {object} [options.query={}] 请求参数,放置于 path 后,若需放置在 body 中,请使用 body 参数
|
|
67
|
-
* @param {object} [options.headers={}] 请求头
|
|
68
|
-
* @param {object=} options.body 请求体
|
|
69
|
-
* @param {number=} options.timeout 最长耗时,单位为毫秒
|
|
70
|
-
* @param {string=} options.auth HTTP 认证头,格式为 user:password
|
|
71
|
-
* @param {string=} options.file 上传文件的完整路径
|
|
72
|
-
* @param {WritableStream=} options.downloadStream 下载流,用于直接将响应内容保存到本地文件
|
|
73
|
-
* @param {Buffer=} options.pfx pfx
|
|
74
|
-
* @param {string=} options.passphrase passphrase
|
|
75
|
-
* @param {boolean=} options.agent agent
|
|
76
|
-
* @param {parse=} options.parse body 解析器,默认为 JSON.parse
|
|
77
|
-
*
|
|
78
|
-
* @returns {promise}
|
|
79
|
-
* @url https://faasjs.com/doc/request.html
|
|
80
|
-
*/
|
|
81
|
-
async function request(url$1, { headers, method, query, body, timeout, auth, file, downloadStream, pfx, passphrase, agent, parse } = {
|
|
82
|
-
headers: {},
|
|
83
|
-
query: {}
|
|
84
|
-
}) {
|
|
85
|
-
const log = new logger.Logger('request');
|
|
86
|
-
if (mock)
|
|
87
|
-
return mock(url$1, {
|
|
88
|
-
headers,
|
|
89
|
-
method,
|
|
90
|
-
query,
|
|
91
|
-
body
|
|
92
|
-
});
|
|
93
|
-
// 序列化 query
|
|
94
|
-
if (query) {
|
|
95
|
-
if (!url$1.includes('?'))
|
|
96
|
-
url$1 += '?';
|
|
97
|
-
else if (!url$1.endsWith('?'))
|
|
98
|
-
url$1 += '&';
|
|
99
|
-
url$1 += querystringify(query);
|
|
100
|
-
}
|
|
101
|
-
// 处理 URL 并生成 options
|
|
102
|
-
const uri = new url.URL(url$1);
|
|
103
|
-
const protocol = uri.protocol === 'https:' ? https__namespace : http__namespace;
|
|
104
|
-
if (!uri.protocol)
|
|
105
|
-
throw Error('Unknown protocol');
|
|
106
|
-
const options = {
|
|
107
|
-
headers: {},
|
|
108
|
-
host: uri.host ? uri.host.replace(/:[0-9]+$/, '') : uri.host,
|
|
109
|
-
method: method ? method.toUpperCase() : 'GET',
|
|
110
|
-
path: uri.pathname + uri.search,
|
|
111
|
-
query: {},
|
|
112
|
-
port: uri.port,
|
|
113
|
-
timeout,
|
|
114
|
-
auth,
|
|
115
|
-
pfx,
|
|
116
|
-
passphrase,
|
|
117
|
-
agent
|
|
118
|
-
};
|
|
119
|
-
// 处理 headers
|
|
120
|
-
for (const key in headers)
|
|
121
|
-
if (typeof headers[key] !== 'undefined' && headers[key] !== null)
|
|
122
|
-
options.headers[key] = headers[key];
|
|
123
|
-
// 序列化 body
|
|
124
|
-
if (body && typeof body !== 'string')
|
|
125
|
-
if (options.headers['Content-Type'] &&
|
|
126
|
-
options.headers['Content-Type'].toString().includes('application/x-www-form-urlencoded'))
|
|
127
|
-
body = querystringify(body);
|
|
128
|
-
else
|
|
129
|
-
body = JSON.stringify(body);
|
|
130
|
-
if (body && !options.headers['Content-Length'])
|
|
131
|
-
options.headers['Content-Length'] = Buffer.byteLength(body);
|
|
132
|
-
return await new Promise(function (resolve, reject) {
|
|
133
|
-
log.debug('request %j', {
|
|
134
|
-
...options,
|
|
135
|
-
body
|
|
136
|
-
});
|
|
137
|
-
const req = protocol.request(options, function (res) {
|
|
138
|
-
if (downloadStream) {
|
|
139
|
-
res.pipe(downloadStream);
|
|
140
|
-
downloadStream.on('finish', function () {
|
|
141
|
-
resolve(undefined);
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
const raw = [];
|
|
146
|
-
res.on('data', (chunk) => {
|
|
147
|
-
raw.push(chunk);
|
|
148
|
-
});
|
|
149
|
-
res.on('end', () => {
|
|
150
|
-
const data = Buffer.concat(raw).toString();
|
|
151
|
-
log.timeEnd(url$1, 'response %s %s %s', res.statusCode, res.headers['content-type'], data);
|
|
152
|
-
const response = Object.create(null);
|
|
153
|
-
response.request = options;
|
|
154
|
-
response.request.body = body;
|
|
155
|
-
response.statusCode = res.statusCode;
|
|
156
|
-
response.statusMessage = res.statusMessage;
|
|
157
|
-
response.headers = res.headers;
|
|
158
|
-
response.body = data;
|
|
159
|
-
if (response.body && response.headers['content-type'] && response.headers['content-type'].includes('application/json'))
|
|
160
|
-
try {
|
|
161
|
-
response.body = (parse) ? parse(response.body) : JSON.parse(response.body);
|
|
162
|
-
log.debug('response.parse JSON');
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
console.error(error);
|
|
166
|
-
}
|
|
167
|
-
if (response.statusCode >= 200 && response.statusCode < 400)
|
|
168
|
-
resolve(response);
|
|
169
|
-
else {
|
|
170
|
-
log.debug('response.error %j', response);
|
|
171
|
-
reject(response);
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
if (body)
|
|
177
|
-
req.write(body);
|
|
178
|
-
if (file) {
|
|
179
|
-
const crlf = '\r\n';
|
|
180
|
-
const boundary = `--${Math.random().toString(16)}`;
|
|
181
|
-
const delimiter = `${crlf}--${boundary}`;
|
|
182
|
-
const headers = [`Content-Disposition: form-data; name="file"; filename="${path.basename(file)}"${crlf}`];
|
|
183
|
-
const multipartBody = Buffer.concat([
|
|
184
|
-
Buffer.from(delimiter + crlf + headers.join('') + crlf),
|
|
185
|
-
fs.readFileSync(file),
|
|
186
|
-
Buffer.from(`${delimiter}--`)
|
|
187
|
-
]);
|
|
188
|
-
req.setHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
|
|
189
|
-
req.setHeader('Content-Length', multipartBody.length);
|
|
190
|
-
req.write(multipartBody);
|
|
191
|
-
}
|
|
192
|
-
req.on('error', function (e) {
|
|
193
|
-
log.timeEnd(url$1, 'response.error %j', e);
|
|
194
|
-
reject(e);
|
|
195
|
-
});
|
|
196
|
-
log.time(url$1);
|
|
197
|
-
req.end();
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
exports["default"] = request;
|
|
202
|
-
exports.querystringify = querystringify;
|
|
203
|
-
exports.request = request;
|
|
204
|
-
exports.setMock = setMock;
|