@faasjs/request 0.0.2-beta.87 → 0.0.3-beta.2

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
@@ -1,9 +1,157 @@
1
1
  # @faasjs/request
2
2
 
3
- 网络请求库
4
-
5
- [![License: MIT](https://img.shields.io/npm/l/@faasjs/request.svg)](https://github.com/faasjs/faasjs/blob/master/packages/faasjs/request/LICENSE)
3
+ [![License: MIT](https://img.shields.io/npm/l/@faasjs/request.svg)](https://github.com/faasjs/faasjs/blob/main/packages/faasjs/request/LICENSE)
6
4
  [![NPM Stable Version](https://img.shields.io/npm/v/@faasjs/request/stable.svg)](https://www.npmjs.com/package/@faasjs/request)
7
5
  [![NPM Beta Version](https://img.shields.io/npm/v/@faasjs/request/beta.svg)](https://www.npmjs.com/package/@faasjs/request)
8
6
 
7
+ FaasJS's request module.
8
+
9
+ ## Install
10
+
11
+ npm install @faasjs/request
12
+
13
+ ## Modules
14
+
15
+ ### Type Aliases
16
+
17
+ - [Request](#request)
18
+ - [RequestOptions](#requestoptions)
19
+ - [Response](#response)
20
+
21
+ ### Functions
22
+
23
+ - [querystringify](#querystringify)
24
+ - [request](#request-1)
25
+ - [setMock](#setmock)
26
+
27
+ ## Type Aliases
28
+
29
+ ### Request
30
+
31
+ Ƭ **Request**: `Object`
32
+
33
+ #### Type declaration
34
+
35
+ | Name | Type |
36
+ | :------ | :------ |
37
+ | `body?` | { `[key: string]`: `any`; } |
38
+ | `headers?` | `http.OutgoingHttpHeaders` |
39
+ | `host?` | `string` |
40
+ | `method?` | `string` |
41
+ | `path?` | `string` |
42
+ | `query?` | `http.OutgoingHttpHeaders` |
43
+
44
+ ___
45
+
46
+ ### RequestOptions
47
+
48
+ Ƭ **RequestOptions**: `Object`
49
+
50
+ #### Type declaration
51
+
52
+ | Name | Type | Description |
53
+ | :------ | :------ | :------ |
54
+ | `agent?` | `boolean` | - |
55
+ | `auth?` | `string` | The authentication credentials to use for the request. Format: `username:password` |
56
+ | `body?` | { `[key: string]`: `any`; } \| `string` | - |
57
+ | `downloadStream?` | `NodeJS.WritableStream` | Create a write stream to download a file. |
58
+ | `file?` | `string` | Path of uploading a file to the server. |
59
+ | `headers?` | `http.OutgoingHttpHeaders` | - |
60
+ | `logger?` | `Logger` | - |
61
+ | `method?` | `string` | The HTTP method to use when making the request. Defaults to GET. |
62
+ | `parse?` | (`body`: `string`) => `any` | Body parser. Defaults to `JSON.parse`. |
63
+ | `passphrase?` | `string` | - |
64
+ | `pfx?` | `Buffer` | - |
65
+ | `query?` | { `[key: string]`: `any`; } | - |
66
+ | `timeout?` | `number` | - |
67
+
68
+ ___
69
+
70
+ ### Response
71
+
72
+ Ƭ **Response**<`T`\>: `Object`
73
+
74
+ #### Type parameters
75
+
76
+ | Name | Type |
77
+ | :------ | :------ |
78
+ | `T` | `any` |
79
+
80
+ #### Type declaration
81
+
82
+ | Name | Type |
83
+ | :------ | :------ |
84
+ | `body` | `T` |
85
+ | `headers` | `http.OutgoingHttpHeaders` |
86
+ | `request?` | [`Request`](#request) |
87
+ | `statusCode?` | `number` |
88
+ | `statusMessage?` | `string` |
89
+
90
+ ## Functions
91
+
92
+ ### querystringify
93
+
94
+ ▸ **querystringify**(`obj`): `string`
95
+
96
+ #### Parameters
97
+
98
+ | Name | Type |
99
+ | :------ | :------ |
100
+ | `obj` | `any` |
101
+
102
+ #### Returns
103
+
104
+ `string`
105
+
106
+ ___
107
+
108
+ ### request
109
+
110
+ ▸ **request**<`T`\>(`url`, `options?`): `Promise`<[`Response`](#response)<`T`\>\>
111
+
112
+ Request
113
+
114
+ **`Url`**
115
+
9
116
  https://faasjs.com/doc/request.html
117
+
118
+ #### Type parameters
119
+
120
+ | Name | Type |
121
+ | :------ | :------ |
122
+ | `T` | `any` |
123
+
124
+ #### Parameters
125
+
126
+ | Name | Type | Description |
127
+ | :------ | :------ | :------ |
128
+ | `url` | `string` | Url |
129
+ | `options?` | [`RequestOptions`](#requestoptions) | Options |
130
+
131
+ #### Returns
132
+
133
+ `Promise`<[`Response`](#response)<`T`\>\>
134
+
135
+ ___
136
+
137
+ ### setMock
138
+
139
+ ▸ **setMock**(`handler`): `void`
140
+
141
+ Mock requests
142
+
143
+ **`Example`**
144
+
145
+ ```ts
146
+ setMock(async (url, options) => Promise.resolve({ headers: {}, statusCode: 200, body: { data: 'ok' } }))
147
+ ```
148
+
149
+ #### Parameters
150
+
151
+ | Name | Type | Description |
152
+ | :------ | :------ | :------ |
153
+ | `handler` | `Mock` | {function \| null} null to disable mock |
154
+
155
+ #### Returns
156
+
157
+ `void`
@@ -0,0 +1,87 @@
1
+ import * as http from 'http';
2
+ import { Logger } from '@faasjs/logger';
3
+
4
+ type Request = {
5
+ headers?: http.OutgoingHttpHeaders;
6
+ method?: string;
7
+ host?: string;
8
+ path?: string;
9
+ query?: http.OutgoingHttpHeaders;
10
+ body?: {
11
+ [key: string]: any;
12
+ };
13
+ };
14
+ type Response<T = any> = {
15
+ request?: Request;
16
+ statusCode?: number;
17
+ statusMessage?: string;
18
+ headers: http.OutgoingHttpHeaders;
19
+ body: T;
20
+ };
21
+ type RequestOptions = {
22
+ headers?: http.OutgoingHttpHeaders;
23
+ /**
24
+ * The HTTP method to use when making the request. Defaults to GET.
25
+ */
26
+ method?: string;
27
+ query?: {
28
+ [key: string]: any;
29
+ };
30
+ body?: {
31
+ [key: string]: any;
32
+ } | string;
33
+ timeout?: number;
34
+ /**
35
+ * The authentication credentials to use for the request.
36
+ *
37
+ * Format: `username:password`
38
+ */
39
+ auth?: string;
40
+ /**
41
+ * Path of uploading a file to the server.
42
+ */
43
+ file?: string;
44
+ /**
45
+ * Create a write stream to download a file.
46
+ */
47
+ downloadStream?: NodeJS.WritableStream;
48
+ pfx?: Buffer;
49
+ passphrase?: string;
50
+ agent?: boolean;
51
+ /**
52
+ * Body parser. Defaults to `JSON.parse`.
53
+ */
54
+ parse?: (body: string) => any;
55
+ logger?: Logger;
56
+ };
57
+ type Mock = (url: string, options: RequestOptions) => Promise<Response>;
58
+ /**
59
+ * Mock requests
60
+ * @param handler {function | null} null to disable mock
61
+ * @example setMock(async (url, options) => Promise.resolve({ headers: {}, statusCode: 200, body: { data: 'ok' } }))
62
+ */
63
+ declare function setMock(handler: Mock | null): void;
64
+ declare function querystringify(obj: any): string;
65
+ /**
66
+ * Request
67
+ * @param {string} url Url
68
+ * @param {object=} [options={}] Options
69
+ * @param {string} [options.method=GET] Method
70
+ * @param {object} [options.query={}] Query
71
+ * @param {object} [options.headers={}] Headers
72
+ * @param {object=} options.body Body
73
+ * @param {number=} options.timeout Timeout
74
+ * @param {string=} options.auth Auth, format: user:password
75
+ * @param {string=} options.file Upload file path
76
+ * @param {WritableStream=} options.downloadStream Download stream
77
+ * @param {Buffer=} options.pfx pfx
78
+ * @param {string=} options.passphrase passphrase
79
+ * @param {boolean=} options.agent agent
80
+ * @param {parse=} options.parse body parser, default is JSON.parse
81
+ *
82
+ * @returns {promise}
83
+ * @url https://faasjs.com/doc/request.html
84
+ */
85
+ declare function request<T = any>(url: string, { headers, method, query, body, timeout, auth, file, downloadStream, pfx, passphrase, agent, parse, logger, }?: RequestOptions): Promise<Response<T>>;
86
+
87
+ export { Request, RequestOptions, Response, querystringify, request, setMock };
package/dist/index.js ADDED
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
25
+
26
+ // src/index.ts
27
+ var src_exports = {};
28
+ __export(src_exports, {
29
+ querystringify: () => querystringify,
30
+ request: () => request,
31
+ setMock: () => setMock
32
+ });
33
+ module.exports = __toCommonJS(src_exports);
34
+ var http = __toESM(require("http"));
35
+ var https = __toESM(require("https"));
36
+ var import_url = require("url");
37
+ var import_fs = require("fs");
38
+ var import_path = require("path");
39
+ var import_logger = require("@faasjs/logger");
40
+ var mock = null;
41
+ function setMock(handler) {
42
+ mock = handler;
43
+ }
44
+ function querystringify(obj) {
45
+ const pairs = [];
46
+ let value;
47
+ let key;
48
+ for (key in obj) {
49
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
50
+ value = obj[key];
51
+ if (!value && (value === null || value === void 0 || isNaN(value))) {
52
+ value = "";
53
+ }
54
+ key = encodeURIComponent(key);
55
+ value = encodeURIComponent(value);
56
+ if (key === null || value === null)
57
+ continue;
58
+ pairs.push(key + "=" + value);
59
+ }
60
+ }
61
+ return pairs.length ? pairs.join("&") : "";
62
+ }
63
+ async function request(url, {
64
+ headers,
65
+ method,
66
+ query,
67
+ body,
68
+ timeout,
69
+ auth,
70
+ file,
71
+ downloadStream,
72
+ pfx,
73
+ passphrase,
74
+ agent,
75
+ parse,
76
+ logger
77
+ } = { headers: {} }) {
78
+ if (!logger)
79
+ logger = new import_logger.Logger("request");
80
+ if (mock)
81
+ return mock(url, {
82
+ headers,
83
+ method,
84
+ query,
85
+ body
86
+ });
87
+ if (query) {
88
+ if (!url.includes("?"))
89
+ url += "?";
90
+ else if (!url.endsWith("?"))
91
+ url += "&";
92
+ url += querystringify(query);
93
+ }
94
+ const uri = new import_url.URL(url);
95
+ const protocol = uri.protocol === "https:" ? https : http;
96
+ if (!uri.protocol)
97
+ throw Error("Unknown protocol");
98
+ const options = {
99
+ headers: {},
100
+ host: uri.host ? uri.host.replace(/:[0-9]+$/, "") : uri.host,
101
+ method: method ? method.toUpperCase() : "GET",
102
+ path: uri.pathname + uri.search,
103
+ port: uri.port,
104
+ timeout,
105
+ auth,
106
+ pfx,
107
+ passphrase,
108
+ agent
109
+ };
110
+ for (const key in headers)
111
+ if (typeof headers[key] !== "undefined" && headers[key] !== null)
112
+ options.headers[key] = headers[key];
113
+ if (body && typeof body !== "string")
114
+ if (options.headers["Content-Type"] && options.headers["Content-Type"].toString().includes("application/x-www-form-urlencoded"))
115
+ body = querystringify(body);
116
+ else
117
+ body = JSON.stringify(body);
118
+ if (body && !options.headers["Content-Length"])
119
+ options.headers["Content-Length"] = Buffer.byteLength(body);
120
+ return await new Promise(function(resolve, reject) {
121
+ logger.debug("request %j", {
122
+ ...options,
123
+ body
124
+ });
125
+ const req = protocol.request(options, function(res) {
126
+ if (downloadStream) {
127
+ res.pipe(downloadStream);
128
+ downloadStream.on("finish", function() {
129
+ resolve(void 0);
130
+ });
131
+ } else {
132
+ const raw = [];
133
+ res.on("data", (chunk) => {
134
+ raw.push(chunk);
135
+ });
136
+ res.on("end", () => {
137
+ const data = Buffer.concat(raw).toString();
138
+ logger.timeEnd(url, "response %s %s %s", res.statusCode, res.headers["content-type"], data);
139
+ const response = /* @__PURE__ */ Object.create(null);
140
+ response.request = options;
141
+ response.request.body = body;
142
+ response.statusCode = res.statusCode;
143
+ response.statusMessage = res.statusMessage;
144
+ response.headers = res.headers;
145
+ response.body = data;
146
+ if (response.body && response.headers["content-type"] && response.headers["content-type"].includes("application/json"))
147
+ try {
148
+ response.body = parse ? parse(response.body) : JSON.parse(response.body);
149
+ logger.debug("response.parse JSON");
150
+ } catch (error) {
151
+ console.warn("response plain body", response.body);
152
+ console.error(error);
153
+ }
154
+ if (response.statusCode >= 200 && response.statusCode < 400)
155
+ resolve(response);
156
+ else {
157
+ logger.debug("response.error %j", response);
158
+ reject(response);
159
+ }
160
+ });
161
+ }
162
+ });
163
+ if (body)
164
+ req.write(body);
165
+ if (file) {
166
+ const crlf = "\r\n";
167
+ const boundary = `--${Math.random().toString(16)}`;
168
+ const delimiter = `${crlf}--${boundary}`;
169
+ const headers2 = [`Content-Disposition: form-data; name="file"; filename="${(0, import_path.basename)(file)}"${crlf}`];
170
+ const multipartBody = Buffer.concat([
171
+ Buffer.from(delimiter + crlf + headers2.join("") + crlf),
172
+ (0, import_fs.readFileSync)(file),
173
+ Buffer.from(`${delimiter}--`)
174
+ ]);
175
+ req.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
176
+ req.setHeader("Content-Length", multipartBody.length);
177
+ req.write(multipartBody);
178
+ }
179
+ req.on("error", function(e) {
180
+ logger.timeEnd(url, "response.error %j", e);
181
+ reject(e);
182
+ });
183
+ logger.time(url);
184
+ req.end();
185
+ });
186
+ }
187
+ // Annotate the CommonJS export names for ESM import in node:
188
+ 0 && (module.exports = {
189
+ querystringify,
190
+ request,
191
+ setMock
192
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,159 @@
1
+ // src/index.ts
2
+ import * as http from "http";
3
+ import * as https from "https";
4
+ import { URL } from "url";
5
+ import { readFileSync } from "fs";
6
+ import { basename } from "path";
7
+ import { Logger } from "@faasjs/logger";
8
+ var mock = null;
9
+ function setMock(handler) {
10
+ mock = handler;
11
+ }
12
+ function querystringify(obj) {
13
+ const pairs = [];
14
+ let value;
15
+ let key;
16
+ for (key in obj) {
17
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
18
+ value = obj[key];
19
+ if (!value && (value === null || value === void 0 || isNaN(value))) {
20
+ value = "";
21
+ }
22
+ key = encodeURIComponent(key);
23
+ value = encodeURIComponent(value);
24
+ if (key === null || value === null)
25
+ continue;
26
+ pairs.push(key + "=" + value);
27
+ }
28
+ }
29
+ return pairs.length ? pairs.join("&") : "";
30
+ }
31
+ async function request(url, {
32
+ headers,
33
+ method,
34
+ query,
35
+ body,
36
+ timeout,
37
+ auth,
38
+ file,
39
+ downloadStream,
40
+ pfx,
41
+ passphrase,
42
+ agent,
43
+ parse,
44
+ logger
45
+ } = { headers: {} }) {
46
+ if (!logger)
47
+ logger = new Logger("request");
48
+ if (mock)
49
+ return mock(url, {
50
+ headers,
51
+ method,
52
+ query,
53
+ body
54
+ });
55
+ if (query) {
56
+ if (!url.includes("?"))
57
+ url += "?";
58
+ else if (!url.endsWith("?"))
59
+ url += "&";
60
+ url += querystringify(query);
61
+ }
62
+ const uri = new URL(url);
63
+ const protocol = uri.protocol === "https:" ? https : http;
64
+ if (!uri.protocol)
65
+ throw Error("Unknown protocol");
66
+ const options = {
67
+ headers: {},
68
+ host: uri.host ? uri.host.replace(/:[0-9]+$/, "") : uri.host,
69
+ method: method ? method.toUpperCase() : "GET",
70
+ path: uri.pathname + uri.search,
71
+ port: uri.port,
72
+ timeout,
73
+ auth,
74
+ pfx,
75
+ passphrase,
76
+ agent
77
+ };
78
+ for (const key in headers)
79
+ if (typeof headers[key] !== "undefined" && headers[key] !== null)
80
+ options.headers[key] = headers[key];
81
+ if (body && typeof body !== "string")
82
+ if (options.headers["Content-Type"] && options.headers["Content-Type"].toString().includes("application/x-www-form-urlencoded"))
83
+ body = querystringify(body);
84
+ else
85
+ body = JSON.stringify(body);
86
+ if (body && !options.headers["Content-Length"])
87
+ options.headers["Content-Length"] = Buffer.byteLength(body);
88
+ return await new Promise(function(resolve, reject) {
89
+ logger.debug("request %j", {
90
+ ...options,
91
+ body
92
+ });
93
+ const req = protocol.request(options, function(res) {
94
+ if (downloadStream) {
95
+ res.pipe(downloadStream);
96
+ downloadStream.on("finish", function() {
97
+ resolve(void 0);
98
+ });
99
+ } else {
100
+ const raw = [];
101
+ res.on("data", (chunk) => {
102
+ raw.push(chunk);
103
+ });
104
+ res.on("end", () => {
105
+ const data = Buffer.concat(raw).toString();
106
+ logger.timeEnd(url, "response %s %s %s", res.statusCode, res.headers["content-type"], data);
107
+ const response = /* @__PURE__ */ Object.create(null);
108
+ response.request = options;
109
+ response.request.body = body;
110
+ response.statusCode = res.statusCode;
111
+ response.statusMessage = res.statusMessage;
112
+ response.headers = res.headers;
113
+ response.body = data;
114
+ if (response.body && response.headers["content-type"] && response.headers["content-type"].includes("application/json"))
115
+ try {
116
+ response.body = parse ? parse(response.body) : JSON.parse(response.body);
117
+ logger.debug("response.parse JSON");
118
+ } catch (error) {
119
+ console.warn("response plain body", response.body);
120
+ console.error(error);
121
+ }
122
+ if (response.statusCode >= 200 && response.statusCode < 400)
123
+ resolve(response);
124
+ else {
125
+ logger.debug("response.error %j", response);
126
+ reject(response);
127
+ }
128
+ });
129
+ }
130
+ });
131
+ if (body)
132
+ req.write(body);
133
+ if (file) {
134
+ const crlf = "\r\n";
135
+ const boundary = `--${Math.random().toString(16)}`;
136
+ const delimiter = `${crlf}--${boundary}`;
137
+ const headers2 = [`Content-Disposition: form-data; name="file"; filename="${basename(file)}"${crlf}`];
138
+ const multipartBody = Buffer.concat([
139
+ Buffer.from(delimiter + crlf + headers2.join("") + crlf),
140
+ readFileSync(file),
141
+ Buffer.from(`${delimiter}--`)
142
+ ]);
143
+ req.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
144
+ req.setHeader("Content-Length", multipartBody.length);
145
+ req.write(multipartBody);
146
+ }
147
+ req.on("error", function(e) {
148
+ logger.timeEnd(url, "response.error %j", e);
149
+ reject(e);
150
+ });
151
+ logger.time(url);
152
+ req.end();
153
+ });
154
+ }
155
+ export {
156
+ querystringify,
157
+ request,
158
+ setMock
159
+ };
package/package.json CHANGED
@@ -1,26 +1,31 @@
1
1
  {
2
2
  "name": "@faasjs/request",
3
- "version": "0.0.2-beta.87",
3
+ "version": "0.0.3-beta.2",
4
4
  "license": "MIT",
5
- "main": "lib/index.js",
6
- "module": "lib/index.es.js",
7
- "types": "lib/index.d.ts",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "homepage": "https://faasjs.com/doc/request",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/faasjs/faasjs.git",
11
+ "directory": "packages/request"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/faasjs/faasjs/issues"
15
+ },
16
+ "funding": "https://github.com/sponsors/faasjs",
8
17
  "scripts": {
9
- "prepack": "rm -rf ./lib && rollup -c && mv lib/*/src/* lib/"
18
+ "build": "tsup-node src/index.ts --format esm,cjs",
19
+ "build:types": "tsup-node src/index.ts --dts-only"
10
20
  },
11
21
  "files": [
12
- "lib"
22
+ "dist"
13
23
  ],
14
24
  "dependencies": {
15
- "@faasjs/logger": "^0.0.2-beta.69"
16
- },
17
- "devDependencies": {
18
- "@types/debug": "*",
19
- "@types/jest": "*",
20
- "@types/node": "*",
21
- "rollup": "*",
22
- "rollup-plugin-typescript2": "*",
23
- "typescript": "*"
25
+ "@faasjs/logger": "^0.0.3-beta.2"
24
26
  },
25
- "gitHead": "f2af1e2dd131245a0075728ace54387bc2ab7262"
27
+ "engines": {
28
+ "npm": ">=8.0.0",
29
+ "node": ">=16.0.0"
30
+ }
26
31
  }
package/lib/index.d.ts DELETED
@@ -1,50 +0,0 @@
1
- /// <reference types="node" />
2
- import * as http from 'http';
3
- export interface Request {
4
- headers?: http.OutgoingHttpHeaders;
5
- method?: string;
6
- host?: string;
7
- path?: string;
8
- query?: http.OutgoingHttpHeaders;
9
- body?: any;
10
- }
11
- export interface Response<T = any> {
12
- request?: Request;
13
- statusCode?: number;
14
- statusMessage?: string;
15
- headers: http.OutgoingHttpHeaders;
16
- body: T;
17
- }
18
- export interface RequestOptions {
19
- headers?: http.OutgoingHttpHeaders;
20
- method?: string;
21
- query?: http.OutgoingHttpHeaders;
22
- body?: any;
23
- timeout?: number;
24
- auth?: string;
25
- file?: string;
26
- downloadStream?: NodeJS.WritableStream;
27
- }
28
- declare type Mock = (url: string, options: RequestOptions) => Promise<Response>;
29
- /**
30
- * 设置模拟请求
31
- * @param handler {function | null} 模拟函数,若设置为 null 则表示清除模拟函数
32
- */
33
- export declare function setMock(handler: Mock | null): void;
34
- /**
35
- * 发起网络请求
36
- * @param {string} url 请求路径或完整网址
37
- * @param {object=} [options={}] 参数和配置
38
- * @param {string} [options.methd=GET] 请求方法
39
- * @param {object} [options.query={}] 请求参数,放置于 path 后,若需放置在 body 中,请使用 body 参数
40
- * @param {object} [options.headers={}] 请求头
41
- * @param {object=} options.body 请求体
42
- * @param {number=} options.timeout 最长耗时,单位为毫秒
43
- * @param {string=} options.auth HTTP 认证头,格式为 user:password
44
- * @param {string=} options.file 上传文件的完整路径
45
- * @param {WritableStream=} options.downloadStream 下载流,用于直接将响应内容保存到本地文件
46
- *
47
- * @returns {promise}
48
- */
49
- export default function request<T = any>(url: string, { headers, method, query, body, timeout, auth, file, downloadStream }?: RequestOptions): Promise<Response<T>>;
50
- export {};
package/lib/index.es.js DELETED
@@ -1,156 +0,0 @@
1
- import * as http from 'http';
2
- import * as https from 'https';
3
- import { stringify } from 'querystring';
4
- import { parse } from 'url';
5
- import { readFileSync } from 'fs';
6
- import { basename } from 'path';
7
- import Logger from '@faasjs/logger';
8
-
9
- let mock = null;
10
- /**
11
- * 设置模拟请求
12
- * @param handler {function | null} 模拟函数,若设置为 null 则表示清除模拟函数
13
- */
14
- function setMock(handler) {
15
- mock = handler;
16
- }
17
- /**
18
- * 发起网络请求
19
- * @param {string} url 请求路径或完整网址
20
- * @param {object=} [options={}] 参数和配置
21
- * @param {string} [options.methd=GET] 请求方法
22
- * @param {object} [options.query={}] 请求参数,放置于 path 后,若需放置在 body 中,请使用 body 参数
23
- * @param {object} [options.headers={}] 请求头
24
- * @param {object=} options.body 请求体
25
- * @param {number=} options.timeout 最长耗时,单位为毫秒
26
- * @param {string=} options.auth HTTP 认证头,格式为 user:password
27
- * @param {string=} options.file 上传文件的完整路径
28
- * @param {WritableStream=} options.downloadStream 下载流,用于直接将响应内容保存到本地文件
29
- *
30
- * @returns {promise}
31
- */
32
- async function request(url, { headers, method, query, body, timeout, auth, file, downloadStream } = {
33
- headers: {},
34
- query: {},
35
- }) {
36
- const log = new Logger('request');
37
- log.debug('request %s %O', url, {
38
- body,
39
- headers,
40
- method,
41
- query,
42
- });
43
- if (mock)
44
- return mock(url, {
45
- headers,
46
- method,
47
- query,
48
- body
49
- });
50
- // 序列化 query
51
- if (query) {
52
- if (!url.includes('?'))
53
- url += '?';
54
- else if (!url.endsWith('?'))
55
- url += '&';
56
- url += stringify(query);
57
- }
58
- // 处理 URL 并生成 options
59
- const uri = parse(url);
60
- const protocol = uri.protocol === 'https:' ? https : http;
61
- if (!uri.protocol)
62
- throw Error('Unkonw protocol');
63
- const options = {
64
- headers: {},
65
- host: uri.host ? uri.host.replace(/:[0-9]+$/, '') : uri.host,
66
- method: method ? method.toUpperCase() : 'GET',
67
- path: uri.path,
68
- query: {},
69
- port: uri.port,
70
- timeout,
71
- auth
72
- };
73
- // 处理 headers
74
- for (const key in headers)
75
- if (typeof headers[key] !== 'undefined' && headers[key] !== null)
76
- options.headers[key] = headers[key];
77
- // 序列化 body
78
- if (body && typeof body !== 'string')
79
- if (options.headers['Content-Type'] &&
80
- options.headers['Content-Type'].toString().includes('application/x-www-form-urlencoded'))
81
- body = stringify(body);
82
- else
83
- body = JSON.stringify(body);
84
- if (body && !options.headers['Content-Length'])
85
- options.headers['Content-Length'] = Buffer.byteLength(body);
86
- return new Promise(function (resolve, reject) {
87
- // 包裹请求
88
- const req = protocol.request(options, function (res) {
89
- if (downloadStream) {
90
- res.pipe(downloadStream);
91
- downloadStream.on('finish', function () {
92
- resolve();
93
- });
94
- }
95
- else {
96
- const raw = [];
97
- res.on('data', (chunk) => {
98
- raw.push(chunk);
99
- });
100
- res.on('end', () => {
101
- const data = Buffer.concat(raw).toString();
102
- log.timeEnd(url, 'response %s %s %s', res.statusCode, res.headers['content-type'], data);
103
- const response = Object.create(null);
104
- response.request = options;
105
- response.request.body = body;
106
- response.statusCode = res.statusCode;
107
- response.statusMessage = res.statusMessage;
108
- response.headers = res.headers;
109
- response.body = data;
110
- if (response.body && response.headers['content-type'] && response.headers['content-type'].includes('application/json'))
111
- try {
112
- response.body = JSON.parse(response.body);
113
- log.debug('response.parse JSON');
114
- }
115
- catch (error) {
116
- console.error(error);
117
- }
118
- if (response.statusCode >= 200 && response.statusCode < 400)
119
- resolve(response);
120
- else {
121
- log.debug('response.error %O', response);
122
- reject(response);
123
- }
124
- });
125
- }
126
- });
127
- if (body)
128
- req.write(body);
129
- if (file) {
130
- const crlf = '\r\n';
131
- const boundary = `--${Math.random().toString(16)}`;
132
- const delimeter = `${crlf}--${boundary}`;
133
- const headers = [
134
- `Content-Disposition: form-data; name="file"; filename="${basename(file)}"${crlf}`
135
- ];
136
- const multipartBody = Buffer.concat([
137
- new Buffer(delimeter + crlf + headers.join('') + crlf),
138
- readFileSync(file),
139
- new Buffer(`${delimeter}--`)
140
- ]);
141
- req.setHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
142
- req.setHeader('Content-Length', multipartBody.length);
143
- req.write(multipartBody);
144
- }
145
- req.on('error', function (e) {
146
- log.timeEnd(url, 'response.error %O', e);
147
- reject(e);
148
- });
149
- // 发送请求
150
- log.time(url);
151
- req.end();
152
- });
153
- }
154
-
155
- export default request;
156
- export { setMock };
package/lib/index.js DELETED
@@ -1,162 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
-
7
- var http = require('http');
8
- var https = require('https');
9
- var querystring = require('querystring');
10
- var URL = require('url');
11
- var fs = require('fs');
12
- var path = require('path');
13
- var Logger = _interopDefault(require('@faasjs/logger'));
14
-
15
- let mock = null;
16
- /**
17
- * 设置模拟请求
18
- * @param handler {function | null} 模拟函数,若设置为 null 则表示清除模拟函数
19
- */
20
- function setMock(handler) {
21
- mock = handler;
22
- }
23
- /**
24
- * 发起网络请求
25
- * @param {string} url 请求路径或完整网址
26
- * @param {object=} [options={}] 参数和配置
27
- * @param {string} [options.methd=GET] 请求方法
28
- * @param {object} [options.query={}] 请求参数,放置于 path 后,若需放置在 body 中,请使用 body 参数
29
- * @param {object} [options.headers={}] 请求头
30
- * @param {object=} options.body 请求体
31
- * @param {number=} options.timeout 最长耗时,单位为毫秒
32
- * @param {string=} options.auth HTTP 认证头,格式为 user:password
33
- * @param {string=} options.file 上传文件的完整路径
34
- * @param {WritableStream=} options.downloadStream 下载流,用于直接将响应内容保存到本地文件
35
- *
36
- * @returns {promise}
37
- */
38
- async function request(url, { headers, method, query, body, timeout, auth, file, downloadStream } = {
39
- headers: {},
40
- query: {},
41
- }) {
42
- const log = new Logger('request');
43
- log.debug('request %s %O', url, {
44
- body,
45
- headers,
46
- method,
47
- query,
48
- });
49
- if (mock)
50
- return mock(url, {
51
- headers,
52
- method,
53
- query,
54
- body
55
- });
56
- // 序列化 query
57
- if (query) {
58
- if (!url.includes('?'))
59
- url += '?';
60
- else if (!url.endsWith('?'))
61
- url += '&';
62
- url += querystring.stringify(query);
63
- }
64
- // 处理 URL 并生成 options
65
- const uri = URL.parse(url);
66
- const protocol = uri.protocol === 'https:' ? https : http;
67
- if (!uri.protocol)
68
- throw Error('Unkonw protocol');
69
- const options = {
70
- headers: {},
71
- host: uri.host ? uri.host.replace(/:[0-9]+$/, '') : uri.host,
72
- method: method ? method.toUpperCase() : 'GET',
73
- path: uri.path,
74
- query: {},
75
- port: uri.port,
76
- timeout,
77
- auth
78
- };
79
- // 处理 headers
80
- for (const key in headers)
81
- if (typeof headers[key] !== 'undefined' && headers[key] !== null)
82
- options.headers[key] = headers[key];
83
- // 序列化 body
84
- if (body && typeof body !== 'string')
85
- if (options.headers['Content-Type'] &&
86
- options.headers['Content-Type'].toString().includes('application/x-www-form-urlencoded'))
87
- body = querystring.stringify(body);
88
- else
89
- body = JSON.stringify(body);
90
- if (body && !options.headers['Content-Length'])
91
- options.headers['Content-Length'] = Buffer.byteLength(body);
92
- return new Promise(function (resolve, reject) {
93
- // 包裹请求
94
- const req = protocol.request(options, function (res) {
95
- if (downloadStream) {
96
- res.pipe(downloadStream);
97
- downloadStream.on('finish', function () {
98
- resolve();
99
- });
100
- }
101
- else {
102
- const raw = [];
103
- res.on('data', (chunk) => {
104
- raw.push(chunk);
105
- });
106
- res.on('end', () => {
107
- const data = Buffer.concat(raw).toString();
108
- log.timeEnd(url, 'response %s %s %s', res.statusCode, res.headers['content-type'], data);
109
- const response = Object.create(null);
110
- response.request = options;
111
- response.request.body = body;
112
- response.statusCode = res.statusCode;
113
- response.statusMessage = res.statusMessage;
114
- response.headers = res.headers;
115
- response.body = data;
116
- if (response.body && response.headers['content-type'] && response.headers['content-type'].includes('application/json'))
117
- try {
118
- response.body = JSON.parse(response.body);
119
- log.debug('response.parse JSON');
120
- }
121
- catch (error) {
122
- console.error(error);
123
- }
124
- if (response.statusCode >= 200 && response.statusCode < 400)
125
- resolve(response);
126
- else {
127
- log.debug('response.error %O', response);
128
- reject(response);
129
- }
130
- });
131
- }
132
- });
133
- if (body)
134
- req.write(body);
135
- if (file) {
136
- const crlf = '\r\n';
137
- const boundary = `--${Math.random().toString(16)}`;
138
- const delimeter = `${crlf}--${boundary}`;
139
- const headers = [
140
- `Content-Disposition: form-data; name="file"; filename="${path.basename(file)}"${crlf}`
141
- ];
142
- const multipartBody = Buffer.concat([
143
- new Buffer(delimeter + crlf + headers.join('') + crlf),
144
- fs.readFileSync(file),
145
- new Buffer(`${delimeter}--`)
146
- ]);
147
- req.setHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
148
- req.setHeader('Content-Length', multipartBody.length);
149
- req.write(multipartBody);
150
- }
151
- req.on('error', function (e) {
152
- log.timeEnd(url, 'response.error %O', e);
153
- reject(e);
154
- });
155
- // 发送请求
156
- log.time(url);
157
- req.end();
158
- });
159
- }
160
-
161
- exports.default = request;
162
- exports.setMock = setMock;