WalleGriffkinder commited on
Commit
85a98e1
·
verified ·
1 Parent(s): 22613d0

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +61 -23
index.js CHANGED
@@ -11,51 +11,89 @@ app.get('/', (req, res) => {
11
 
12
  // Прокси для всех остальных путей
13
  app.all('*', async (req, res) => {
14
- if (req.url === '/') return;
 
 
 
 
 
 
 
15
 
16
  try {
17
- // Извлекаем URL из пути, пропуская первый слэш
 
 
18
  const targetUrl = req.url.substring(1);
19
-
20
- // Проверяем что URL валидный
21
- if (!targetUrl.startsWith('http')) {
22
- return res.status(400).send('Invalid URL');
23
- }
24
 
 
 
 
 
 
 
25
  // Копируем и фильтруем заголовки
26
  const headers = {...req.headers};
27
- delete headers['host'];
28
- delete headers['content-length'];
29
 
30
- const response = await fetch(targetUrl, {
31
  method: req.method,
32
  headers,
33
- body: req.method !== 'GET' ? req.body : undefined
 
 
 
 
 
34
  });
35
 
36
- // Streaming response
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  if (response.headers.get('content-type')?.includes('text/event-stream')) {
38
- res.setHeader('Content-Type', 'text/event-stream');
39
  response.body.pipe(res);
40
  return;
41
  }
42
 
43
  // Regular response
44
- const data = await response.buffer();
45
-
46
- // Копируем все заголовки из ответа
47
- for (const [key, value] of response.headers.entries()) {
48
- res.setHeader(key, value);
 
49
  }
50
-
51
- res.status(response.status);
52
- res.send(data);
53
 
54
  } catch (error) {
55
- res.status(500).send(error.message);
 
 
 
 
 
 
 
 
 
 
 
56
  }
57
  });
58
 
59
  app.listen(7860, '0.0.0.0', () => {
60
- console.log('Server running on port 7860');
 
61
  });
 
11
 
12
  // Прокси для всех остальных путей
13
  app.all('*', async (req, res) => {
14
+ // Этот if (req.url === '/') вероятно, не нужен, если app.get('/') обрабатывает '/',
15
+ // но оставим для безопасности, если app.all('*') почему-то получит запрос к '/'
16
+ if (req.url === '/') {
17
+ // Если это корневой путь, и он не был обработан app.get('/'),
18
+ // то здесь можно вернуть ошибку или специфический ответ.
19
+ // В данном случае, лучше ничего не делать, так как app.get('/') должен его поймать.
20
+ return;
21
+ }
22
 
23
  try {
24
+ // Извлекаем целевой URL из пути запроса
25
+ // req.url будет выглядеть как "/https://anotherurl.com?param=value"
26
+ // Мы удаляем первый символ '/', чтобы получить "https://anotherurl.com?param=value"
27
  const targetUrl = req.url.substring(1);
 
 
 
 
 
28
 
29
+ // Проверяем, не пустой ли targetUrl после удаления '/', на всякий случай
30
+ if (!targetUrl) {
31
+ res.status(400).send('Target URL is missing in the path.');
32
+ return;
33
+ }
34
+
35
  // Копируем и фильтруем заголовки
36
  const headers = {...req.headers};
37
+ delete headers['host']; // host будет установлен fetch на основе targetUrl
38
+ delete headers['content-length']; // content-length будет пересчитан fetch
39
 
40
+ const response = await fetch(targetUrl, { // Используем извлеченный targetUrl
41
  method: req.method,
42
  headers,
43
+ // Отправляем тело запроса, если это не GET или HEAD запрос
44
+ body: (req.method !== 'GET' && req.method !== 'HEAD') ? req.body : undefined,
45
+ // Важно для проксирования: redirect: 'manual' или 'follow' в зависимости от нужного поведения
46
+ // 'follow' (по умолчанию) будет автоматически следовать редиректам от целевого сервера
47
+ // 'manual' позволит прокси вернуть редирект клиенту как есть
48
+ redirect: 'manual' // Или 'follow', если хотите, чтобы прокси сам следовал редиректам
49
  });
50
 
51
+ // Копируем все заголовки из ответа целевого сервера
52
+ Object.entries(response.headers.raw()).forEach(([key, value]) => {
53
+ // Некоторые заголовки, такие как 'content-encoding', могут быть проблемой,
54
+ // если тело ответа изменяется (например, автоматическое распаковывание gzip fetch'ем)
55
+ // Однако, если мы стримим или передаем buffer, это должно быть в порядке.
56
+ // Для безопасности, можно добавить фильтрацию специфичных заголовков здесь при необходимости.
57
+ if (value) {
58
+ res.setHeader(key, value.length === 1 ? value[0] : value);
59
+ }
60
+ });
61
+
62
+ res.status(response.status);
63
+
64
+ // Streaming response для text/event-stream
65
  if (response.headers.get('content-type')?.includes('text/event-stream')) {
66
+ // res.setHeader('Content-Type', 'text/event-stream'); // Уже установлено циклом выше
67
  response.body.pipe(res);
68
  return;
69
  }
70
 
71
  // Regular response
72
+ // Используем response.body.pipe(res) для более эффективной передачи больших ответов
73
+ // response.buffer() загружает весь ответ в память перед отправкой.
74
+ if (response.body) {
75
+ response.body.pipe(res);
76
+ } else {
77
+ res.end();
78
  }
 
 
 
79
 
80
  } catch (error) {
81
+ console.error('Proxy error:', error);
82
+ // Отправляем более информативное сообщение об ошибке, если это возможно
83
+ // Избегайте отправки error.message напрямую клиенту в продакшене без санации,
84
+ // так как оно может содержать чувствительную информацию.
85
+ if (error.code === 'ENOTFOUND' || error.message.includes('invalid URL')) {
86
+ res.status(400).send(`Invalid target URL or host not found: ${req.url.substring(1)}`);
87
+ } else if (error.message.includes('ECONNREFUSED')) {
88
+ res.status(502).send(`Bad Gateway: Could not connect to target server at ${req.url.substring(1)}`);
89
+ }
90
+ else {
91
+ res.status(500).send('Proxy error occurred.');
92
+ }
93
  }
94
  });
95
 
96
  app.listen(7860, '0.0.0.0', () => {
97
+ console.log('Server running on port 7860. Proxying requests from path to the specified URL.');
98
+ console.log('Example: http://localhost:7860/https://www.google.com will proxy to https://www.google.com');
99
  });