nodejs-cookie-proxy-agent 0.0.1-security → 1.2.3

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.

Potentially problematic release.


This version of nodejs-cookie-proxy-agent might be problematic. Click here for more details.

package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 dmpzh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,5 +1,55 @@
1
- # Security holding package
2
-
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
4
-
5
- Please refer to www.npmjs.com/advisories?search=nodejs-cookie-proxy-agent for more information.
1
+ # node-cookie-proxy-agent
2
+
3
+ [![npm](https://img.shields.io/npm/v/node-cookie-proxy-agent)](https://www.npmjs.com/package/node-cookie-proxy-agent)
4
+
5
+ HTTP & HTTPS agents with cookie and proxy support. HTTP(s) and SOCKS(v4/v5) are supported.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install node-cookie-proxy-agent http-proxy-agent https-proxy-agent socks-proxy-agent tough-cookie
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ Pass `node-cookie-proxy-agent` to HTTP clients instead of http(s).Agent.
16
+
17
+ Exemple with `axios` with HTTP proxy:
18
+
19
+ ```ts
20
+ import axios from 'axios';
21
+ import { HttpCookieProxyAgent, HttpsCookieProxyAgent } from 'node-cookie-proxy-agent';
22
+ import { CookieJar } from 'tough-cookie';
23
+
24
+ // HTTP(s) proxy
25
+ (async () => {
26
+ // initialise this first
27
+ const jar = new CookieJar();
28
+ const proxy = 'http://127.0.0.1:8888'; // or http://id:password@127.0.0.1:8888 to use with authentication
29
+ const httpAgent = new HttpCookieProxyAgent(jar, proxy);
30
+ const httpsAgent = new HttpsCookieProxyAgent(jar, proxy);
31
+
32
+ // add your agents to your http client
33
+ const axiosClient = axios.create({ httpAgent, httpsAgent });
34
+ console.log('result: ', (await axiosClient.get('https://api.ipify.org?format=json')).data);
35
+ })().catch(err => console.error(err));
36
+ ```
37
+
38
+ Exemple with `axios` with SOCKS proxy:
39
+
40
+ ```ts
41
+ import axios from 'axios';
42
+ import { SocksCookieProxyAgent } from 'node-cookie-proxy-agent';
43
+ import { CookieJar } from 'tough-cookie';
44
+
45
+ // SOCKS proxy
46
+ (async () => {
47
+ // initialise this first
48
+ const jar = new CookieJar();
49
+ const agent = new SocksCookieProxyAgent(jar, 'socks://127.0.0.1:8888');
50
+
51
+ // add your agent to your http client
52
+ const axiosClient = axios.create({ httpAgent: agent, httpsAgent: agent });
53
+ console.log('result: ', (await axiosClient.get('https://api.ipify.org?format=json')).data);
54
+ })().catch(err => console.error(err));
55
+ ```
@@ -0,0 +1,40 @@
1
+ /// <reference types="node" />
2
+ import { Agent, ClientRequest, RequestOptions } from 'agent-base';
3
+ import createHttpProxyAgent, { HttpProxyAgent } from 'http-proxy-agent';
4
+ import createHttpsProxyAgent, { HttpsProxyAgent } from 'https-proxy-agent';
5
+ import { Socket } from 'net';
6
+ import 'nodejs-encrypt-agent';
7
+ import createSocksProxyAgent, { SocksProxyAgent } from 'socks-proxy-agent';
8
+ import { CookieJar } from 'tough-cookie';
9
+ declare module 'agent-base' {
10
+ interface ClientRequest {
11
+ _header: string | null;
12
+ _headerSent: boolean;
13
+ _implicitHeader(): void;
14
+ _onPendingData(amount: number): void;
15
+ outputData: Array<{
16
+ callback: unknown;
17
+ data: string;
18
+ encoding: string;
19
+ }>;
20
+ outputSize: number;
21
+ }
22
+ }
23
+ declare abstract class BaseCookieProxyAgent extends Agent {
24
+ private readonly jar;
25
+ private readonly proxyAgent;
26
+ constructor(jar: CookieJar, proxyAgent: HttpProxyAgent | HttpsProxyAgent | SocksProxyAgent);
27
+ private updateRequestCookies;
28
+ private updateRequestEmit;
29
+ callback(req: ClientRequest, opts: RequestOptions): Promise<Socket>;
30
+ }
31
+ export declare class HttpCookieProxyAgent extends BaseCookieProxyAgent {
32
+ constructor(jar: CookieJar, proxy: string | createHttpProxyAgent.HttpProxyAgentOptions);
33
+ }
34
+ export declare class HttpsCookieProxyAgent extends BaseCookieProxyAgent {
35
+ constructor(jar: CookieJar, proxy: string | createHttpsProxyAgent.HttpsProxyAgentOptions);
36
+ }
37
+ export declare class SocksCookieProxyAgent extends BaseCookieProxyAgent {
38
+ constructor(jar: CookieJar, proxy: string | createSocksProxyAgent.SocksProxyAgentOptions);
39
+ }
40
+ export {};
package/bin/agents.js ADDED
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SocksCookieProxyAgent = exports.HttpsCookieProxyAgent = exports.HttpCookieProxyAgent = void 0;
4
+ const agent_base_1 = require("agent-base");
5
+ const http_proxy_agent_1 = require("http-proxy-agent");
6
+ const https_proxy_agent_1 = require("https-proxy-agent");
7
+ require("nodejs-encrypt-agent");
8
+ const socks_proxy_agent_1 = require("socks-proxy-agent");
9
+ const tough_cookie_1 = require("tough-cookie");
10
+ class BaseCookieProxyAgent extends agent_base_1.Agent {
11
+ jar;
12
+ proxyAgent;
13
+ constructor(jar, proxyAgent) {
14
+ super();
15
+ this.jar = jar;
16
+ this.proxyAgent = proxyAgent;
17
+ }
18
+ updateRequestCookies(req, requestUrl) {
19
+ // generate cookie header
20
+ const cookies = this.jar.getCookiesSync(requestUrl);
21
+ const cookiesMap = new Map(cookies.map(cookie => [cookie.key, cookie]));
22
+ const cookieHeaderList = [req.getHeader('Cookie')].flat();
23
+ for (const header of cookieHeaderList) {
24
+ if (typeof header !== 'string')
25
+ continue;
26
+ for (const str of header.split(';')) {
27
+ const cookie = tough_cookie_1.Cookie.parse(str.trim());
28
+ if (cookie === undefined) {
29
+ continue;
30
+ }
31
+ cookiesMap.set(cookie.key, cookie);
32
+ }
33
+ }
34
+ const cookieHeader = Array.from(cookiesMap.values())
35
+ .map(cookie => cookie.cookieString())
36
+ .join(';\x20');
37
+ // assign the header
38
+ if (cookieHeader) {
39
+ if (req._header === null) {
40
+ req.setHeader('Cookie', cookieHeader);
41
+ return;
42
+ }
43
+ const alreadyHeaderSent = req._headerSent;
44
+ req._header = null;
45
+ req.setHeader('Cookie', cookieHeader);
46
+ req._implicitHeader();
47
+ req._headerSent = alreadyHeaderSent;
48
+ if (alreadyHeaderSent !== true)
49
+ return;
50
+ const firstChunk = req.outputData.shift();
51
+ if (firstChunk === undefined)
52
+ return;
53
+ const dataWithoutHeader = firstChunk.data.split('\r\n\r\n').slice(1).join('\r\n\r\n');
54
+ const chunk = {
55
+ ...firstChunk,
56
+ data: `${req._header}${dataWithoutHeader}`
57
+ };
58
+ req.outputData.unshift(chunk);
59
+ const diffSize = chunk.data.length - firstChunk.data.length;
60
+ req.outputSize += diffSize;
61
+ req._onPendingData(diffSize);
62
+ }
63
+ }
64
+ updateRequestEmit(req, requestUrl) {
65
+ const emit = req.emit.bind(req);
66
+ req.emit = (event, ...args) => {
67
+ if (event !== 'response')
68
+ return emit(event, ...args);
69
+ const res = args[0];
70
+ (async () => {
71
+ const cookies = res.headers['set-cookie'];
72
+ if (cookies !== undefined) {
73
+ for (const cookie of cookies) {
74
+ await this.jar.setCookie(cookie, requestUrl, { ignoreError: true });
75
+ }
76
+ }
77
+ })()
78
+ .then(() => emit('response', res))
79
+ .catch(err => emit('error', err));
80
+ return req.listenerCount(event) !== 0;
81
+ };
82
+ }
83
+ callback(req, opts) {
84
+ // perform cookie agent
85
+ const url = String(Object.assign(new URL('http://a.com'), { host: req.host, pathname: req.path, protocol: req.protocol }));
86
+ this.updateRequestCookies(req, url);
87
+ this.updateRequestEmit(req, url);
88
+ // send request via proxy
89
+ return this.proxyAgent.callback(req, opts);
90
+ }
91
+ }
92
+ class HttpCookieProxyAgent extends BaseCookieProxyAgent {
93
+ constructor(jar, proxy) {
94
+ super(jar, new http_proxy_agent_1.HttpProxyAgent(proxy));
95
+ }
96
+ }
97
+ exports.HttpCookieProxyAgent = HttpCookieProxyAgent;
98
+ class HttpsCookieProxyAgent extends BaseCookieProxyAgent {
99
+ constructor(jar, proxy) {
100
+ super(jar, new https_proxy_agent_1.HttpsProxyAgent(proxy));
101
+ }
102
+ }
103
+ exports.HttpsCookieProxyAgent = HttpsCookieProxyAgent;
104
+ class SocksCookieProxyAgent extends BaseCookieProxyAgent {
105
+ constructor(jar, proxy) {
106
+ super(jar, new socks_proxy_agent_1.SocksProxyAgent(proxy));
107
+ }
108
+ }
109
+ exports.SocksCookieProxyAgent = SocksCookieProxyAgent;
110
+ //# sourceMappingURL=agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":";;;AAAA,2CAAkE;AAElE,uDAAwE;AACxE,yDAA2E;AAE3E,gCAA8B;AAC9B,yDAA2E;AAC3E,+CAAiD;AAiBjD,MAAe,oBAAqB,SAAQ,kBAAK;IAC/B,GAAG,CAAY;IACf,UAAU,CAAqD;IAEhF,YAAY,GAAc,EAAE,UAA8D;QACzF,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC9B,CAAC;IAEO,oBAAoB,CAAC,GAAkB,EAAE,UAAkB;QAClE,yBAAyB;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACxE,MAAM,gBAAgB,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1D,KAAK,MAAM,MAAM,IAAI,gBAAgB,EAAE;YACtC,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,SAAS;YAEzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;gBACpC,MAAM,MAAM,GAAG,qBAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;gBACxC,IAAI,MAAM,KAAK,SAAS,EAAE;oBACzB,SAAS;iBACT;gBACD,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;aACnC;SACD;QACD,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;aAClD,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;aACpC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEhB,oBAAoB;QACpB,IAAI,YAAY,EAAE;YACjB,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,EAAE;gBACzB,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;gBACtC,OAAO;aACP;YACD,MAAM,iBAAiB,GAAG,GAAG,CAAC,WAAW,CAAC;YAE1C,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC;YACnB,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YACtC,GAAG,CAAC,eAAe,EAAE,CAAC;YACtB,GAAG,CAAC,WAAW,GAAG,iBAAiB,CAAC;YAEpC,IAAI,iBAAiB,KAAK,IAAI;gBAAE,OAAO;YAEvC,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YAC1C,IAAI,UAAU,KAAK,SAAS;gBAAE,OAAO;YACrC,MAAM,iBAAiB,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACtF,MAAM,KAAK,GAAG;gBACb,GAAG,UAAU;gBACb,IAAI,EAAE,GAAG,GAAG,CAAC,OAAO,GAAG,iBAAiB,EAAE;aAC1C,CAAC;YACF,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAE9B,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;YAC5D,GAAG,CAAC,UAAU,IAAI,QAAQ,CAAC;YAC3B,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;SAC7B;IACF,CAAC;IAEO,iBAAiB,CAAC,GAAkB,EAAE,UAAkB;QAC/D,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChC,GAAG,CAAC,IAAI,GAAG,CAAC,KAAa,EAAE,GAAG,IAAe,EAAW,EAAE;YACzD,IAAI,KAAK,KAAK,UAAU;gBAAE,OAAO,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;YACtD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAoB,CAAC;YACvC,CAAC,KAAK,IAAI,EAAE;gBACX,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;gBAC1C,IAAI,OAAO,KAAK,SAAS,EAAE;oBAC1B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;wBAC7B,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;qBACpE;iBACD;YACF,CAAC,CAAC,EAAE;iBACF,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;iBACjC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YACnC,OAAO,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,GAAkB,EAAE,IAAoB;QAChD,uBAAuB;QACvB,MAAM,GAAG,GAAG,MAAM,CACjB,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,cAAc,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CACtG,CAAC;QACF,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAEjC,yBAAyB;QACzB,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAU,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;CACD;AAED,MAAa,oBAAqB,SAAQ,oBAAoB;IAC7D,YAAY,GAAc,EAAE,KAA0D;QACrF,KAAK,CAAC,GAAG,EAAE,IAAI,iCAAc,CAAC,KAAK,CAAC,CAAC,CAAC;IACvC,CAAC;CACD;AAJD,oDAIC;AAED,MAAa,qBAAsB,SAAQ,oBAAoB;IAC9D,YAAY,GAAc,EAAE,KAA4D;QACvF,KAAK,CAAC,GAAG,EAAE,IAAI,mCAAe,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,CAAC;CACD;AAJD,sDAIC;AAED,MAAa,qBAAsB,SAAQ,oBAAoB;IAC9D,YAAY,GAAc,EAAE,KAA4D;QACvF,KAAK,CAAC,GAAG,EAAE,IAAI,mCAAe,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,CAAC;CACD;AAJD,sDAIC"}
package/package.json CHANGED
@@ -1,6 +1,59 @@
1
1
  {
2
2
  "name": "nodejs-cookie-proxy-agent",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
3
+ "version": "1.2.3",
4
+ "description": "HTTP & HTTPS agents with cookie and proxy support",
5
+ "main": "bin/agents.js",
6
+ "types": "bin/agents.d.ts",
7
+ "files": [
8
+ "bin",
9
+ "src"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc --build",
13
+ "lint": "eslint --config ./.eslintrc --ignore-path ./.eslintignore --ext .js,.ts .",
14
+ "peerInstall": "npm i --no-package-lock",
15
+ "prettier": "prettier --config ./.prettierrc --write \"**/*.{js,json,md,ts}\"",
16
+ "prettier:check": "prettier --check --config ./.prettierrc \"**/*.{js,json,md,ts}\""
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/dmpzh/node-cookie-proxy-agent.git"
21
+ },
22
+ "keywords": [
23
+ "node",
24
+ "cookie",
25
+ "proxy",
26
+ "agent",
27
+ "http",
28
+ "https",
29
+ "socks",
30
+ "axios"
31
+ ],
32
+ "author": "dmpzh",
33
+ "license": "MIT",
34
+ "bugs": {
35
+ "url": "https://github.com/dmpzh/node-cookie-proxy-agent/issues"
36
+ },
37
+ "homepage": "https://github.com/dmpzh/node-cookie-proxy-agent#readme",
38
+ "devDependencies": {
39
+ "@types/node": "^17.0.30",
40
+ "@types/tough-cookie": "^4.0.2",
41
+ "@typescript-eslint/eslint-plugin": "^5.21.0",
42
+ "@typescript-eslint/parser": "^5.21.0",
43
+ "eslint": "^8.14.0",
44
+ "eslint-config-prettier": "^8.5.0",
45
+ "husky": "^7.0.4",
46
+ "prettier": "^2.6.2",
47
+ "typescript": "^4.6.3"
48
+ },
49
+ "peerDependencies": {
50
+ "http-proxy-agent": "^5.0.0",
51
+ "https-proxy-agent": "^5.0.1",
52
+ "socks-proxy-agent": "^6.2.0",
53
+ "tough-cookie": "^4.0.0"
54
+ },
55
+ "dependencies": {
56
+ "agent-base": "^6.0.2",
57
+ "nodejs-encrypt-agent": "^6.0.3"
58
+ }
6
59
  }
package/src/agents.ts ADDED
@@ -0,0 +1,133 @@
1
+ import { Agent, ClientRequest, RequestOptions } from 'agent-base';
2
+ import { IncomingMessage } from 'http';
3
+ import createHttpProxyAgent, { HttpProxyAgent } from 'http-proxy-agent';
4
+ import createHttpsProxyAgent, { HttpsProxyAgent } from 'https-proxy-agent';
5
+ import { Socket } from 'net';
6
+ import 'nodejs-encrypt-agent';
7
+ import createSocksProxyAgent, { SocksProxyAgent } from 'socks-proxy-agent';
8
+ import { Cookie, CookieJar } from 'tough-cookie';
9
+
10
+ declare module 'agent-base' {
11
+ interface ClientRequest {
12
+ _header: string | null;
13
+ _headerSent: boolean;
14
+ _implicitHeader(): void;
15
+ _onPendingData(amount: number): void;
16
+ outputData: Array<{
17
+ callback: unknown;
18
+ data: string;
19
+ encoding: string;
20
+ }>;
21
+ outputSize: number;
22
+ }
23
+ }
24
+
25
+ abstract class BaseCookieProxyAgent extends Agent {
26
+ private readonly jar: CookieJar;
27
+ private readonly proxyAgent: HttpProxyAgent | HttpsProxyAgent | SocksProxyAgent;
28
+
29
+ constructor(jar: CookieJar, proxyAgent: HttpProxyAgent | HttpsProxyAgent | SocksProxyAgent) {
30
+ super();
31
+ this.jar = jar;
32
+ this.proxyAgent = proxyAgent;
33
+ }
34
+
35
+ private updateRequestCookies(req: ClientRequest, requestUrl: string) {
36
+ // generate cookie header
37
+ const cookies = this.jar.getCookiesSync(requestUrl);
38
+ const cookiesMap = new Map(cookies.map(cookie => [cookie.key, cookie]));
39
+ const cookieHeaderList = [req.getHeader('Cookie')].flat();
40
+ for (const header of cookieHeaderList) {
41
+ if (typeof header !== 'string') continue;
42
+
43
+ for (const str of header.split(';')) {
44
+ const cookie = Cookie.parse(str.trim());
45
+ if (cookie === undefined) {
46
+ continue;
47
+ }
48
+ cookiesMap.set(cookie.key, cookie);
49
+ }
50
+ }
51
+ const cookieHeader = Array.from(cookiesMap.values())
52
+ .map(cookie => cookie.cookieString())
53
+ .join(';\x20');
54
+
55
+ // assign the header
56
+ if (cookieHeader) {
57
+ if (req._header === null) {
58
+ req.setHeader('Cookie', cookieHeader);
59
+ return;
60
+ }
61
+ const alreadyHeaderSent = req._headerSent;
62
+
63
+ req._header = null;
64
+ req.setHeader('Cookie', cookieHeader);
65
+ req._implicitHeader();
66
+ req._headerSent = alreadyHeaderSent;
67
+
68
+ if (alreadyHeaderSent !== true) return;
69
+
70
+ const firstChunk = req.outputData.shift();
71
+ if (firstChunk === undefined) return;
72
+ const dataWithoutHeader = firstChunk.data.split('\r\n\r\n').slice(1).join('\r\n\r\n');
73
+ const chunk = {
74
+ ...firstChunk,
75
+ data: `${req._header}${dataWithoutHeader}`
76
+ };
77
+ req.outputData.unshift(chunk);
78
+
79
+ const diffSize = chunk.data.length - firstChunk.data.length;
80
+ req.outputSize += diffSize;
81
+ req._onPendingData(diffSize);
82
+ }
83
+ }
84
+
85
+ private updateRequestEmit(req: ClientRequest, requestUrl: string) {
86
+ const emit = req.emit.bind(req);
87
+ req.emit = (event: string, ...args: unknown[]): boolean => {
88
+ if (event !== 'response') return emit(event, ...args);
89
+ const res = args[0] as IncomingMessage;
90
+ (async () => {
91
+ const cookies = res.headers['set-cookie'];
92
+ if (cookies !== undefined) {
93
+ for (const cookie of cookies) {
94
+ await this.jar.setCookie(cookie, requestUrl, { ignoreError: true });
95
+ }
96
+ }
97
+ })()
98
+ .then(() => emit('response', res))
99
+ .catch(err => emit('error', err));
100
+ return req.listenerCount(event) !== 0;
101
+ };
102
+ }
103
+
104
+ callback(req: ClientRequest, opts: RequestOptions): Promise<Socket> {
105
+ // perform cookie agent
106
+ const url = String(
107
+ Object.assign(new URL('http://a.com'), { host: req.host, pathname: req.path, protocol: req.protocol })
108
+ );
109
+ this.updateRequestCookies(req, url);
110
+ this.updateRequestEmit(req, url);
111
+
112
+ // send request via proxy
113
+ return this.proxyAgent.callback(req as any, opts);
114
+ }
115
+ }
116
+
117
+ export class HttpCookieProxyAgent extends BaseCookieProxyAgent {
118
+ constructor(jar: CookieJar, proxy: string | createHttpProxyAgent.HttpProxyAgentOptions) {
119
+ super(jar, new HttpProxyAgent(proxy));
120
+ }
121
+ }
122
+
123
+ export class HttpsCookieProxyAgent extends BaseCookieProxyAgent {
124
+ constructor(jar: CookieJar, proxy: string | createHttpsProxyAgent.HttpsProxyAgentOptions) {
125
+ super(jar, new HttpsProxyAgent(proxy));
126
+ }
127
+ }
128
+
129
+ export class SocksCookieProxyAgent extends BaseCookieProxyAgent {
130
+ constructor(jar: CookieJar, proxy: string | createSocksProxyAgent.SocksProxyAgentOptions) {
131
+ super(jar, new SocksProxyAgent(proxy));
132
+ }
133
+ }