3v324v23 commited on
Commit
f56bbc4
·
1 Parent(s): 82f851a

Добавление прокси-сервера для отладки и перехвата запросов UI-API

Browse files
Files changed (2) hide show
  1. Dockerfile +4 -1
  2. app.py +141 -3
Dockerfile CHANGED
@@ -22,6 +22,9 @@ RUN apt-get clean && apt-get update && apt-get install -y --no-install-recommend
22
  ca-certificates \
23
  && apt-get clean && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/*
24
 
 
 
 
25
  # Установка Go 1.21
26
  RUN wget https://golang.org/dl/go1.21.0.linux-amd64.tar.gz && \
27
  tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz && \
@@ -189,7 +192,7 @@ RUN chmod +x /app/app.py && \
189
  USER tenuser
190
 
191
  # Открываем порты
192
- EXPOSE 7860 8080 3000
193
 
194
  # Запускаем API сервер и Playground в dev-режиме
195
  ENTRYPOINT ["python3", "/app/app.py"]
 
22
  ca-certificates \
23
  && apt-get clean && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/*
24
 
25
+ # Установка Python-пакетов
26
+ RUN pip3 install requests
27
+
28
  # Установка Go 1.21
29
  RUN wget https://golang.org/dl/go1.21.0.linux-amd64.tar.gz && \
30
  tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz && \
 
192
  USER tenuser
193
 
194
  # Открываем порты
195
+ EXPOSE 7860 8080 3000 9090
196
 
197
  # Запускаем API сервер и Playground в dev-режиме
198
  ENTRYPOINT ["python3", "/app/app.py"]
app.py CHANGED
@@ -12,6 +12,11 @@ import logging
12
  import urllib.request
13
  import urllib.error
14
  import tempfile
 
 
 
 
 
15
 
16
  # Настройка логирования
17
  logging.basicConfig(level=logging.INFO,
@@ -30,6 +35,133 @@ API_BINARY = Path("/app/server/bin/api")
30
  PLAYGROUND_DIR = Path("/app/playground")
31
  BACKUP_DIR = Path("/app/backup")
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  def ensure_directory_permissions(directory_path):
34
  """Обеспечиваем правильные разрешения для директории"""
35
  directory = Path(directory_path)
@@ -264,17 +396,23 @@ def main():
264
  test_thread.daemon = True
265
  test_thread.start()
266
 
 
 
 
 
 
 
267
  # Запускаем Playground UI в режиме dev на порту 7860 (порт Hugging Face)
268
  logger.info("Запуск Playground UI в режиме разработки на порту 7860...")
269
  os.environ["PORT"] = "7860"
270
- os.environ["AGENT_SERVER_URL"] = "http://localhost:8080"
271
  os.environ["NEXT_PUBLIC_EDIT_GRAPH_MODE"] = "true" # Включаем расширенный режим редактирования
272
  os.environ["NEXT_PUBLIC_DISABLE_CAMERA"] = "true" # Отключаем запрос на использование камеры
273
 
274
  # Важные переменные для отключения запросов к дизайнеру
275
  os.environ["NEXT_PUBLIC_DEV_MODE"] = "false"
276
- os.environ["NEXT_PUBLIC_API_BASE_URL"] = "/api/agents"
277
- os.environ["NEXT_PUBLIC_DESIGNER_API_URL"] = "http://localhost:8080"
278
 
279
  # Запускаем Playground UI
280
  playground_process = subprocess.Popen(
 
12
  import urllib.request
13
  import urllib.error
14
  import tempfile
15
+ import http.server
16
+ import socketserver
17
+ import requests
18
+ from threading import Thread
19
+ from http import HTTPStatus
20
 
21
  # Настройка логирования
22
  logging.basicConfig(level=logging.INFO,
 
35
  PLAYGROUND_DIR = Path("/app/playground")
36
  BACKUP_DIR = Path("/app/backup")
37
 
38
+ class ProxyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
39
+ """HTTP-прокси для отладки и исправления запросов между UI и API"""
40
+
41
+ def __init__(self, *args, **kwargs):
42
+ # Целевой API сервер
43
+ self.api_host = "localhost"
44
+ self.api_port = 8080
45
+ super().__init__(*args, **kwargs)
46
+
47
+ def do_GET(self):
48
+ """Обработка GET запросов"""
49
+ logger.info(f"PROXY: GET запрос: {self.path}")
50
+
51
+ # Специальная обработка для запроса графов
52
+ if self.path == "/graphs" or self.path == "/api/agents/graphs":
53
+ self._handle_graphs_request()
54
+ return
55
+
56
+ # Проксирование запроса к API
57
+ target_url = f"http://{self.api_host}:{self.api_port}{self.path}"
58
+ try:
59
+ response = requests.get(target_url, headers=self._get_headers())
60
+ self._send_response(response)
61
+ except Exception as e:
62
+ logger.error(f"PROXY: Ошибка при проксировании GET-запроса: {e}")
63
+ self.send_error(HTTPStatus.INTERNAL_SERVER_ERROR, str(e))
64
+
65
+ def do_POST(self):
66
+ """Обработка POST запросов"""
67
+ content_length = int(self.headers.get('Content-Length', 0))
68
+ post_data = self.rfile.read(content_length) if content_length > 0 else b''
69
+
70
+ logger.info(f"PROXY: POST запрос: {self.path}")
71
+
72
+ # Специальные запросы для дизайнера
73
+ if "/api/designer/v1/packages/reload" in self.path or "/api/dev/v1/packages/reload" in self.path:
74
+ self._handle_designer_reload()
75
+ return
76
+
77
+ # Проксирование запроса к API
78
+ target_url = f"http://{self.api_host}:{self.api_port}{self.path}"
79
+ try:
80
+ response = requests.post(target_url, data=post_data, headers=self._get_headers())
81
+ self._send_response(response)
82
+ except Exception as e:
83
+ logger.error(f"PROXY: Ошибка при проксировании POST-запроса: {e}")
84
+ self.send_error(HTTPStatus.INTERNAL_SERVER_ERROR, str(e))
85
+
86
+ def _handle_graphs_request(self):
87
+ """Специальная обработка для запроса графов"""
88
+ try:
89
+ # Читаем графы из property.json
90
+ with open(PROPERTY_JSON, 'r') as f:
91
+ property_data = json.load(f)
92
+
93
+ graphs = property_data.get('graphs', [])
94
+ logger.info(f"PROXY: Возвращаем графы напрямую: {json.dumps(graphs)}")
95
+
96
+ self.send_response(HTTPStatus.OK)
97
+ self.send_header('Content-Type', 'application/json')
98
+ self.end_headers()
99
+ self.wfile.write(json.dumps(graphs).encode('utf-8'))
100
+ except Exception as e:
101
+ logger.error(f"PROXY: Ошибка при обработке запроса графов: {e}")
102
+ self.send_error(HTTPStatus.INTERNAL_SERVER_ERROR, str(e))
103
+
104
+ def _handle_designer_reload(self):
105
+ """Обработка запросов дизайнера"""
106
+ response_data = {
107
+ "success": True,
108
+ "packages": [
109
+ {
110
+ "name": "default",
111
+ "description": "Default package",
112
+ "graphs": []
113
+ }
114
+ ]
115
+ }
116
+
117
+ # Читаем графы из property.json
118
+ try:
119
+ with open(PROPERTY_JSON, 'r') as f:
120
+ property_data = json.load(f)
121
+
122
+ graphs = property_data.get('graphs', [])
123
+ response_data["packages"][0]["graphs"] = graphs
124
+ logger.info(f"PROXY: Возвращаем данные для дизайнера с графами: {json.dumps(graphs)}")
125
+ except Exception as e:
126
+ logger.error(f"PROXY: Ошибка при чтении графов для дизайнера: {e}")
127
+
128
+ self.send_response(HTTPStatus.OK)
129
+ self.send_header('Content-Type', 'application/json')
130
+ self.end_headers()
131
+ self.wfile.write(json.dumps(response_data).encode('utf-8'))
132
+
133
+ def _get_headers(self):
134
+ """Получение заголовков для проксирования"""
135
+ headers = {}
136
+ for header in self.headers:
137
+ headers[header] = self.headers[header]
138
+ return headers
139
+
140
+ def _send_response(self, response):
141
+ """Отправка ответа клиенту"""
142
+ self.send_response(response.status_code)
143
+
144
+ # Копируем заголовки
145
+ for header, value in response.headers.items():
146
+ self.send_header(header, value)
147
+ self.end_headers()
148
+
149
+ # Отправляем тело ответа
150
+ self.wfile.write(response.content)
151
+
152
+ def log_message(self, format, *args):
153
+ """Переопределение логирования"""
154
+ logger.debug(f"PROXY: {self.address_string()} - {format % args}")
155
+
156
+ def run_proxy_server(port=9090):
157
+ """Запуск прокси-сервера"""
158
+ try:
159
+ with socketserver.TCPServer(("", port), ProxyHTTPRequestHandler) as httpd:
160
+ logger.info(f"Запуск прокси-сервера на порту {port}")
161
+ httpd.serve_forever()
162
+ except Exception as e:
163
+ logger.error(f"Ошибка при запуске прокси-сервера: {e}")
164
+
165
  def ensure_directory_permissions(directory_path):
166
  """Обеспечиваем правильные разрешения для директории"""
167
  directory = Path(directory_path)
 
396
  test_thread.daemon = True
397
  test_thread.start()
398
 
399
+ # Запускаем прокси-сервер для перехвата и модификации запросов
400
+ proxy_port = 9090
401
+ proxy_thread = Thread(target=run_proxy_server, args=(proxy_port,))
402
+ proxy_thread.daemon = True
403
+ proxy_thread.start()
404
+
405
  # Запускаем Playground UI в режиме dev на порту 7860 (порт Hugging Face)
406
  logger.info("Запуск Playground UI в режиме разработки на порту 7860...")
407
  os.environ["PORT"] = "7860"
408
+ os.environ["AGENT_SERVER_URL"] = f"http://localhost:{proxy_port}" # Указываем прокси вместо прямого API
409
  os.environ["NEXT_PUBLIC_EDIT_GRAPH_MODE"] = "true" # Включаем расширенный режим редактирования
410
  os.environ["NEXT_PUBLIC_DISABLE_CAMERA"] = "true" # Отключаем запрос на использование камеры
411
 
412
  # Важные переменные для отключения запросов к дизайнеру
413
  os.environ["NEXT_PUBLIC_DEV_MODE"] = "false"
414
+ os.environ["NEXT_PUBLIC_API_BASE_URL"] = f"/api/agents"
415
+ os.environ["NEXT_PUBLIC_DESIGNER_API_URL"] = f"http://localhost:{proxy_port}"
416
 
417
  # Запускаем Playground UI
418
  playground_process = subprocess.Popen(