Update server.js
Browse files
server.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
| 1 |
-
|
| 2 |
import express from 'express';
|
| 3 |
-
import http from 'http';
|
| 4 |
import { spawn } from 'child_process';
|
| 5 |
-
import url from 'url';
|
| 6 |
import fetch from 'node-fetch';
|
| 7 |
|
| 8 |
-
const PROXY_PORT = 3000;
|
| 9 |
-
const SECONDARY_SERVER_PORT = 7860;
|
| 10 |
|
| 11 |
-
// Функция для форматирования информации о запросе
|
| 12 |
function formatRequestInfo(req, serverType = 'express') {
|
| 13 |
let info = 'ИНФОРМАЦИЯ О ЗАПРОСЕ:\n\n';
|
| 14 |
let reqUrl, queryParams, clientIp;
|
|
@@ -49,7 +47,6 @@ function formatRequestInfo(req, serverType = 'express') {
|
|
| 49 |
return info;
|
| 50 |
}
|
| 51 |
|
| 52 |
-
// --- Сервер 1: CORS Proxy на порту PROXY_PORT (будет туннелироваться через serveo.net) ---
|
| 53 |
const proxyApp = express();
|
| 54 |
|
| 55 |
proxyApp.use(express.raw({
|
|
@@ -85,12 +82,12 @@ proxyApp.get('/', (req, res) => {
|
|
| 85 |
const origin = req.headers.origin;
|
| 86 |
addCorsHeaders(res, origin);
|
| 87 |
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
| 88 |
-
res.send(`CORS Proxy is running on port ${PROXY_PORT}. Append target URL to proxy, e.g., /http://example.com. Tunnel
|
| 89 |
});
|
| 90 |
|
| 91 |
proxyApp.all('*', async (req, res) => {
|
| 92 |
if (req.path === '/') {
|
| 93 |
-
return;
|
| 94 |
}
|
| 95 |
|
| 96 |
const clientRequestOrigin = req.headers.origin;
|
|
@@ -124,7 +121,7 @@ proxyApp.all('*', async (req, res) => {
|
|
| 124 |
res.status(400).send(`Invalid target URL provided in path: ${targetUrlString}. Error: ${e.message}`);
|
| 125 |
return;
|
| 126 |
}
|
| 127 |
-
|
| 128 |
const requestHeaders = {...req.headers};
|
| 129 |
delete requestHeaders['host'];
|
| 130 |
delete requestHeaders['content-length'];
|
|
@@ -140,17 +137,17 @@ proxyApp.all('*', async (req, res) => {
|
|
| 140 |
|
| 141 |
proxyResponse.headers.forEach((value, key) => {
|
| 142 |
const lowerKey = key.toLowerCase();
|
| 143 |
-
if (!lowerKey.startsWith('access-control-') &&
|
| 144 |
-
!['strict-transport-security', 'content-security-policy', 'public-key-pins',
|
| 145 |
-
'transfer-encoding', 'connection', 'keep-alive', 'proxy-authenticate',
|
| 146 |
'proxy-authorization', 'te', 'trailers', 'upgrade'].includes(lowerKey)
|
| 147 |
) {
|
| 148 |
res.setHeader(key, value);
|
| 149 |
}
|
| 150 |
});
|
| 151 |
-
|
| 152 |
addCorsHeaders(res, clientRequestOrigin);
|
| 153 |
-
const exposedHeaders = Array.from(proxyResponse.headers.keys()).filter(key =>
|
| 154 |
!key.toLowerCase().startsWith('access-control-') &&
|
| 155 |
key.toLowerCase() !== 'transfer-encoding' &&
|
| 156 |
key.toLowerCase() !== 'connection'
|
|
@@ -161,7 +158,7 @@ proxyApp.all('*', async (req, res) => {
|
|
| 161 |
} else {
|
| 162 |
res.setHeader('Access-Control-Expose-Headers', '*');
|
| 163 |
}
|
| 164 |
-
|
| 165 |
res.status(proxyResponse.status);
|
| 166 |
|
| 167 |
if (proxyResponse.body) {
|
|
@@ -196,44 +193,31 @@ proxyApp.listen(PROXY_PORT, '0.0.0.0', () => {
|
|
| 196 |
console.log(`CORS Proxy server (для туннеля) слушает порт ${PROXY_PORT}`);
|
| 197 |
|
| 198 |
console.log(`Попытка запустить туннель serveo.net для порта ${PROXY_PORT}...`);
|
| 199 |
-
// Команда для serveo.net: ssh -R 80:localhost:3000 serveo.net
|
| 200 |
-
// Опции -o StrictHostKeyChecking=no и -o UserKnownHostsFile=/dev/null также полезны
|
| 201 |
const tunnel = spawn('ssh', [
|
| 202 |
'-R', `80:localhost:${PROXY_PORT}`,
|
| 203 |
'-o', 'StrictHostKeyChecking=no',
|
| 204 |
'-o', 'UserKnownHostsFile=/dev/null',
|
| 205 |
-
'-o', 'ServerAliveInterval=60',
|
| 206 |
-
'-o', 'ExitOnForwardFailure=yes',
|
| 207 |
-
'-o', 'ConnectTimeout=
|
| 208 |
-
'serveo.net'
|
| 209 |
]);
|
| 210 |
|
| 211 |
tunnel.stdout.on('data', (data) => {
|
| 212 |
const output = data.toString();
|
| 213 |
-
console.log(`
|
| 214 |
-
// Serveo.net обычно выводит что-то вроде:
|
| 215 |
-
// Forwarding HTTP traffic from https://[subdomain].serveo.net
|
| 216 |
-
// Forwarding TCP traffic from serveo.net:[port]
|
| 217 |
const urlMatch = output.match(/https?:\/\/[a-zA-Z0-9-]+\.serveo\.net/);
|
| 218 |
if (urlMatch) {
|
| 219 |
-
console.log(`>>> Туннель
|
| 220 |
}
|
| 221 |
});
|
| 222 |
|
| 223 |
tunnel.stderr.on('data', (data) => {
|
| 224 |
-
|
| 225 |
-
console.error(`Serveo.net stderr: ${output}`);
|
| 226 |
-
// Serveo может запросить подтверждение ключа при первом подключении,
|
| 227 |
-
// но с -o StrictHostKeyChecking=no этого быть не должно.
|
| 228 |
-
// Если в выводе есть "Warning: remote host identification has changed!",
|
| 229 |
-
// это может быть проблемой, если IP serveo.net изменился. /dev/null для KnownHosts должен это решать.
|
| 230 |
});
|
| 231 |
|
| 232 |
tunnel.on('close', (code) => {
|
| 233 |
console.log(`Процесс serveo.net завершился с кодом ${code}`);
|
| 234 |
-
if (code !== 0 && code !== null) { // null может быть если процесс убит сигналом
|
| 235 |
-
console.error(">>> Туннель serveo.net закрылся неожиданно. Может потребоваться перезапуск.");
|
| 236 |
-
}
|
| 237 |
});
|
| 238 |
|
| 239 |
tunnel.on('error', (err) => {
|
|
@@ -241,12 +225,10 @@ proxyApp.listen(PROXY_PORT, '0.0.0.0', () => {
|
|
| 241 |
});
|
| 242 |
});
|
| 243 |
|
| 244 |
-
|
| 245 |
-
// --- Сервер 2: Простой HTTP-сервер на порту SECONDARY_SERVER_PORT ---
|
| 246 |
const secondaryServer = http.createServer((req, res) => {
|
| 247 |
if (req.url === '/' && req.method === 'GET') {
|
| 248 |
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
| 249 |
-
res.end(`Hello World from secondary server on port ${SECONDARY_SERVER_PORT}
|
| 250 |
} else {
|
| 251 |
const requestInfo = formatRequestInfo(req, 'http');
|
| 252 |
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
@@ -255,11 +237,9 @@ const secondaryServer = http.createServer((req, res) => {
|
|
| 255 |
});
|
| 256 |
|
| 257 |
secondaryServer.listen(SECONDARY_SERVER_PORT, '0.0.0.0', () => {
|
| 258 |
-
console.log(`Второй HTTP-сервер слушает порт ${SECONDARY_SERVER_PORT}`);
|
| 259 |
});
|
| 260 |
|
| 261 |
-
|
| 262 |
-
// Обработка сигналов для корректного завершения
|
| 263 |
process.on('SIGINT', () => {
|
| 264 |
console.log('Получен SIGINT. Завершение...');
|
| 265 |
process.exit(0);
|
|
|
|
|
|
|
| 1 |
import express from 'express';
|
| 2 |
+
import http from 'http';
|
| 3 |
import { spawn } from 'child_process';
|
| 4 |
+
import url from 'url';
|
| 5 |
import fetch from 'node-fetch';
|
| 6 |
|
| 7 |
+
const PROXY_PORT = 3000;
|
| 8 |
+
const SECONDARY_SERVER_PORT = 7860;
|
| 9 |
|
|
|
|
| 10 |
function formatRequestInfo(req, serverType = 'express') {
|
| 11 |
let info = 'ИНФОРМАЦИЯ О ЗАПРОСЕ:\n\n';
|
| 12 |
let reqUrl, queryParams, clientIp;
|
|
|
|
| 47 |
return info;
|
| 48 |
}
|
| 49 |
|
|
|
|
| 50 |
const proxyApp = express();
|
| 51 |
|
| 52 |
proxyApp.use(express.raw({
|
|
|
|
| 82 |
const origin = req.headers.origin;
|
| 83 |
addCorsHeaders(res, origin);
|
| 84 |
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
| 85 |
+
res.send(`CORS Proxy is running on port ${PROXY_PORT}. Append target URL to proxy, e.g., /http://example.com. Tunnel will be established for this port.`);
|
| 86 |
});
|
| 87 |
|
| 88 |
proxyApp.all('*', async (req, res) => {
|
| 89 |
if (req.path === '/') {
|
| 90 |
+
return;
|
| 91 |
}
|
| 92 |
|
| 93 |
const clientRequestOrigin = req.headers.origin;
|
|
|
|
| 121 |
res.status(400).send(`Invalid target URL provided in path: ${targetUrlString}. Error: ${e.message}`);
|
| 122 |
return;
|
| 123 |
}
|
| 124 |
+
|
| 125 |
const requestHeaders = {...req.headers};
|
| 126 |
delete requestHeaders['host'];
|
| 127 |
delete requestHeaders['content-length'];
|
|
|
|
| 137 |
|
| 138 |
proxyResponse.headers.forEach((value, key) => {
|
| 139 |
const lowerKey = key.toLowerCase();
|
| 140 |
+
if (!lowerKey.startsWith('access-control-') &&
|
| 141 |
+
!['strict-transport-security', 'content-security-policy', 'public-key-pins',
|
| 142 |
+
'transfer-encoding', 'connection', 'keep-alive', 'proxy-authenticate',
|
| 143 |
'proxy-authorization', 'te', 'trailers', 'upgrade'].includes(lowerKey)
|
| 144 |
) {
|
| 145 |
res.setHeader(key, value);
|
| 146 |
}
|
| 147 |
});
|
| 148 |
+
|
| 149 |
addCorsHeaders(res, clientRequestOrigin);
|
| 150 |
+
const exposedHeaders = Array.from(proxyResponse.headers.keys()).filter(key =>
|
| 151 |
!key.toLowerCase().startsWith('access-control-') &&
|
| 152 |
key.toLowerCase() !== 'transfer-encoding' &&
|
| 153 |
key.toLowerCase() !== 'connection'
|
|
|
|
| 158 |
} else {
|
| 159 |
res.setHeader('Access-Control-Expose-Headers', '*');
|
| 160 |
}
|
| 161 |
+
|
| 162 |
res.status(proxyResponse.status);
|
| 163 |
|
| 164 |
if (proxyResponse.body) {
|
|
|
|
| 193 |
console.log(`CORS Proxy server (для туннеля) слушает порт ${PROXY_PORT}`);
|
| 194 |
|
| 195 |
console.log(`Попытка запустить туннель serveo.net для порта ${PROXY_PORT}...`);
|
|
|
|
|
|
|
| 196 |
const tunnel = spawn('ssh', [
|
| 197 |
'-R', `80:localhost:${PROXY_PORT}`,
|
| 198 |
'-o', 'StrictHostKeyChecking=no',
|
| 199 |
'-o', 'UserKnownHostsFile=/dev/null',
|
| 200 |
+
'-o', 'ServerAliveInterval=60',
|
| 201 |
+
'-o', 'ExitOnForwardFailure=yes',
|
| 202 |
+
'-o', 'ConnectTimeout=20', // Increased timeout slightly for serveo
|
| 203 |
+
'serveo.net'
|
| 204 |
]);
|
| 205 |
|
| 206 |
tunnel.stdout.on('data', (data) => {
|
| 207 |
const output = data.toString();
|
| 208 |
+
console.log(`serveo.net stdout: ${output}`);
|
|
|
|
|
|
|
|
|
|
| 209 |
const urlMatch = output.match(/https?:\/\/[a-zA-Z0-9-]+\.serveo\.net/);
|
| 210 |
if (urlMatch) {
|
| 211 |
+
console.log(`>>> Туннель для PROXY (порт ${PROXY_PORT}) через serveo.net активен: ${urlMatch[0]}`);
|
| 212 |
}
|
| 213 |
});
|
| 214 |
|
| 215 |
tunnel.stderr.on('data', (data) => {
|
| 216 |
+
console.error(`serveo.net stderr: ${data}`);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
});
|
| 218 |
|
| 219 |
tunnel.on('close', (code) => {
|
| 220 |
console.log(`Процесс serveo.net завершился с кодом ${code}`);
|
|
|
|
|
|
|
|
|
|
| 221 |
});
|
| 222 |
|
| 223 |
tunnel.on('error', (err) => {
|
|
|
|
| 225 |
});
|
| 226 |
});
|
| 227 |
|
|
|
|
|
|
|
| 228 |
const secondaryServer = http.createServer((req, res) => {
|
| 229 |
if (req.url === '/' && req.method === 'GET') {
|
| 230 |
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
| 231 |
+
res.end(`Hello World from secondary server on port ${SECONDARY_SERVER_PORT}!`);
|
| 232 |
} else {
|
| 233 |
const requestInfo = formatRequestInfo(req, 'http');
|
| 234 |
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
|
|
| 237 |
});
|
| 238 |
|
| 239 |
secondaryServer.listen(SECONDARY_SERVER_PORT, '0.0.0.0', () => {
|
| 240 |
+
console.log(`Второй HTTP-сервер (для Hugging Face / Hello World) слушает порт ${SECONDARY_SERVER_PORT}`);
|
| 241 |
});
|
| 242 |
|
|
|
|
|
|
|
| 243 |
process.on('SIGINT', () => {
|
| 244 |
console.log('Получен SIGINT. Завершение...');
|
| 245 |
process.exit(0);
|