Skip to content

Commit 6382f3d

Browse files
authored
Merge pull request #3 from alinGmail/proxyheader
Proxyheader
2 parents 2119926 + b208688 commit 6382f3d

File tree

13 files changed

+231
-35
lines changed

13 files changed

+231
-35
lines changed

backEnd/src/action/ProxyAction.ts

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,26 @@ let proxy = httpProxy.createProxyServer({});
1616

1717
proxy.on("proxyReq", function (proxyReq, req, res, options) {
1818
fixRequestBody(proxyReq, req as express.Request);
19-
const proxyAction = (options as any).proxyAction as ProxyActionM;
20-
//
21-
if (proxyAction.handleCross) {
22-
// handle cross
23-
handleOptionsCross(
24-
req as express.Request,
25-
res as express.Response,
26-
proxyAction.crossAllowCredentials
27-
);
28-
}
19+
20+
2921
});
3022
proxy.on("proxyRes", function (proxyRes: http.IncomingMessage, req, res) {
3123
let body: Array<any> = [];
3224
const recordBody = isRecordBody(req, proxyRes);
25+
const proxyAction = (req as any).proxyAction as ProxyActionM;
26+
// handle cross`
27+
if (proxyAction.handleCross) {
28+
// handle cross
29+
handleRequestCross(
30+
req as express.Request,
31+
proxyRes,
32+
proxyAction.crossAllowCredentials
33+
);
34+
}
35+
// handle the external headers
36+
if (proxyAction.headers && proxyAction.headers.length > 0){
37+
handleExternalHeaders(req as express.Request,proxyRes,proxyAction.headers);
38+
}
3339
proxyRes.on("data", function (chunk) {
3440
if (recordBody) {
3541
body.push(chunk);
@@ -87,6 +93,20 @@ function handleOptionsCross(
8793
res.end();
8894
}
8995

96+
/**
97+
*
98+
* @param req
99+
* @param res
100+
* @param headers
101+
*/
102+
function handleExternalHeaders(req: express.Request,
103+
res: http.IncomingMessage,
104+
headers:Array<[string,string]>){
105+
headers.forEach(item=>{
106+
res.headers[item[0].toLowerCase()] = item[1];
107+
});
108+
}
109+
90110
/**
91111
*
92112
* @param req
@@ -96,10 +116,10 @@ function handleOptionsCross(
96116
*/
97117
function handleRequestCross(
98118
req: express.Request,
99-
res: express.Response,
119+
res: http.IncomingMessage,
100120
crossAllowCredentials: boolean
101121
) {
102-
res.header("Access-Control-Allow-Origin", req.get("Origin"));
122+
res.headers['Access-Control-Allow-Origin'.toLowerCase()] = req.get("Origin");
103123
const headerKeySet = new Set<string>();
104124
req.rawHeaders.forEach((item, index) => {
105125
if (index % 2 === 0) {
@@ -111,10 +131,10 @@ function handleRequestCross(
111131
headerArray.push(item);
112132
});
113133
const headerStr = headerArray.join(",");
114-
res.header("Access-Control-Allow-Headers", headerStr);
115-
res.header("Access-Control-Allow-Methods", req.method.toUpperCase());
134+
res.headers['Access-Control-Allow-Headers'] = headerStr;
135+
res.headers["Access-Control-Allow-Methods"] = req.method.toUpperCase();
116136
if (crossAllowCredentials) {
117-
res.header("Access-Control-Allow-Credentials", "true");
137+
res.headers["Access-Control-Allow-Credentials"] = "true";
118138
}
119139
}
120140

@@ -145,6 +165,7 @@ export default class ProxyActionImpl implements IAction {
145165
},
146166
proxyAction: this.action,
147167
};
168+
(req as any).proxyAction = this.action;
148169
res.on("end", () => {
149170
resolve();
150171
});

backEnd/src/db/dbManager.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ExpectationM } from "core/struct/expectation";
55
import { LogViewM } from "core/struct/logView";
66
import { LogM } from "core/struct/log";
77
import e from "express";
8+
import {SystemConfigM} from "core/struct/systemConfig";
89

910
const projectDbPromiseMap = new Map<string, Promise<Loki>>();
1011

@@ -92,3 +93,12 @@ export function setNewestLogNumber(
9293
) {
9394
logIndexMap.set(`${path}/${projectId}`, newestLogIndex);
9495
}
96+
export async function getSystemCollection(path:string){
97+
const projectDb = await getProjectDb(path);
98+
let entries = projectDb.getCollection<SystemConfigM>("system");
99+
if (entries === null) {
100+
entries = projectDb.addCollection<SystemConfigM>("system");
101+
}
102+
return entries;
103+
}
104+

backEnd/src/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { getActionRouter } from "./controller/actionController";
77
import {addLogListener, getLogRouter} from "./controller/logController";
88
import {getLogFilterRouter} from "./controller/logFilterController";
99
import {getLocal} from "mockttp";
10+
import {getSystemCollection} from "./db/dbManager";
1011
const { Server } = require("socket.io");
1112

1213
const server = express();
@@ -16,9 +17,19 @@ const io = new Server(http,{
1617
origin: "http://localhost:5173"
1718
}
1819
});
20+
export const systemVersion = 801;
1921
// io.fetchSockets()
22+
async function projectInit() {
23+
const systemCollection = await getSystemCollection("userData");
24+
const systemConfig = systemCollection.findOne({});
25+
if(systemConfig){
2026

27+
}else{
28+
systemCollection.insertOne({version:systemVersion});
29+
}
30+
}
2131
(async function () {
32+
await projectInit();
2233
server.use("/project", await getProjectRouter("db"));
2334
server.use("/expectation", getExpectationRouter("db"));
2435
server.use("/matcher", getMatcherRouter("db"));

backEnd/test/action/ProxyAction.test.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,28 @@ describe("test proxy action",()=>{
3939
pathMatcherM.value = "";
4040
expectationM.matchers = [pathMatcherM];
4141
expectationM.activate = true;
42+
expectationM.priority = 1;
4243
const proxyActionM = createProxyAction();
4344
proxyActionM.host = "localhost:8085";
4445
expectationM.actions.push(proxyActionM);
4546

47+
const expectationCrossM = createExpectation();
48+
const pathMatcherCrossM = createPathMatcher();
49+
pathMatcherCrossM.conditions = MatcherCondition.START_WITH;
50+
pathMatcherCrossM.value = "/testCross";
51+
expectationCrossM.matchers = [pathMatcherCrossM];
52+
expectationCrossM.activate = true;
53+
expectationCrossM.priority = 2;
54+
const proxyCrossActionM = createProxyAction();
55+
proxyCrossActionM.host = "localhost:8085";
56+
proxyCrossActionM.handleCross = true;
57+
proxyCrossActionM.crossAllowCredentials = true;
58+
proxyCrossActionM.headers?.push(["myToken","myTokenValue"])
59+
expectationCrossM.actions.push(proxyCrossActionM);
60+
4661

4762
await expectationCreation(server, projectM, expectationM);
48-
const expectationMCollection = await getExpectationCollection(projectM.id, 'test_db');
63+
await expectationCreation(server, projectM, expectationCrossM);
4964

5065
// set up the server
5166
await mockServer.start(8085);
@@ -71,6 +86,14 @@ describe("test proxy action",()=>{
7186
'token':"json header",
7287
"Content-Type":"application/json"
7388
});
89+
// response json
90+
await mockServer.forGet("/testCross").thenReply(200,JSON.stringify({
91+
name:"john",age:20
92+
}),{
93+
'token':"json header",
94+
"myToken":"origin value",
95+
"Content-Type":"application/json"
96+
});
7497
await mockServer.forGet("/testJsonNoContentType").thenReply(200,JSON.stringify({
7598
name:"john",age:20
7699
}),{
@@ -134,6 +157,30 @@ describe("test proxy action",()=>{
134157
const response = await request(proxyServer).get("/testJsonNoContentType").set({Accept:"application/json"});
135158
await testJsonResponse(response, projectM);
136159
});
160+
161+
test(`test handle cross`,async ()=>{
162+
const response = await request(proxyServer).get("/testCross")
163+
.set("Origin","www.google.com")
164+
.set("AccessToken","aaa").set("SecretName","bbb");
165+
await testJsonResponse(response, projectM);
166+
expect(response.get("Access-Control-Allow-Origin")).toEqual("www.google.com");
167+
expect(response.get("Access-Control-Allow-Headers")).toContain("accesstoken");
168+
expect(response.get("Access-Control-Allow-Headers")).toContain("secretname");
169+
expect(response.get("Access-Control-Allow-Credentials")).toContain("true");
170+
expect(response.get("myToken")).toEqual("myTokenValue");
171+
172+
const optionResponse = await request(proxyServer).options("/testCross")
173+
.set("Origin","www.google.com")
174+
.set("Access-Control-Request-Headers","accesstoken,secretname")
175+
.set("Access-Control-Request-Methods","POST");
176+
expect(optionResponse.statusCode).toBe(200);
177+
expect(optionResponse.get("Access-Control-Allow-Origin")).toEqual("www.google.com");
178+
expect(optionResponse.get("Access-Control-Allow-Headers")).toContain("accesstoken");
179+
expect(optionResponse.get("Access-Control-Allow-Headers")).toContain("secretname");
180+
expect(optionResponse.get("Access-Control-Allow-Credentials")).toContain("true");
181+
});
182+
183+
137184
});
138185

139186
async function getLastLog(projectId:string,path:string){

core/struct/action.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export interface ProxyActionM {
3737
handleCross:boolean;
3838
crossAllowCredentials:boolean;
3939
pathRewrite: Array<PathRewriteM>;
40+
headers: Array<[string, string]>|undefined;
4041
}
4142

4243
export interface CustomResponseActionM {
@@ -80,6 +81,7 @@ export function createProxyAction(): ProxyActionM {
8081
protocol:ProxyProtocol.HTTP,
8182
handleCross:false,
8283
crossAllowCredentials:false,
84+
headers:[]
8385
};
8486
}
8587

core/struct/systemConfig.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
export interface SystemConfigM{
3+
version:number;
4+
}

desktop/electron/action/ProxyAction.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,25 @@ let proxy = httpProxy.createProxyServer({});
1616

1717
proxy.on("proxyReq", function (proxyReq, req, res, options) {
1818
fixRequestBody(proxyReq, req as express.Request);
19-
const proxyAction = (options as any).proxyAction as ProxyActionM;
20-
//
21-
if (proxyAction.handleCross) {
22-
// handle cross
23-
handleOptionsCross(
24-
req as express.Request,
25-
res as express.Response,
26-
proxyAction.crossAllowCredentials
27-
);
28-
}
19+
2920
});
3021
proxy.on("proxyRes", function (proxyRes: http.IncomingMessage, req, res) {
3122
let body: Array<any> = [];
3223
const recordBody = isRecordBody(req, proxyRes);
24+
const proxyAction = (req as any).proxyAction as ProxyActionM;
25+
// handle cross`
26+
if (proxyAction.handleCross) {
27+
// handle cross
28+
handleRequestCross(
29+
req as express.Request,
30+
proxyRes,
31+
proxyAction.crossAllowCredentials
32+
);
33+
}
34+
// handle the external headers
35+
if (proxyAction.headers && proxyAction.headers.length > 0){
36+
handleExternalHeaders(req as express.Request,proxyRes,proxyAction.headers);
37+
}
3338
proxyRes.on("data", function (chunk) {
3439
if (recordBody) {
3540
body.push(chunk);
@@ -87,6 +92,19 @@ function handleOptionsCross(
8792
res.end();
8893
}
8994

95+
/**
96+
*
97+
* @param req
98+
* @param res
99+
* @param headers
100+
*/
101+
function handleExternalHeaders(req: express.Request,
102+
res: http.IncomingMessage,
103+
headers:Array<[string,string]>){
104+
headers.forEach(item=>{
105+
res.headers[item[0].toLowerCase()] = item[1];
106+
});
107+
}
90108
/**
91109
*
92110
* @param req
@@ -96,10 +114,10 @@ function handleOptionsCross(
96114
*/
97115
function handleRequestCross(
98116
req: express.Request,
99-
res: express.Response,
117+
res: http.IncomingMessage,
100118
crossAllowCredentials: boolean
101119
) {
102-
res.header("Access-Control-Allow-Origin", req.get("Origin"));
120+
res.headers['Access-Control-Allow-Origin'.toLowerCase()] = req.get("Origin");
103121
const headerKeySet = new Set<string>();
104122
req.rawHeaders.forEach((item, index) => {
105123
if (index % 2 === 0) {
@@ -111,10 +129,10 @@ function handleRequestCross(
111129
headerArray.push(item);
112130
});
113131
const headerStr = headerArray.join(",");
114-
res.header("Access-Control-Allow-Headers", headerStr);
115-
res.header("Access-Control-Allow-Methods", req.method.toUpperCase());
132+
res.headers['Access-Control-Allow-Headers'] = headerStr;
133+
res.headers["Access-Control-Allow-Methods"] = req.method.toUpperCase();
116134
if (crossAllowCredentials) {
117-
res.header("Access-Control-Allow-Credentials", "true");
135+
res.headers["Access-Control-Allow-Credentials"] = "true";
118136
}
119137
}
120138

@@ -145,6 +163,7 @@ export default class ProxyActionImpl implements IAction {
145163
},
146164
proxyAction: this.action,
147165
};
166+
(req as any).proxyAction = this.action;
148167
res.on("end", () => {
149168
resolve();
150169
});

desktop/electron/db/dbManager.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ProjectM } from "core/struct/project";
44
import { ExpectationM } from "core/struct/expectation";
55
import { LogViewM } from "core/struct/logView";
66
import { LogM } from "core/struct/log";
7+
import {SystemConfigM} from "core/struct/systemConfig";
78

89

910
const projectDbPromiseMap = new Map<string, Promise<Loki>>();
@@ -53,6 +54,16 @@ export async function getProjectCollection(path: string) {
5354
return entries;
5455
}
5556

57+
export async function getSystemCollection(path:string){
58+
const projectDb = await getProjectDb(path);
59+
let entries = projectDb.getCollection<SystemConfigM>("system");
60+
if (entries === null) {
61+
entries = projectDb.addCollection<SystemConfigM>("system");
62+
}
63+
return entries;
64+
}
65+
66+
5667
export async function getExpectationCollection(
5768
projectId: string,
5869
path: string

desktop/electron/main.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { setLogFilterHandler } from "./handler/logFilterHandler";
1313
import { Menu, shell, MenuItem } from "electron";
1414
import * as console from "console";
1515
import { buildMenu } from "./buildMenu";
16+
import { getSystemCollection } from "./db/dbManager";
17+
import {systemVersion} from "../src/config";
1618
// The built directory structure
1719
//
1820
// ├─┬─┬ dist
@@ -32,9 +34,20 @@ let win: BrowserWindow | null;
3234
const VITE_DEV_SERVER_URL = process.env["VITE_DEV_SERVER_URL"];
3335

3436
const env = process.env["PROJECT_ENV"];
37+
38+
async function projectInit() {
39+
const systemCollection = await getSystemCollection(app.getPath("userData"));
40+
const systemConfig = systemCollection.findOne({});
41+
if(systemConfig){
42+
43+
}else{
44+
systemCollection.insertOne({version:systemVersion});
45+
}
46+
}
47+
3548
async function createWindow() {
3649
buildMenu();
37-
50+
await projectInit();
3851
await setProjectHandler(app.getPath("userData"));
3952
await setExpectationHandler(app.getPath("userData"));
4053
await setMatcherHandler(app.getPath("userData"));

0 commit comments

Comments
 (0)