xjs-node 1.0.3 → 1.0.5

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
@@ -58,7 +58,7 @@ import { HttpResolver, s_clientMode } from "xjs-node";
58
58
  const context = http.newContext();
59
59
  res = await context.get("https://begyyal.net/1");
60
60
  // this request sends with cookies that is set by precedent requests.
61
- // in POST, payload is treated as json if it is an object.
61
+ // in POST, payload is treated as json if it is an object. (but also Stream is acceptable.)
62
62
  res = await context.post("https://begyyal.net/2", { a: "b" });
63
63
  })();
64
64
  ```
@@ -1,7 +1,5 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="node" />
3
- import { OutgoingHttpHeaders, IncomingHttpHeaders } from "http";
4
- import { ClientOption, IHttpClient } from "./i-http-client";
2
+ import { ClientOption, HttpResponse, IHttpClient, RequestOption } from "./i-http-client";
5
3
  import { Loggable } from "xjs-common";
6
4
  export declare const s_clientMode: {
7
5
  nodejs: {
@@ -28,70 +26,24 @@ export declare class HttpResolverContext implements IHttpClient {
28
26
  private _cookies?;
29
27
  get clientMode(): string;
30
28
  constructor(cmv: number, op?: ClientOption, _l?: Loggable);
31
- get(url: string, op?: {
32
- headers?: OutgoingHttpHeaders;
33
- ignoreQuery?: boolean;
34
- downloadPath?: string;
35
- timeout?: number;
36
- } & {
29
+ get(url: string, op?: RequestOption & {
37
30
  outerRedirectCount?: number;
38
- }): Promise<{
39
- headers?: IncomingHttpHeaders;
40
- payload: string;
41
- }>;
42
- get(url: string, op?: {
43
- headers?: OutgoingHttpHeaders;
44
- ignoreQuery?: boolean;
45
- downloadPath?: string;
46
- timeout?: number;
47
31
  responseType: "string";
48
- } & {
32
+ }): Promise<HttpResponse<string>>;
33
+ get(url: string, op?: RequestOption & {
49
34
  outerRedirectCount?: number;
50
- }): Promise<{
51
- headers?: IncomingHttpHeaders;
52
- payload: string;
53
- }>;
54
- get(url: string, op?: {
55
- headers?: OutgoingHttpHeaders;
56
- ignoreQuery?: boolean;
57
- downloadPath?: string;
58
- timeout?: number;
59
35
  responseType: "buffer";
60
- } & {
36
+ }): Promise<HttpResponse<Buffer>>;
37
+ get(url: string, op?: RequestOption & {
61
38
  outerRedirectCount?: number;
62
- }): Promise<{
63
- headers?: IncomingHttpHeaders;
64
- payload: Buffer;
65
- }>;
66
- post(url: string, payload: any, op?: {
67
- headers?: OutgoingHttpHeaders;
68
- ignoreQuery?: boolean;
69
- downloadPath?: string;
70
- timeout?: number;
71
- }): Promise<{
72
- headers?: IncomingHttpHeaders;
73
- payload: string;
74
- }>;
75
- post(url: string, payload: any, op?: {
76
- headers?: OutgoingHttpHeaders;
77
- ignoreQuery?: boolean;
78
- downloadPath?: string;
79
- timeout?: number;
39
+ }): Promise<HttpResponse<string>>;
40
+ post(url: string, payload: any, op?: RequestOption & {
80
41
  responseType: "string";
81
- }): Promise<{
82
- headers?: IncomingHttpHeaders;
83
- payload: string;
84
- }>;
85
- post(url: string, payload: any, op?: {
86
- headers?: OutgoingHttpHeaders;
87
- ignoreQuery?: boolean;
88
- downloadPath?: string;
89
- timeout?: number;
42
+ }): Promise<HttpResponse<string>>;
43
+ post(url: string, payload: any, op?: RequestOption & {
90
44
  responseType: "buffer";
91
- }): Promise<{
92
- headers?: IncomingHttpHeaders;
93
- payload: Buffer;
94
- }>;
45
+ }): Promise<HttpResponse<Buffer>>;
46
+ post(url: string, payload: any, op?: RequestOption): Promise<HttpResponse<string>>;
95
47
  private createProxyAgent;
96
48
  private getIn;
97
49
  private postIn;
@@ -35,6 +35,7 @@ const async_hooks_1 = require("async_hooks");
35
35
  const u_file_1 = require("../../func/u-file");
36
36
  const u_1 = require("../../func/u");
37
37
  const xjs_common_1 = require("xjs-common");
38
+ const stream_1 = require("stream");
38
39
  exports.s_clientMode = {
39
40
  nodejs: { id: 0, cipherOrder: null },
40
41
  chrome: { id: 1, cipherOrder: [2, 0, 1] },
@@ -44,36 +45,36 @@ const s_errCode = 1200;
44
45
  const s_redirectLimit = 5;
45
46
  const s_mode2headers = new Map([
46
47
  [exports.s_clientMode.firefox, (cmv) => ({
47
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
48
- "Accept-Encoding": "gzip, deflate, br",
49
- "Accept-Language": "en-US,en;q=0.5",
50
- "Sec-Fetch-Dest": "document",
51
- "Sec-Fetch-Mode": "navigate",
52
- "Sec-Fetch-Site": "none",
53
- "Sec-Fetch-User": "?1",
54
- "Upgrade-Insecure-Requests": "1",
55
- "User-Agent": `Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:${cmv}.0) Gecko/20100101 Firefox/${cmv}.0`
48
+ "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
49
+ "accept-encoding": "gzip, deflate, br",
50
+ "accept-language": "en-US,en;q=0.5",
51
+ "sec-fetch-dest": "document",
52
+ "sec-fetch-mode": "navigate",
53
+ "sec-fetch-site": "none",
54
+ "sec-fetch-user": "?1",
55
+ "upgrade-insecure-requests": "1",
56
+ "user-agent": `Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:${cmv}.0) Gecko/20100101 Firefox/${cmv}.0`
56
57
  })],
57
58
  [exports.s_clientMode.chrome, (cmv) => {
58
59
  const uad = cmv < 130
59
60
  ? `"Not/A)Brand";v="8", "Chromium";v="${cmv}", "Google Chrome";v="${cmv}"`
60
61
  : `"Chromium";v="${cmv}", "Not:A-Brand";v="24", "Google Chrome";v="${cmv}"`;
61
62
  const ch = {
62
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
63
- "Accept-Encoding": "gzip, deflate, br, zstd",
64
- "Accept-Language": "en-US,en;q=0.9",
65
- "Sec-Ch-Ua": uad,
66
- "Sec-Ch-Ua-Mobile": "?0",
67
- "Sec-Ch-Ua-Platform": '"Windows"',
68
- "Sec-Fetch-Dest": "document",
69
- "Sec-Fetch-Mode": "navigate",
70
- "Sec-Fetch-Site": "none",
71
- "Sec-Fetch-User": "?1",
72
- "Upgrade-Insecure-Requests": "1",
73
- "User-Agent": `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${cmv}.0.0.0 Safari/537.36`
63
+ "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
64
+ "accept-encoding": "gzip, deflate, br, zstd",
65
+ "accept-language": "en-US,en;q=0.9",
66
+ "sec-ch-ua": uad,
67
+ "sec-ch-ua-mobile": "?0",
68
+ "sec-ch-ua-platform": '"Windows"',
69
+ "sec-fetch-dest": "document",
70
+ "sec-fetch-mode": "navigate",
71
+ "sec-fetch-site": "none",
72
+ "sec-fetch-user": "?1",
73
+ "upgrade-insecure-requests": "1",
74
+ "user-agent": `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${cmv}.0.0.0 Safari/537.36`
74
75
  };
75
76
  if (cmv >= 124)
76
- ch["Priority"] = "u=0, i";
77
+ ch["priority"] = "u=0, i";
77
78
  return ch;
78
79
  }]
79
80
  ]);
@@ -97,16 +98,6 @@ class HttpResolverContext {
97
98
  this._chHeaders = s_mode2headers.get(this._mode)(this.cmv);
98
99
  }
99
100
  }
100
- /**
101
- * request GET to the url.
102
- * @param url target url.
103
- * @param op.headers http headers.
104
- * @param op.ignoreQuery {@link RequestOption.ignoreQuery}
105
- * @param op.downloadPath {@link RequestOption.downloadPath}
106
- * @param op.timeout {@link RequestOption.timeout}
107
- * @param op.responseType {@link RequestOption.responseType}
108
- * @returns string encoded by utf-8 as response payload.
109
- */
110
101
  async get(url, op) {
111
102
  const u = new url_1.URL(url);
112
103
  const proxyAgent = this._proxyConfig && await this.createProxyAgent(u);
@@ -114,17 +105,6 @@ class HttpResolverContext {
114
105
  Object.assign(rc, op);
115
106
  return await this._als.run(rc, this.getIn, u).finally(() => proxyAgent?.destroy());
116
107
  }
117
- /**
118
- * request POST to the url.
119
- * @param url target url.
120
- * @param payload request payload. if this is an object, it is treated as json.
121
- * @param op.headers http headers.
122
- * @param op.ignoreQuery {@link RequestOption.ignoreQuery}
123
- * @param op.downloadPath {@link RequestOption.downloadPath}
124
- * @param op.timeout {@link RequestOption.timeout}
125
- * @param op.responseType {@link RequestOption.responseType}
126
- * @returns string encoded by utf-8 as response payload.
127
- */
128
108
  async post(url, payload, op) {
129
109
  const u = new url_1.URL(url);
130
110
  const proxyAgent = this._proxyConfig && await this.createProxyAgent(u);
@@ -137,7 +117,7 @@ class HttpResolverContext {
137
117
  return new Promise((resolve, reject) => {
138
118
  const headers = {};
139
119
  if (conf.auth)
140
- headers['Proxy-Authorization'] = `Basic ${Buffer.from(conf.auth.name + ':' + conf.auth.pass).toString('base64')}`;
120
+ headers['proxy-authorization'] = `Basic ${Buffer.from(conf.auth.name + ':' + conf.auth.pass).toString('base64')}`;
141
121
  const req = (0, http_1.request)({
142
122
  host: conf.server,
143
123
  port: conf.port,
@@ -162,19 +142,22 @@ class HttpResolverContext {
162
142
  const params = {};
163
143
  const rc = this._als.getStore();
164
144
  params.method = xjs_common_1.HttpMethod.Get;
165
- params.headers = rc.headers ?? {};
145
+ params.headers = xjs_common_1.UHttp.normalizeHeaders(rc.headers);
166
146
  return await this.reqHttps(u, params);
167
147
  };
168
148
  postIn = async (u, payload) => {
169
149
  const params = {};
170
150
  const rc = this._als.getStore();
171
151
  params.method = xjs_common_1.HttpMethod.Post;
172
- params.headers = rc.headers ?? {};
152
+ params.headers = xjs_common_1.UHttp.normalizeHeaders(rc.headers);
173
153
  let p = payload;
174
- if (xjs_common_1.UType.isObject(payload)) {
154
+ if (p instanceof stream_1.Stream) {
155
+ params.headers["content-type"] ??= "application/octet-stream";
156
+ }
157
+ else if (xjs_common_1.UType.isObject(payload)) {
175
158
  p = JSON.stringify(payload);
176
- params.headers["Content-Length"] = p.length;
177
- params.headers["Content-Type"] = "application/json";
159
+ params.headers["content-length"] = p.length;
160
+ params.headers["content-type"] = "application/json";
178
161
  }
179
162
  return await this.reqHttps(u, params, p);
180
163
  };
@@ -199,7 +182,10 @@ class HttpResolverContext {
199
182
  reject(new xjs_common_1.XjsErr(s_errCode, "The http request timeout, maybe server did not respond."));
200
183
  });
201
184
  if (payload)
202
- req.write(payload);
185
+ if (payload instanceof stream_1.Stream)
186
+ payload.pipe(req);
187
+ else
188
+ req.write(payload);
203
189
  req.end();
204
190
  });
205
191
  }
@@ -1,9 +1,7 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="node" />
3
2
  import { Loggable } from "xjs-common";
4
3
  import { HttpResolverContext } from "./http-resolver-context";
5
- import { ClientOption, IHttpClient } from "./i-http-client";
6
- import { IncomingHttpHeaders, OutgoingHttpHeaders } from "http";
4
+ import { ClientOption, HttpResponse, IHttpClient, RequestOption } from "./i-http-client";
7
5
  export interface ClientMode {
8
6
  id: number;
9
7
  cipherOrder: number[];
@@ -31,69 +29,23 @@ export declare class HttpResolver implements IHttpClient {
31
29
  * @returns a http client as new context.
32
30
  */
33
31
  newContext(op?: ClientOption): HttpResolverContext;
34
- get(url: string, op?: {
35
- headers?: OutgoingHttpHeaders;
36
- ignoreQuery?: boolean;
37
- downloadPath?: string;
38
- timeout?: number;
39
- } & ClientOption & {
32
+ get(url: string, op?: RequestOption & ClientOption & {
40
33
  redirectAsNewRequest?: boolean;
41
- }): Promise<{
42
- headers?: IncomingHttpHeaders;
43
- payload: string;
44
- }>;
45
- get(url: string, op?: {
46
- headers?: OutgoingHttpHeaders;
47
- ignoreQuery?: boolean;
48
- downloadPath?: string;
49
- timeout?: number;
50
34
  responseType: "string";
51
- } & ClientOption & {
35
+ }): Promise<HttpResponse<string>>;
36
+ get(url: string, op?: RequestOption & ClientOption & {
52
37
  redirectAsNewRequest?: boolean;
53
- }): Promise<{
54
- headers?: IncomingHttpHeaders;
55
- payload: string;
56
- }>;
57
- get(url: string, op?: {
58
- headers?: OutgoingHttpHeaders;
59
- ignoreQuery?: boolean;
60
- downloadPath?: string;
61
- timeout?: number;
62
38
  responseType: "buffer";
63
- } & ClientOption & {
39
+ }): Promise<HttpResponse<Buffer>>;
40
+ get(url: string, op?: RequestOption & ClientOption & {
64
41
  redirectAsNewRequest?: boolean;
65
- }): Promise<{
66
- headers?: IncomingHttpHeaders;
67
- payload: Buffer;
68
- }>;
69
- post(url: string, payload: any, op?: {
70
- headers?: OutgoingHttpHeaders;
71
- ignoreQuery?: boolean;
72
- downloadPath?: string;
73
- timeout?: number;
74
- } & ClientOption): Promise<{
75
- headers?: IncomingHttpHeaders;
76
- payload: string;
77
- }>;
78
- post(url: string, payload: any, op?: {
79
- headers?: OutgoingHttpHeaders;
80
- ignoreQuery?: boolean;
81
- downloadPath?: string;
82
- timeout?: number;
42
+ }): Promise<HttpResponse<string>>;
43
+ post(url: string, payload: any, op?: RequestOption & ClientOption & {
83
44
  responseType: "string";
84
- } & ClientOption): Promise<{
85
- headers?: IncomingHttpHeaders;
86
- payload: string;
87
- }>;
88
- post(url: string, payload: any, op?: {
89
- headers?: OutgoingHttpHeaders;
90
- ignoreQuery?: boolean;
91
- downloadPath?: string;
92
- timeout?: number;
45
+ }): Promise<HttpResponse<string>>;
46
+ post(url: string, payload: any, op?: RequestOption & ClientOption & {
93
47
  responseType: "buffer";
94
- } & ClientOption): Promise<{
95
- headers?: IncomingHttpHeaders;
96
- payload: Buffer;
97
- }>;
48
+ }): Promise<HttpResponse<Buffer>>;
49
+ post(url: string, payload: any, op?: RequestOption & ClientOption): Promise<HttpResponse<string>>;
98
50
  private fixCmv;
99
51
  }
@@ -3,7 +3,13 @@
3
3
  import { IncomingHttpHeaders, OutgoingHttpHeaders } from "http";
4
4
  import { ClientMode, ProxyConfig } from "./http-resolver";
5
5
  export interface ClientOption {
6
+ /**
7
+ * {@link s_clientMode} that is imitated. default is random between chrome or firefox.
8
+ */
6
9
  mode?: ClientMode;
10
+ /**
11
+ * proxy configuration.
12
+ */
7
13
  proxy?: ProxyConfig;
8
14
  }
9
15
  export interface RequestOption {
@@ -26,7 +32,7 @@ export interface RequestOption {
26
32
  */
27
33
  responseType?: "string" | "buffer";
28
34
  }
29
- export interface HttpResponse {
35
+ export interface HttpResponse<T = string | Buffer> {
30
36
  /**
31
37
  * http headers in the response.
32
38
  */
@@ -34,7 +40,7 @@ export interface HttpResponse {
34
40
  /**
35
41
  * response payload which has a type depends on {@link RequestOption.responseType}.
36
42
  */
37
- payload?: string | Buffer;
43
+ payload?: T;
38
44
  }
39
45
  export interface IHttpClient {
40
46
  /**
@@ -49,14 +55,22 @@ export interface IHttpClient {
49
55
  * @param op.responseType {@link RequestOption.responseType}
50
56
  * @param op.redirectAsNewRequest handle redirect as new request. this may be efficient when using proxy which is implemented reverse proxy.
51
57
  * @returns http response. {@link HttpResponse}
52
- */
58
+ */
59
+ get(url: string, op?: RequestOption & ClientOption & {
60
+ redirectAsNewRequest?: boolean;
61
+ responseType: "string";
62
+ }): Promise<HttpResponse<string>>;
63
+ get(url: string, op?: RequestOption & ClientOption & {
64
+ redirectAsNewRequest?: boolean;
65
+ responseType: "buffer";
66
+ }): Promise<HttpResponse<Buffer>>;
53
67
  get(url: string, op?: RequestOption & ClientOption & {
54
68
  redirectAsNewRequest?: boolean;
55
- }): Promise<HttpResponse>;
69
+ }): Promise<HttpResponse<string>>;
56
70
  /**
57
71
  * request POST to the url with new context.
58
72
  * @param url target url. (currently https only)
59
- * @param payload request payload. if this is an object, it is treated as json.
73
+ * @param payload request payload. if this is a Stream, pipe will be used, otherwise if an object, this is treated as json.
60
74
  * @param op.headers http headers.
61
75
  * @param op.mode {@link s_clientMode} that is imitated. default is random between chrome or firefox.
62
76
  * @param op.proxy proxy configuration.
@@ -66,5 +80,11 @@ export interface IHttpClient {
66
80
  * @param op.responseType {@link RequestOption.responseType}
67
81
  * @returns http response. {@link HttpResponse}
68
82
  */
69
- post(url: string, payload: any, op?: RequestOption & ClientOption): Promise<HttpResponse>;
83
+ post(url: string, payload: any, op?: RequestOption & ClientOption & {
84
+ responseType: "string";
85
+ }): Promise<HttpResponse<string>>;
86
+ post(url: string, payload: any, op?: RequestOption & ClientOption & {
87
+ responseType: "buffer";
88
+ }): Promise<HttpResponse<Buffer>>;
89
+ post(url: string, payload: any, op?: RequestOption & ClientOption): Promise<HttpResponse<string>>;
70
90
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xjs-node",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "library modules for nodejs + typescript that bundled general-purpose implementations.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,6 +29,6 @@
29
29
  "typescript": "^4.9.5"
30
30
  },
31
31
  "dependencies": {
32
- "xjs-common": "^10.1.0"
32
+ "xjs-common": "^10.1.3"
33
33
  }
34
34
  }