forked from doza62/opencode-mobile
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreverse-proxy.ts
More file actions
125 lines (105 loc) · 3.43 KB
/
Copy pathreverse-proxy.ts
File metadata and controls
125 lines (105 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import http, { request as httpRequest } from "http";
export interface ProxyConfig {
proxyPort: number;
serverPort: number;
tokenApiPort: number;
}
let serverStarted = false;
let server: http.Server | null = null;
export function startProxy(config: ProxyConfig): Promise<void> {
// Validate config
if (!config?.proxyPort || !config?.serverPort || !config?.tokenApiPort) {
console.log("[Proxy] Invalid config received (re-init?), skipping");
console.log("[Proxy] startProxy called from:", new Error().stack?.split('\n').slice(2, 6).join('\n'));
return Promise.resolve();
}
return new Promise((resolve, reject) => {
if (serverStarted) {
console.log("[Proxy] Proxy already running");
resolve();
return;
}
server = http.createServer((clientReq, clientRes) => {
const url = clientReq.url || "";
const targetPort = url.startsWith("/push-token")
? config.tokenApiPort
: config.serverPort;
const options = {
hostname: "127.0.0.1",
port: targetPort,
path: url,
method: clientReq.method,
headers: {
...clientReq.headers,
"x-forwarded-for": clientReq.socket.remoteAddress,
"x-forwarded-host": clientReq.headers.host,
},
};
const proxyReq = httpRequest(options, (proxyRes) => {
clientRes.writeHead(proxyRes.statusCode || 200, proxyRes.headers);
// Clean up listeners when done
const cleanup = () => {
proxyRes.removeListener("data", onData);
proxyRes.removeListener("end", onEnd);
proxyRes.removeListener("error", onError);
};
const onData = (chunk: Buffer) => {
clientRes.write(chunk);
};
const onEnd = () => {
cleanup();
clientRes.end();
};
const onError = (err: Error) => {
cleanup();
if (!clientRes.headersSent) {
clientRes.writeHead(502, { "Content-Type": "text/plain" });
clientRes.end("Proxy error");
}
};
proxyRes.on("data", onData);
proxyRes.on("end", onEnd);
proxyRes.on("error", onError);
// Clean up if client disconnects
clientRes.on("close", cleanup);
});
proxyReq.on("error", (err: any) => {
console.error("[Proxy] Error forwarding request:", err.message);
if (!clientRes.headersSent) {
clientRes.writeHead(502, { "Content-Type": "text/plain" });
clientRes.end("Bad Gateway");
}
});
clientReq.pipe(proxyReq);
});
server.on("error", (err: any) => {
if (err.code === "EADDRINUSE") {
console.log("[Proxy] Port already in use - proxy likely already running");
serverStarted = true;
resolve();
} else {
console.error("[Proxy] Failed to start:", err.message);
reject(err);
}
});
server.listen(config.proxyPort, () => {
serverStarted = true;
console.log(`[Proxy] Running on port ${config.proxyPort}`);
console.log(`[Proxy] /push-token/* → Port ${config.tokenApiPort}`);
console.log(`[Proxy] /* → Port ${config.serverPort}`);
resolve();
});
});
}
export function stopProxy(): void {
if (server) {
server.close(() => {
console.log("[Proxy] Server stopped");
});
server = null;
serverStarted = false;
}
}
export function isProxyRunning(): boolean {
return serverStarted;
}