Askhat777 commited on
Commit
f07061d
·
verified ·
1 Parent(s): 613f4b9

Update proxy_server.py

Browse files
Files changed (1) hide show
  1. proxy_server.py +100 -105
proxy_server.py CHANGED
@@ -1,40 +1,42 @@
1
  """
2
- PROXY SERVER - Публичный сервер
3
- Схема: MT5 PROXY SAFE_BACKEND
4
- PROXY проверяет лицензию на SAFE_BACKEND и кэширует результаты
5
  """
6
  from fastapi import FastAPI, HTTPException, Request
7
  from fastapi.middleware.cors import CORSMiddleware
8
  import httpx
9
  import os
10
  import time
11
- import asyncio
12
  from datetime import datetime
 
13
 
14
- # ==================== КОНФИГУРАЦИЯ ====================
15
  class Config:
16
- SAFE_BACKEND_URL = os.environ.get(
17
- "SAFE_BACKEND_URL",
18
- "https://askhat777-gold-backend-secure.hf.space" # Проверь этот URL!
19
- )
20
- SAFE_API_TOKEN = os.environ.get(
21
- "SAFE_API_TOKEN",
22
- "GOLD_SAFE_2026_u7x9A2B3C4D5E6F7G8H9I0J1K2L3M4N5O6P"
23
- )
24
 
25
- PRICE_CACHE_TTL = 1 # 1 секунда
26
- LEVELS_CACHE_TTL = 60 # 1 минута
27
- LICENSE_CACHE_TTL = 300 # 5 минут
 
 
 
 
28
 
29
  print("\n" + "=" * 70)
30
- print("⚙️ КОНФИГУРАЦИЯ PROXY")
31
  print("=" * 70)
32
- print(f"Safe Backend: {Config.SAFE_BACKEND_URL}")
33
- print(f"API Token: {'✓ УСТАНОВЛЕН' if os.environ.get('SAFE_API_TOKEN') else '✗ НЕ УСТАНОВЛЕН'}")
34
  print("=" * 70 + "\n")
35
 
36
  # ==================== ИНИЦИАЛИЗАЦИЯ ====================
37
- app = FastAPI(title="Gold Proxy", version="1.2")
38
 
39
  app.add_middleware(
40
  CORSMiddleware,
@@ -44,14 +46,14 @@ app.add_middleware(
44
  allow_headers=["*"],
45
  )
46
 
47
- # ==================== КЭШИРОВАНИЕ ====================
48
  class ProxyCache:
49
- """Кэш Proxy с разделением по лицензиям"""
50
 
51
  def __init__(self):
52
  self.cache = {}
53
  self.timestamps = {}
54
- self.license_cache = {} # Кэш для проверки лицензий
55
 
56
  def make_key(self, license_key: str, dte: int) -> str:
57
  return f"{license_key}_{dte}"
@@ -60,7 +62,7 @@ class ProxyCache:
60
  key = self.make_key(license_key, dte)
61
  self.cache[key] = data
62
  self.timestamps[key] = time.time()
63
- print(f"💾 Кэш сохранен: {key}")
64
 
65
  def get(self, license_key: str, dte: int, ttl: int) -> tuple:
66
  key = self.make_key(license_key, dte)
@@ -76,81 +78,79 @@ class ProxyCache:
76
  return None, float('inf')
77
 
78
  return self.cache[key], age
79
-
80
- def cache_license_check(self, license_key: str, is_valid: bool):
81
- """Кэширует результат проверки лицензии"""
82
- self.license_cache[license_key] = {
83
- 'valid': is_valid,
84
- 'timestamp': time.time()
85
- }
86
-
87
- def get_cached_license(self, license_key: str) -> tuple:
88
- """Получает кэшированную проверку лицензии"""
89
- if license_key in self.license_cache:
90
- cached = self.license_cache[license_key]
91
- age = time.time() - cached['timestamp']
92
-
93
- if age < Config.LICENSE_CACHE_TTL:
94
- return cached['valid'], age
95
-
96
- del self.license_cache[license_key]
97
-
98
- return None, float('inf')
99
 
100
  proxy_cache = ProxyCache()
101
 
102
  # ==================== ЗАПРОСЫ К SAFE BACKEND ====================
103
- async def fetch_from_safe_backend(license_key: str, dte: int, client_ip: str) -> dict:
 
 
 
 
 
 
104
  url = f"{Config.SAFE_BACKEND_URL}/api/mt5/data"
105
 
106
  print(f"\n🔄 ЗАПРОС К SAFE BACKEND")
107
- print(f" Полный URL: {url}") # ← Помогает отладить
108
- print(f" Метод: GET")
109
- print(f" Параметры: license_key={license_key}, dte={dte}")
110
 
111
  headers = {
112
  "X-API-Token": Config.SAFE_API_TOKEN,
113
- "User-Agent": "Gold-Proxy/1.2",
114
  "X-Forwarded-For": client_ip,
115
  }
116
 
117
  try:
118
- async with httpx.AsyncClient(
119
- timeout=30.0,
120
- verify=False # ← Если проблема с SSL сертификатом
121
- ) as client:
122
- response = await client.get(url, params={
123
- "license_key": license_key,
124
- "dte": dte
125
- }, headers=headers)
126
-
127
- print(f" Response Status: {response.status_code}")
128
-
129
- if response.status_code == 200:
130
- return response.json()
131
- else:
132
- print(f" ❌ Error: {response.text[:200]}")
133
- raise HTTPException(status_code=response.status_code)
134
-
135
- except httpx.ConnectError as e:
136
- print(f" ❌ Не удалось подключиться: {e}")
137
- raise HTTPException(status_code=503, detail="Safe Backend недоступен")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  # ==================== API ЭНДПОИНТЫ ====================
139
  @app.get("/")
140
  def root():
 
141
  return {
142
- "status": "Gold Proxy",
143
- "version": "1.2",
144
- "safe_backend": Config.SAFE_BACKEND_URL,
145
  "cache_size": len(proxy_cache.cache),
146
- "endpoints": {
147
- "data": "/api/mt5/data?license_key=TEST_KEY_12345&dte=0",
148
- "health": "/health"
149
- }
150
  }
151
 
152
  @app.get("/health")
153
  def health_check():
 
154
  return {
155
  "status": "healthy",
156
  "timestamp": datetime.now().isoformat(),
@@ -166,63 +166,58 @@ async def proxy_mt5_data(
166
  """
167
  Основной прокси эндпоинт для MT5
168
 
169
- 1️⃣ Проверяет кэш
170
  2️⃣ Если кэш устарел → запрашивает Safe Backend
171
- 3️⃣ Safe Backend проверяет лицензию
172
  4️⃣ Возвращает данные клиенту
173
  """
174
- start_time = time.time() # Перенесено внутрь функции
175
 
 
176
  client_ip = request.client.host if request.client else "unknown"
 
177
  print(f"\n📥 ЗАПРОС ОТ MT5")
178
  print(f" IP: {client_ip}")
179
  print(f" License: {license_key[:10]}...")
180
  print(f" DTE: {dte}")
181
-
182
- # 1️⃣ Проверяем кэш данных
183
- # Предполагается, что proxy_cache и Config определены выше в вашем коде
184
- cached_data, cache_age = proxy_cache.get(license_key, dte, Config.LEVELS_CACHE_TTL)
185
-
 
 
 
186
  if cached_data:
187
  elapsed = time.time() - start_time
188
  print(f" ✅ Используется кэш (возраст {cache_age:.1f}сек)")
189
- print(f" 📤 Ответ отправлен за {elapsed:.3f}сек")
190
  return cached_data
191
-
192
  print(f" 🔄 Кэш отсутствует или устарел")
193
-
194
- # 2️⃣ Запрашиваем у Safe Backend
195
- # Предполагается, что функция fetch_from_safe_backend определена и импортирована
196
  try:
197
  data = await fetch_from_safe_backend(license_key, dte, client_ip)
198
  except Exception as e:
199
- print(f" ❌ Ошибка запроса к бэкенду: {e}")
200
- # Можно вернуть ошибку клиенту или пустой объект, в зависимости от логики
201
- raise HTTPException(status_code=500, detail="Safe Backend Error")
202
-
203
  # 3️⃣ Сохраняем в кэш
204
  proxy_cache.set(license_key, dte, data)
205
-
206
  elapsed = time.time() - start_time
207
- print(f" 📤 Ответ отправлен за {elapsed:.3f}сек")
208
-
209
  return data
210
 
211
- # ==================== ЗАПУСК ====================
212
-
213
  @app.on_event("startup")
214
  async def startup():
215
  print("\n" + "=" * 70)
216
- print("🚀 PROXY SERVER ЗАПУЩЕН")
217
  print("=" * 70)
218
  print(f"Время: {datetime.now().isoformat()}")
219
- # Проверьте, что Config.SAFE_BACKEND_URL существует
220
- print(f"Safe Backend: {getattr(Config, 'SAFE_BACKEND_URL', 'Not Set')}")
221
- safe_token = getattr(Config, 'SAFE_API_TOKEN', 'None')
222
- print(f"API Token: {safe_token[:15]}..." if safe_token else "API Token: None")
223
  print("=" * 70 + "\n")
224
 
225
  if __name__ == "__main__":
226
- import uvicorn
227
- # Убедитесь, что порт 7860 свободен (это стандартный порт для HF Spaces)
228
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
  """
2
+ PROXY SERVER - Публичный сервер на HF Spaces
3
+ Получает запросы от MT5, кэширует, пробрасывает в Safe Backend
 
4
  """
5
  from fastapi import FastAPI, HTTPException, Request
6
  from fastapi.middleware.cors import CORSMiddleware
7
  import httpx
8
  import os
9
  import time
 
10
  from datetime import datetime
11
+ from typing import Optional
12
 
13
+ # ==================== КОНФИГУРАЦИЯ ИЗ СЕКРЕТОВ ====================
14
  class Config:
15
+ # Получаем из HF Secrets
16
+ SAFE_BACKEND_URL = os.environ.get("SAFE_BACKEND_URL")
17
+ SAFE_API_TOKEN = os.environ.get("SAFE_API_TOKEN")
18
+
19
+ # Проверяем наличие
20
+ if not SAFE_BACKEND_URL:
21
+ raise ValueError("❌ SAFE_BACKEND_URL не установлен в HF Secrets!")
 
22
 
23
+ if not SAFE_API_TOKEN:
24
+ raise ValueError("❌ SAFE_API_TOKEN не установлен в HF Secrets!")
25
+
26
+ # TTL кэша
27
+ PRICE_CACHE_TTL = 1 # 1 секунда
28
+ LEVELS_CACHE_TTL = 60 # 1 минута
29
+ LICENSE_CACHE_TTL = 300 # 5 минут
30
 
31
  print("\n" + "=" * 70)
32
+ print("⚙️ ИНИЦИАЛИЗАЦИЯ PROXY")
33
  print("=" * 70)
34
+ print(f"Safe Backend URL: {Config.SAFE_BACKEND_URL}")
35
+ print(f" SAFE_API_TOKEN загружен: {Config.SAFE_API_TOKEN[:20]}...")
36
  print("=" * 70 + "\n")
37
 
38
  # ==================== ИНИЦИАЛИЗАЦИЯ ====================
39
+ app = FastAPI(title="Gold Proxy", version="1.3")
40
 
41
  app.add_middleware(
42
  CORSMiddleware,
 
46
  allow_headers=["*"],
47
  )
48
 
49
+ # ==================== КЭШ ПРОКСИ ====================
50
  class ProxyCache:
51
+ """Кэш для Proxy с разделением по лицензиям"""
52
 
53
  def __init__(self):
54
  self.cache = {}
55
  self.timestamps = {}
56
+ self.license_cache = {}
57
 
58
  def make_key(self, license_key: str, dte: int) -> str:
59
  return f"{license_key}_{dte}"
 
62
  key = self.make_key(license_key, dte)
63
  self.cache[key] = data
64
  self.timestamps[key] = time.time()
65
+ print(f"💾 Кэш сохранен: {key[:20]}...")
66
 
67
  def get(self, license_key: str, dte: int, ttl: int) -> tuple:
68
  key = self.make_key(license_key, dte)
 
78
  return None, float('inf')
79
 
80
  return self.cache[key], age
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
  proxy_cache = ProxyCache()
83
 
84
  # ==================== ЗАПРОСЫ К SAFE BACKEND ====================
85
+ async def fetch_from_safe_backend(
86
+ license_key: str,
87
+ dte: int,
88
+ client_ip: str
89
+ ) -> dict:
90
+ """Отправляет запрос в Safe Backend"""
91
+
92
  url = f"{Config.SAFE_BACKEND_URL}/api/mt5/data"
93
 
94
  print(f"\n🔄 ЗАПРОС К SAFE BACKEND")
95
+ print(f" URL: {url}")
96
+ print(f" License: {license_key}")
97
+ print(f" DTE: {dte}")
98
 
99
  headers = {
100
  "X-API-Token": Config.SAFE_API_TOKEN,
101
+ "User-Agent": "Gold-Proxy/1.3",
102
  "X-Forwarded-For": client_ip,
103
  }
104
 
105
  try:
106
+ async with httpx.AsyncClient(timeout=30.0) as client:
107
+ response = await client.get(
108
+ url,
109
+ params={"license_key": license_key, "dte": dte},
110
+ headers=headers
111
+ )
112
+
113
+ print(f" Status: {response.status_code}")
114
+
115
+ if response.status_code == 200:
116
+ data = response.json()
117
+ print(f" ✅ Данные получены: {data['calls_count']} calls, {data['puts_count']} puts")
118
+ return data
119
+
120
+ elif response.status_code in [401, 403]:
121
+ print(f" ❌ Ошибка авторизации (401/403)")
122
+ raise HTTPException(status_code=401, detail="License invalid")
123
+
124
+ else:
125
+ print(f" Ошибка {response.status_code}: {response.text[:100]}")
126
+ raise HTTPException(status_code=response.status_code, detail="Backend error")
127
+
128
+ except httpx.TimeoutException:
129
+ print(f" ❌ Timeout (30сек)")
130
+ raise HTTPException(status_code=504, detail="Backend timeout")
131
+
132
+ except httpx.RequestError as e:
133
+ print(f" ❌ Ошибка подключения: {str(e)}")
134
+ raise HTTPException(status_code=503, detail="Connection error")
135
+
136
+ except Exception as e:
137
+ print(f" ❌ Неизвестная ошибка: {e}")
138
+ raise HTTPException(status_code=500, detail=str(e))
139
+
140
  # ==================== API ЭНДПОИНТЫ ====================
141
  @app.get("/")
142
  def root():
143
+ """Публичный информационный эндпоинт"""
144
  return {
145
+ "name": "Gold Proxy",
146
+ "version": "1.3",
147
+ "status": "online",
148
  "cache_size": len(proxy_cache.cache),
 
 
 
 
149
  }
150
 
151
  @app.get("/health")
152
  def health_check():
153
+ """Healthcheck"""
154
  return {
155
  "status": "healthy",
156
  "timestamp": datetime.now().isoformat(),
 
166
  """
167
  Основной прокси эндпоинт для MT5
168
 
169
+ 1️⃣ Проверяет кэш (1 минута)
170
  2️⃣ Если кэш устарел → запрашивает Safe Backend
171
+ 3️⃣ Safe Backend проверяет лицензию и токен
172
  4️⃣ Возвращает данные клиенту
173
  """
 
174
 
175
+ start_time = time.time()
176
  client_ip = request.client.host if request.client else "unknown"
177
+
178
  print(f"\n📥 ЗАПРОС ОТ MT5")
179
  print(f" IP: {client_ip}")
180
  print(f" License: {license_key[:10]}...")
181
  print(f" DTE: {dte}")
182
+
183
+ # 1️⃣ Проверяем кэш
184
+ cached_data, cache_age = proxy_cache.get(
185
+ license_key,
186
+ dte,
187
+ Config.LEVELS_CACHE_TTL
188
+ )
189
+
190
  if cached_data:
191
  elapsed = time.time() - start_time
192
  print(f" ✅ Используется кэш (возраст {cache_age:.1f}сек)")
193
+ print(f" 📤 Ответ за {elapsed:.3f}сек")
194
  return cached_data
195
+
196
  print(f" 🔄 Кэш отсутствует или устарел")
197
+
198
+ # 2️⃣ Запрашиваем Safe Backend
 
199
  try:
200
  data = await fetch_from_safe_backend(license_key, dte, client_ip)
201
  except Exception as e:
202
+ print(f" ❌ Ошибка: {e}")
203
+ raise
204
+
 
205
  # 3️⃣ Сохраняем в кэш
206
  proxy_cache.set(license_key, dte, data)
207
+
208
  elapsed = time.time() - start_time
209
+ print(f" 📤 Ответ за {elapsed:.3f}сек")
210
+
211
  return data
212
 
 
 
213
  @app.on_event("startup")
214
  async def startup():
215
  print("\n" + "=" * 70)
216
+ print("🚀 PROXY SERVER ГОТОВ К РАБОТЕ")
217
  print("=" * 70)
218
  print(f"Время: {datetime.now().isoformat()}")
219
+ print(f"Safe Backend: {Config.SAFE_BACKEND_URL}")
 
 
 
220
  print("=" * 70 + "\n")
221
 
222
  if __name__ == "__main__":
 
 
223
  uvicorn.run(app, host="0.0.0.0", port=7860)