Skip to content

Commit 7dee6da

Browse files
authored
add the feature of proxy and reconstruct the file of config (Tencent#393)
feat: new plugin and add proxy
1 parent 4568a4e commit 7dee6da

File tree

10 files changed

+156
-36
lines changed

10 files changed

+156
-36
lines changed

examples/express/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ app.get('/', function (req, res) {
55
res.send('Hello World!');
66
});
77

8+
app.post('/', function (req, res) {
9+
res.send('Hello World in post');
10+
});
11+
812
app.listen(4443, function () {
913
console.log('Example app listening on port 4443!');
1014
});

examples/express/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"author": "",
1010
"license": "MIT",
1111
"dependencies": {
12-
"@tswjs/open-platform-plugin": "^0.0.2",
12+
"@tswjs/open-platform-plugin": "0.0.6",
1313
"@tswjs/tsw": "^2.0.0-alpha",
1414
"axios": "^0.19.0",
1515
"express": "^4.17.1"

examples/express/tswconfig.js

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
const OpenPlatformPlugin = require("@tswjs/open-platform-plugin");
2+
3+
module.exports = {
4+
plugins: [
5+
new OpenPlatformPlugin({
6+
appid: "xxx",
7+
appkey: "xxx",
8+
// getReportList: () => {
9+
// return true;
10+
// },
11+
getReportList: () => {
12+
return new Promise((resolve, reject) => {
13+
setTimeout(() => {
14+
resolve(["demoUser"]);
15+
}, 2000)
16+
})
17+
},
18+
// 只支持同步写法
19+
getUid: (request) => {
20+
const cookie = request.headers.cookie;
21+
const uid = cookie.split("quid=")[1].split(";")[0];
22+
return uid;
23+
},
24+
// getProxyInfo: () => {
25+
// return new Promise((resolve, reject) => {
26+
// setTimeout(() => {
27+
// resolve({
28+
// "127.0.0.1": {
29+
// "port": 80,
30+
// "name": "2.0demo",
31+
// "group": "TSW",
32+
// "groupName": "TSW团队",
33+
// "desc": "2.0demo测试环境",
34+
// "order": 30,
35+
// "owner": "demoUser",
36+
// "alphaList": ["demoUser"]
37+
// }
38+
// });
39+
// }, 2000)
40+
// })
41+
// },
42+
getProxyInfo: () => {
43+
return {
44+
"127.0.0.1": {
45+
"port": 80,
46+
"name": "2.0demo",
47+
"group": "TSW",
48+
"groupName": "TSW团队",
49+
"desc": "2.0demo测试环境",
50+
"order": 30,
51+
"owner": "demoUser",
52+
"alphaList": ["demoUser"]
53+
}
54+
};
55+
}
56+
})
57+
]
58+
};

examples/express/tswconfig.json

-7
This file was deleted.

lib/core/bus.ts

+23-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ interface ResponseEventPayload {
1717
context: Context;
1818
}
1919

20+
interface RequestEventPayload {
21+
req: http.IncomingMessage;
22+
context: Context;
23+
}
24+
2025
interface EventBus extends EventEmitter {
2126
emit(
2227
event: "DNS_LOOKUP_SUCCESS",
@@ -38,6 +43,10 @@ interface EventBus extends EventEmitter {
3843
event: "RESPONSE_CLOSE",
3944
payload: ResponseEventPayload
4045
): boolean;
46+
emit(
47+
event: "REQUEST_START",
48+
payload: RequestEventPayload
49+
): boolean;
4150

4251
on(
4352
event: "DNS_LOOKUP_SUCCESS",
@@ -59,6 +68,10 @@ interface EventBus extends EventEmitter {
5968
event: "RESPONSE_CLOSE",
6069
listener: (payload: ResponseEventPayload) => void
6170
): this;
71+
on(
72+
event: "REQUEST_START",
73+
listener: (payload: RequestEventPayload) => void
74+
): this;
6275

6376
once(
6477
event: "DNS_LOOKUP_SUCCESS",
@@ -80,6 +93,10 @@ interface EventBus extends EventEmitter {
8093
event: "RESPONSE_CLOSE",
8194
listener: (payload: ResponseEventPayload) => void
8295
): this;
96+
once(
97+
event: "REQUEST_START",
98+
listener: (payload: RequestEventPayload) => void
99+
): this;
83100
}
84101

85102
export enum EVENT_LIST {
@@ -105,7 +122,12 @@ export enum EVENT_LIST {
105122
*
106123
* Indicates that the underlying connection was terminated.
107124
*/
108-
RESPONSE_CLOSE = "RESPONSE_CLOSE"
125+
RESPONSE_CLOSE = "RESPONSE_CLOSE",
126+
127+
/**
128+
* Emitted when then http.Request coming
129+
*/
130+
REQUEST_START = "REQUEST_START",
109131
}
110132

111133
let bus: EventBus | undefined;

lib/core/context.ts

+15
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,18 @@ export class Context {
9696
* All ajax raw data.
9797
*/
9898
captureRequests: RequestLog[];
99+
/**
100+
* Proxy ip for certain request.
101+
*/
102+
proxyIp: string;
103+
/**
104+
* Proxy port for certain request.
105+
*/
106+
proxyPort: number;
107+
/**
108+
* Mark for user.
109+
*/
110+
uid: string;
99111

100112
constructor() {
101113
this.log = {
@@ -111,6 +123,9 @@ export class Context {
111123

112124
this.captureSN = 0;
113125
this.captureRequests = [];
126+
this.proxyIp = "";
127+
this.proxyPort = 80;
128+
this.uid = "";
114129
}
115130
}
116131

lib/core/runtime/create-server.hack.ts

+52
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,58 @@ export const httpCreateServerHack = (): void => {
146146
d.run(() => {
147147
// 初始化一下 Context
148148
currentContext();
149+
150+
const context = process.domain.currentContext;
151+
eventBus.emit(EVENT_LIST.REQUEST_START, {
152+
req, context
153+
});
154+
155+
// proxy req to proxy env when hitting uid
156+
if (context.proxyIp !== "" && !req.headers.proxiedByTSW) {
157+
console.debug("isProxyUser...");
158+
159+
const requestOptions = {
160+
hostname: context.proxyIp,
161+
port: context.proxyPort,
162+
path: req.url,
163+
method: req.method,
164+
headers: { proxiedByTSW: true, ...req.headers }
165+
};
166+
console.debug("start proxy");
167+
const proxyReq = http.request(requestOptions, (proxyRes) => {
168+
proxyRes.pipe(res);
169+
Object.keys(proxyRes.headers).forEach((headerType) => {
170+
res.setHeader(headerType, proxyRes.headers[headerType]);
171+
});
172+
173+
res.writeHead(proxyRes.statusCode);
174+
proxyRes.on("end", () => {
175+
console.debug("end proxy");
176+
});
177+
});
178+
179+
if (/POST|PUT/i.test(req.method)) {
180+
req.pipe(proxyReq);
181+
} else {
182+
proxyReq.end();
183+
}
184+
185+
proxyReq.on("error", (err) => {
186+
console.error("proxy fail...");
187+
console.error(JSON.stringify(err));
188+
if (res.headersSent) {
189+
res.end();
190+
return;
191+
}
192+
193+
res.setHeader("Content-Type", "text/html; charset=UTF-8");
194+
res.writeHead(500);
195+
res.end();
196+
});
197+
198+
return;
199+
}
200+
149201
requestListener(req, res);
150202
});
151203
};

lib/index.ts

+1-26
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,19 @@ import { dnsHack } from "./core/runtime/dns.hack";
55
import { requestHack } from "./core/runtime/capture/index";
66
import { eventBus } from "./core/bus";
77

8-
const loadPlugins = async (
9-
basePath: string,
10-
config: typeof global.tswConfig
11-
): Promise<void> => {
12-
// eslint-disable-next-line no-restricted-syntax
13-
for (const pluginPath of config.plugins) {
14-
if (!pluginPath.trim()) {
15-
return;
16-
}
17-
18-
let absolutePath = "";
19-
if (path.isAbsolute(pluginPath)) {
20-
absolutePath = pluginPath;
21-
} else if (pluginPath.startsWith(".")) {
22-
absolutePath = path.resolve(basePath, pluginPath);
23-
} else {
24-
absolutePath = path.resolve(basePath, "node_modules", pluginPath);
25-
}
26-
27-
// eslint-disable-next-line no-await-in-loop
28-
(await import(absolutePath))(eventBus, config);
29-
}
30-
};
31-
328
export default async (
339
basePath: string,
3410
mainPath: string,
3511
configPath: string
3612
): Promise<void> => {
3713
const configAbsolutePath = path.resolve(basePath, configPath);
14+
global.eventBus = eventBus;
3815
global.tswConfig = await import(configAbsolutePath);
3916

4017
httpCreateServerHack();
4118
dnsHack();
4219
consoleHack();
4320
requestHack();
4421

45-
await loadPlugins(path.dirname(configAbsolutePath), global.tswConfig);
46-
4722
await import(path.resolve(basePath, mainPath));
4823
};

tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
],
1111
"resolveJsonModule": true,
1212
// "noImplicitAny": true
13-
// "sourceMap": true, // for debug
13+
"sourceMap": true, // for debug
1414
}
1515
}

typings/type.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@ declare namespace NodeJS {
3030
appkey: string;
3131
plugins: string[];
3232
};
33+
eventBus: EventEmitter;
3334
}
3435
}

0 commit comments

Comments
 (0)