mcp-proxy-adapter 6.9.17__py3-none-any.whl → 6.9.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_proxy_adapter/api/app.py +52 -52
- mcp_proxy_adapter/api/handlers.py +5 -5
- mcp_proxy_adapter/api/middleware/__init__.py +8 -8
- mcp_proxy_adapter/api/middleware/base.py +14 -14
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +7 -7
- mcp_proxy_adapter/api/middleware/error_handling.py +9 -9
- mcp_proxy_adapter/api/middleware/factory.py +17 -17
- mcp_proxy_adapter/api/middleware/logging.py +6 -6
- mcp_proxy_adapter/api/middleware/performance.py +3 -3
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +19 -19
- mcp_proxy_adapter/api/middleware/transport_middleware.py +3 -3
- mcp_proxy_adapter/api/middleware/unified_security.py +11 -11
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +21 -21
- mcp_proxy_adapter/api/tool_integration.py +3 -2
- mcp_proxy_adapter/api/tools.py +4 -3
- mcp_proxy_adapter/commands/auth_validation_command.py +6 -5
- mcp_proxy_adapter/commands/base.py +10 -10
- mcp_proxy_adapter/commands/builtin_commands.py +6 -6
- mcp_proxy_adapter/commands/catalog_manager.py +74 -74
- mcp_proxy_adapter/commands/cert_monitor_command.py +13 -12
- mcp_proxy_adapter/commands/certificate_management_command.py +20 -19
- mcp_proxy_adapter/commands/command_registry.py +68 -67
- mcp_proxy_adapter/commands/config_command.py +3 -1
- mcp_proxy_adapter/commands/dependency_manager.py +10 -10
- mcp_proxy_adapter/commands/help_command.py +21 -20
- mcp_proxy_adapter/commands/hooks.py +27 -27
- mcp_proxy_adapter/commands/key_management_command.py +19 -18
- mcp_proxy_adapter/commands/plugins_command.py +2 -1
- mcp_proxy_adapter/commands/protocol_management_command.py +6 -6
- mcp_proxy_adapter/commands/proxy_registration_command.py +9 -9
- mcp_proxy_adapter/commands/registration_status_command.py +4 -4
- mcp_proxy_adapter/commands/reload_command.py +5 -5
- mcp_proxy_adapter/commands/role_test_command.py +2 -1
- mcp_proxy_adapter/commands/roles_management_command.py +9 -8
- mcp_proxy_adapter/commands/security_command.py +3 -2
- mcp_proxy_adapter/commands/ssl_setup_command.py +7 -6
- mcp_proxy_adapter/commands/token_management_command.py +12 -11
- mcp_proxy_adapter/commands/transport_management_command.py +2 -2
- mcp_proxy_adapter/config.py +3 -3
- mcp_proxy_adapter/core/__init__.py +1 -1
- mcp_proxy_adapter/core/app_runner.py +3 -3
- mcp_proxy_adapter/core/auth_validator.py +9 -9
- mcp_proxy_adapter/core/certificate_utils.py +27 -27
- mcp_proxy_adapter/core/client_manager.py +13 -13
- mcp_proxy_adapter/core/client_security.py +26 -26
- mcp_proxy_adapter/core/config_converter.py +18 -18
- mcp_proxy_adapter/core/config_validator.py +5 -1
- mcp_proxy_adapter/core/crl_utils.py +22 -22
- mcp_proxy_adapter/core/logging.py +21 -13
- mcp_proxy_adapter/core/mtls_asgi.py +7 -7
- mcp_proxy_adapter/core/mtls_asgi_app.py +9 -9
- mcp_proxy_adapter/core/mtls_proxy.py +9 -9
- mcp_proxy_adapter/core/mtls_server.py +18 -18
- mcp_proxy_adapter/core/protocol_manager.py +29 -29
- mcp_proxy_adapter/core/proxy_registration.py +67 -67
- mcp_proxy_adapter/core/security_adapter.py +18 -18
- mcp_proxy_adapter/core/security_factory.py +16 -16
- mcp_proxy_adapter/core/security_integration.py +6 -6
- mcp_proxy_adapter/core/server_adapter.py +12 -12
- mcp_proxy_adapter/core/server_engine.py +17 -17
- mcp_proxy_adapter/core/signal_handler.py +12 -12
- mcp_proxy_adapter/core/ssl_utils.py +12 -12
- mcp_proxy_adapter/core/transport_manager.py +14 -14
- mcp_proxy_adapter/core/unified_config_adapter.py +6 -6
- mcp_proxy_adapter/core/utils.py +5 -5
- mcp_proxy_adapter/custom_openapi.py +7 -7
- mcp_proxy_adapter/examples/cert_manager_bugfix.py +2 -2
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +6 -5
- mcp_proxy_adapter/examples/full_application/commands/echo_command.py +44 -0
- mcp_proxy_adapter/examples/full_application/commands/help_command.py +66 -0
- mcp_proxy_adapter/examples/full_application/commands/list_command.py +64 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +21 -21
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +6 -6
- mcp_proxy_adapter/examples/full_application/main.py +28 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +38 -38
- mcp_proxy_adapter/examples/test_framework_complete.py +35 -35
- mcp_proxy_adapter/examples/test_mcp_server.py +2 -2
- mcp_proxy_adapter/examples/validate_generator_compatibility.py +386 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +248 -0
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.9.18.dist-info/RECORD +149 -0
- mcp_proxy_adapter-6.9.17.dist-info/RECORD +0 -144
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/top_level.txt +0 -0
@@ -10,7 +10,7 @@ from typing import Dict, List, Optional, Tuple, Union
|
|
10
10
|
from urllib.parse import urlparse
|
11
11
|
|
12
12
|
from mcp_proxy_adapter.config import config
|
13
|
-
from mcp_proxy_adapter.core.logging import
|
13
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
14
14
|
|
15
15
|
|
16
16
|
class ProtocolManager:
|
@@ -37,31 +37,31 @@ class ProtocolManager:
|
|
37
37
|
current_config = (
|
38
38
|
self.app_config if self.app_config is not None else config.get_all()
|
39
39
|
)
|
40
|
-
|
40
|
+
get_global_logger().debug(
|
41
41
|
f"ProtocolManager._load_config - current_config type: {type(current_config)}"
|
42
42
|
)
|
43
43
|
|
44
44
|
if not hasattr(current_config, "get"):
|
45
45
|
# Not a dict-like config, fallback to global
|
46
|
-
|
46
|
+
get_global_logger().debug(
|
47
47
|
f"ProtocolManager._load_config - current_config is not dict-like, falling back to global config"
|
48
48
|
)
|
49
49
|
current_config = config.get_all()
|
50
50
|
|
51
|
-
|
51
|
+
get_global_logger().debug(
|
52
52
|
f"ProtocolManager._load_config - final current_config type: {type(current_config)}"
|
53
53
|
)
|
54
54
|
if hasattr(current_config, "get"):
|
55
|
-
|
55
|
+
get_global_logger().debug(
|
56
56
|
f"ProtocolManager._load_config - current_config keys: {list(current_config.keys()) if hasattr(current_config, 'keys') else 'no keys'}"
|
57
57
|
)
|
58
58
|
|
59
59
|
# Get server protocol configuration (new simplified structure)
|
60
|
-
|
60
|
+
get_global_logger().debug(f"ProtocolManager._load_config - before getting server protocol")
|
61
61
|
try:
|
62
62
|
server_config = current_config.get("server", {})
|
63
63
|
server_protocol = server_config.get("protocol", "http")
|
64
|
-
|
64
|
+
get_global_logger().debug(f"ProtocolManager._load_config - server protocol: {server_protocol}")
|
65
65
|
|
66
66
|
# Set allowed protocols based on server protocol
|
67
67
|
if server_protocol == "http":
|
@@ -73,19 +73,19 @@ class ProtocolManager:
|
|
73
73
|
else:
|
74
74
|
# Fallback to HTTP
|
75
75
|
self.allowed_protocols = ["http"]
|
76
|
-
|
76
|
+
get_global_logger().warning(f"Unknown server protocol '{server_protocol}', defaulting to HTTP")
|
77
77
|
|
78
|
-
|
78
|
+
get_global_logger().debug(f"ProtocolManager._load_config - allowed protocols: {self.allowed_protocols}")
|
79
79
|
|
80
80
|
except Exception as e:
|
81
|
-
|
81
|
+
get_global_logger().debug(f"ProtocolManager._load_config - ERROR getting server protocol: {e}")
|
82
82
|
# Fallback to HTTP
|
83
83
|
self.allowed_protocols = ["http"]
|
84
84
|
|
85
85
|
# Protocol management is always enabled in new structure
|
86
86
|
self.enabled = True
|
87
87
|
|
88
|
-
|
88
|
+
get_global_logger().debug(
|
89
89
|
f"Protocol manager loaded config: enabled={self.enabled}, allowed_protocols={self.allowed_protocols}"
|
90
90
|
)
|
91
91
|
|
@@ -104,16 +104,16 @@ class ProtocolManager:
|
|
104
104
|
ssl_config = security_config.get("ssl", {})
|
105
105
|
|
106
106
|
if ssl_config.get("enabled", False):
|
107
|
-
|
107
|
+
get_global_logger().debug("SSL enabled via security.ssl configuration")
|
108
108
|
return True
|
109
109
|
|
110
110
|
# Fallback to legacy SSL config
|
111
111
|
legacy_ssl_config = current_config.get("ssl", {})
|
112
112
|
if legacy_ssl_config.get("enabled", False):
|
113
|
-
|
113
|
+
get_global_logger().debug("SSL enabled via legacy ssl configuration")
|
114
114
|
return True
|
115
115
|
|
116
|
-
|
116
|
+
get_global_logger().debug("SSL is disabled in configuration")
|
117
117
|
return False
|
118
118
|
|
119
119
|
def update_config(self, new_config: Dict):
|
@@ -125,7 +125,7 @@ class ProtocolManager:
|
|
125
125
|
"""
|
126
126
|
self.app_config = new_config
|
127
127
|
self._load_config()
|
128
|
-
|
128
|
+
get_global_logger().info(
|
129
129
|
f"Protocol manager configuration updated: allowed_protocols={self.allowed_protocols}"
|
130
130
|
)
|
131
131
|
|
@@ -143,18 +143,18 @@ class ProtocolManager:
|
|
143
143
|
Returns:
|
144
144
|
True if protocol is allowed, False otherwise
|
145
145
|
"""
|
146
|
-
|
147
|
-
|
148
|
-
|
146
|
+
get_global_logger().debug(f"🔍 ProtocolManager.is_protocol_allowed - protocol: {protocol}")
|
147
|
+
get_global_logger().debug(f"🔍 ProtocolManager.is_protocol_allowed - enabled: {self.enabled}")
|
148
|
+
get_global_logger().debug(f"🔍 ProtocolManager.is_protocol_allowed - allowed_protocols: {self.allowed_protocols}")
|
149
149
|
|
150
150
|
if not self.enabled:
|
151
|
-
|
151
|
+
get_global_logger().debug("✅ ProtocolManager.is_protocol_allowed - Protocol management is disabled, allowing all protocols")
|
152
152
|
return True
|
153
153
|
|
154
154
|
protocol_lower = protocol.lower()
|
155
155
|
is_allowed = protocol_lower in self.allowed_protocols
|
156
156
|
|
157
|
-
|
157
|
+
get_global_logger().debug(f"🔍 ProtocolManager.is_protocol_allowed - Protocol '{protocol}' allowed: {is_allowed}")
|
158
158
|
return is_allowed
|
159
159
|
|
160
160
|
def get_protocol_port(self, protocol: str) -> Optional[int]:
|
@@ -171,11 +171,11 @@ class ProtocolManager:
|
|
171
171
|
protocol_config = self.protocols_config.get(protocol_lower, {})
|
172
172
|
|
173
173
|
if not protocol_config.get("enabled", False):
|
174
|
-
|
174
|
+
get_global_logger().debug(f"Protocol '{protocol}' is not enabled")
|
175
175
|
return None
|
176
176
|
|
177
177
|
port = protocol_config.get("port")
|
178
|
-
|
178
|
+
get_global_logger().debug(f"Protocol '{protocol}' port: {port}")
|
179
179
|
return port
|
180
180
|
|
181
181
|
def get_allowed_protocols(self) -> List[str]:
|
@@ -257,7 +257,7 @@ class ProtocolManager:
|
|
257
257
|
ssl_config = self._get_ssl_config(current_config)
|
258
258
|
|
259
259
|
if not ssl_config.get("enabled", False):
|
260
|
-
|
260
|
+
get_global_logger().warning(
|
261
261
|
f"SSL required for protocol '{protocol}' but SSL is disabled"
|
262
262
|
)
|
263
263
|
return None
|
@@ -266,7 +266,7 @@ class ProtocolManager:
|
|
266
266
|
key_file = ssl_config.get("key_file")
|
267
267
|
|
268
268
|
if not cert_file or not key_file:
|
269
|
-
|
269
|
+
get_global_logger().warning(
|
270
270
|
f"SSL required for protocol '{protocol}' but certificate files not configured"
|
271
271
|
)
|
272
272
|
return None
|
@@ -285,11 +285,11 @@ class ProtocolManager:
|
|
285
285
|
max_tls_version=ssl_config.get("max_tls_version", "1.3"),
|
286
286
|
)
|
287
287
|
|
288
|
-
|
288
|
+
get_global_logger().info(f"SSL context created for protocol '{protocol}'")
|
289
289
|
return ssl_context
|
290
290
|
|
291
291
|
except Exception as e:
|
292
|
-
|
292
|
+
get_global_logger().error(f"Failed to create SSL context for protocol '{protocol}': {e}")
|
293
293
|
return None
|
294
294
|
|
295
295
|
def _get_ssl_config(self, current_config: Dict) -> Dict:
|
@@ -307,13 +307,13 @@ class ProtocolManager:
|
|
307
307
|
ssl_config = security_config.get("ssl", {})
|
308
308
|
|
309
309
|
if ssl_config.get("enabled", False):
|
310
|
-
|
310
|
+
get_global_logger().debug("Using security.ssl configuration")
|
311
311
|
return ssl_config
|
312
312
|
|
313
313
|
# Fallback to legacy SSL config
|
314
314
|
legacy_ssl_config = current_config.get("ssl", {})
|
315
315
|
if legacy_ssl_config.get("enabled", False):
|
316
|
-
|
316
|
+
get_global_logger().debug("Using legacy ssl configuration")
|
317
317
|
return legacy_ssl_config
|
318
318
|
|
319
319
|
# Return empty config if SSL is disabled
|
@@ -417,6 +417,6 @@ def get_protocol_manager(app_config: Optional[Dict] = None) -> ProtocolManager:
|
|
417
417
|
# Create new instance if none exists or config changed
|
418
418
|
if protocol_manager is None or protocol_manager.app_config != app_config:
|
419
419
|
protocol_manager = ProtocolManager(app_config)
|
420
|
-
|
420
|
+
get_global_logger().info("Protocol manager created with new configuration")
|
421
421
|
|
422
422
|
return protocol_manager
|
@@ -22,7 +22,7 @@ import aiohttp
|
|
22
22
|
import os
|
23
23
|
import glob
|
24
24
|
|
25
|
-
from mcp_proxy_adapter.core.logging import
|
25
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
26
26
|
from mcp_proxy_adapter.core.client_security import create_client_security_manager
|
27
27
|
|
28
28
|
|
@@ -193,7 +193,7 @@ class ProxyRegistrationManager:
|
|
193
193
|
self.server_url: Optional[str] = None
|
194
194
|
self.heartbeat_task: Optional[asyncio.Task] = None
|
195
195
|
|
196
|
-
|
196
|
+
get_global_logger().info(
|
197
197
|
"Proxy registration manager initialized with security framework integration"
|
198
198
|
)
|
199
199
|
|
@@ -214,7 +214,7 @@ class ProxyRegistrationManager:
|
|
214
214
|
server_url: The URL where this server is accessible.
|
215
215
|
"""
|
216
216
|
self.server_url = server_url
|
217
|
-
|
217
|
+
get_global_logger().info(f"Proxy registration server URL set to: {server_url}")
|
218
218
|
|
219
219
|
def _get_auth_headers(self) -> Dict[str, str]:
|
220
220
|
"""
|
@@ -250,21 +250,21 @@ class ProxyRegistrationManager:
|
|
250
250
|
Returns:
|
251
251
|
SSL context or None if SSL not needed
|
252
252
|
"""
|
253
|
-
|
253
|
+
get_global_logger().debug("_create_ssl_context called")
|
254
254
|
|
255
255
|
# Decide SSL strictly by proxy URL scheme: use SSL only for https proxy URLs
|
256
256
|
try:
|
257
257
|
from urllib.parse import urlparse as _urlparse
|
258
258
|
scheme = _urlparse(self.proxy_url).scheme if self.proxy_url else "http"
|
259
259
|
if scheme.lower() != "https":
|
260
|
-
|
260
|
+
get_global_logger().debug("Proxy URL is HTTP, skipping SSL context creation for registration")
|
261
261
|
return None
|
262
262
|
except Exception:
|
263
|
-
|
263
|
+
get_global_logger().debug("Failed to parse proxy_url, assuming HTTP and skipping SSL context")
|
264
264
|
return None
|
265
265
|
|
266
266
|
if not self.client_security:
|
267
|
-
|
267
|
+
get_global_logger().debug("SSL context creation failed: client_security is None")
|
268
268
|
return None
|
269
269
|
|
270
270
|
try:
|
@@ -301,7 +301,7 @@ class ProxyRegistrationManager:
|
|
301
301
|
"in your configuration file."
|
302
302
|
)
|
303
303
|
|
304
|
-
|
304
|
+
get_global_logger().debug(
|
305
305
|
f"SSL context creation: cert_config={cert_config}, ssl_config={ssl_config}"
|
306
306
|
)
|
307
307
|
|
@@ -314,7 +314,7 @@ class ProxyRegistrationManager:
|
|
314
314
|
else:
|
315
315
|
# No CA certificate configured - use system default
|
316
316
|
context = ssl.create_default_context()
|
317
|
-
|
317
|
+
get_global_logger().warning(
|
318
318
|
"No CA certificate configured for proxy registration. "
|
319
319
|
"This may cause SSL verification failures if the proxy uses self-signed certificates. "
|
320
320
|
"Consider configuring 'proxy_registration.ssl.ca_cert' in your configuration file."
|
@@ -327,7 +327,7 @@ class ProxyRegistrationManager:
|
|
327
327
|
|
328
328
|
if cert_file and key_file:
|
329
329
|
context.load_cert_chain(cert_file, key_file)
|
330
|
-
|
330
|
+
get_global_logger().debug(
|
331
331
|
f"Loaded client certificates for mTLS: cert={cert_file}, key={key_file}"
|
332
332
|
)
|
333
333
|
|
@@ -340,42 +340,42 @@ class ProxyRegistrationManager:
|
|
340
340
|
# Load CA certificate if provided
|
341
341
|
if ca_cert_file:
|
342
342
|
context.load_verify_locations(ca_cert_file)
|
343
|
-
|
343
|
+
get_global_logger().debug(f"Loaded CA certificate: {ca_cert_file}")
|
344
344
|
|
345
345
|
# Check if verify_ssl is disabled in ssl_config
|
346
346
|
if verify_ssl == False:
|
347
347
|
context.check_hostname = False
|
348
348
|
context.verify_mode = ssl.CERT_NONE
|
349
|
-
|
349
|
+
get_global_logger().debug("SSL verification disabled (verify_ssl=False)")
|
350
350
|
elif verify_mode == "CERT_NONE":
|
351
351
|
context.check_hostname = False
|
352
352
|
context.verify_mode = ssl.CERT_NONE
|
353
|
-
|
353
|
+
get_global_logger().debug("SSL verification disabled (CERT_NONE)")
|
354
354
|
elif verify_mode == "CERT_REQUIRED":
|
355
355
|
context.check_hostname = True
|
356
356
|
context.verify_mode = ssl.CERT_REQUIRED
|
357
|
-
|
357
|
+
get_global_logger().debug("SSL verification enabled (CERT_REQUIRED)")
|
358
358
|
else:
|
359
359
|
# For test environments, default to CERT_NONE to avoid certificate issues
|
360
360
|
context.check_hostname = False
|
361
361
|
context.verify_mode = ssl.CERT_NONE
|
362
|
-
|
362
|
+
get_global_logger().debug("SSL verification disabled (default for test environment)")
|
363
363
|
else:
|
364
364
|
# No specific ssl_config, default to CERT_NONE for test environments
|
365
365
|
context.check_hostname = False
|
366
366
|
context.verify_mode = ssl.CERT_NONE
|
367
|
-
|
367
|
+
get_global_logger().debug("Using CERT_NONE for test environment (no ssl_config)")
|
368
368
|
|
369
|
-
|
369
|
+
get_global_logger().info("Created custom SSL context for proxy registration")
|
370
370
|
return context
|
371
371
|
else:
|
372
|
-
|
372
|
+
get_global_logger().debug(
|
373
373
|
"SSL context creation skipped: no cert_config or ssl_config"
|
374
374
|
)
|
375
375
|
|
376
376
|
return None
|
377
377
|
except Exception as e:
|
378
|
-
|
378
|
+
get_global_logger().warning(f"Failed to create SSL context: {e}")
|
379
379
|
# Don't fail the entire operation, just return None
|
380
380
|
return None
|
381
381
|
|
@@ -387,11 +387,11 @@ class ProxyRegistrationManager:
|
|
387
387
|
True if registration was successful, False otherwise.
|
388
388
|
"""
|
389
389
|
if not self.is_enabled():
|
390
|
-
|
390
|
+
get_global_logger().info("Proxy registration is disabled in configuration")
|
391
391
|
return False
|
392
392
|
|
393
393
|
if not self.server_url:
|
394
|
-
|
394
|
+
get_global_logger().error("Server URL not set, cannot register with proxy")
|
395
395
|
return False
|
396
396
|
|
397
397
|
# Normalize server_url for docker host if needed
|
@@ -409,11 +409,11 @@ class ProxyRegistrationManager:
|
|
409
409
|
normalized = urlunparse(parsed._replace(netloc=new_netloc))
|
410
410
|
if normalized != self.server_url:
|
411
411
|
self.server_url = normalized
|
412
|
-
|
412
|
+
get_global_logger().info(
|
413
413
|
f"Normalized server_url for docker host: {self.server_url}"
|
414
414
|
)
|
415
415
|
except Exception as _e:
|
416
|
-
|
416
|
+
get_global_logger().debug(f"server_url normalization skipped: {_e}")
|
417
417
|
|
418
418
|
# Prepare registration data with proxy info
|
419
419
|
proxy_info = self.registration_config.get("proxy_info", {})
|
@@ -430,8 +430,8 @@ class ProxyRegistrationManager:
|
|
430
430
|
),
|
431
431
|
}
|
432
432
|
|
433
|
-
|
434
|
-
|
433
|
+
get_global_logger().info(f"Attempting to register server with proxy at {self.proxy_url}")
|
434
|
+
get_global_logger().debug(f"Registration data: {registration_data}")
|
435
435
|
|
436
436
|
# Do not block application startup: single attempt, no sleeps here
|
437
437
|
for attempt in range(1):
|
@@ -447,7 +447,7 @@ class ProxyRegistrationManager:
|
|
447
447
|
self.server_key = result.get("server_key")
|
448
448
|
else:
|
449
449
|
self.server_key = None
|
450
|
-
|
450
|
+
get_global_logger().info(
|
451
451
|
f"✅ Successfully registered with proxy. Server key: {self.server_key}"
|
452
452
|
)
|
453
453
|
|
@@ -461,11 +461,11 @@ class ProxyRegistrationManager:
|
|
461
461
|
else:
|
462
462
|
# Be robust if result is not a dict
|
463
463
|
error_msg = None
|
464
|
-
|
464
|
+
get_global_logger().error(f"DEBUG: result type = {type(result)}, result = {result}")
|
465
465
|
if isinstance(result, dict):
|
466
|
-
|
466
|
+
get_global_logger().error(f"DEBUG: result is dict, getting error field")
|
467
467
|
error_field = result.get("error", {})
|
468
|
-
|
468
|
+
get_global_logger().error(f"DEBUG: error_field type = {type(error_field)}, error_field = {error_field}")
|
469
469
|
if isinstance(error_field, dict):
|
470
470
|
error_msg = error_field.get("message", "Unknown error")
|
471
471
|
elif isinstance(error_field, str):
|
@@ -491,7 +491,7 @@ class ProxyRegistrationManager:
|
|
491
491
|
|
492
492
|
if (error_code in ("DUPLICATE_SERVER_URL", "REGISTRATION_ERROR") or already_registered) and existing_server_key:
|
493
493
|
try:
|
494
|
-
|
494
|
+
get_global_logger().info(f"Attempting auto-unregistration of existing instance: {existing_server_key}")
|
495
495
|
# Build unregistration payload using parsed server_key
|
496
496
|
try:
|
497
497
|
copy_number = int(existing_server_key.split("_")[-1])
|
@@ -501,7 +501,7 @@ class ProxyRegistrationManager:
|
|
501
501
|
# Reuse secure unregistration request directly
|
502
502
|
unreg_success, _unreg_result = await self._make_secure_unregistration_request(unregistration_data)
|
503
503
|
if unreg_success:
|
504
|
-
|
504
|
+
get_global_logger().info("Auto-unregistration succeeded, retrying registration once...")
|
505
505
|
# Retry registration once immediately
|
506
506
|
retry_success, retry_result = await self._make_secure_registration_request(registration_data)
|
507
507
|
if retry_success:
|
@@ -510,29 +510,29 @@ class ProxyRegistrationManager:
|
|
510
510
|
self.server_key = retry_result.get("server_key")
|
511
511
|
else:
|
512
512
|
self.server_key = None
|
513
|
-
|
513
|
+
get_global_logger().info(f"✅ Successfully registered after auto-unregistration. Server key: {self.server_key}")
|
514
514
|
if self.registration_config.get("heartbeat", {}).get("enabled", True):
|
515
515
|
await self._start_heartbeat()
|
516
516
|
return True
|
517
517
|
else:
|
518
|
-
|
518
|
+
get_global_logger().warning(f"Retry registration failed after auto-unregistration: {retry_result}")
|
519
519
|
else:
|
520
|
-
|
520
|
+
get_global_logger().warning(f"Auto-unregistration failed: {_unreg_result}")
|
521
521
|
except Exception as _auto_e:
|
522
|
-
|
522
|
+
get_global_logger().warning(f"Auto-unregistration/registration flow error: {_auto_e}")
|
523
523
|
else:
|
524
524
|
error_msg = str(result)
|
525
|
-
|
525
|
+
get_global_logger().warning(
|
526
526
|
f"❌ Registration attempt {attempt + 1} failed: {error_msg}"
|
527
527
|
)
|
528
528
|
|
529
529
|
except Exception as e:
|
530
|
-
|
530
|
+
get_global_logger().error(
|
531
531
|
f"❌ Registration attempt {attempt + 1} failed with exception: {e}"
|
532
532
|
)
|
533
|
-
|
533
|
+
get_global_logger().error(f"Full traceback: {traceback.format_exc()}")
|
534
534
|
|
535
|
-
|
535
|
+
get_global_logger().error(
|
536
536
|
f"❌ Failed to register with proxy after {self.retry_attempts} attempts"
|
537
537
|
)
|
538
538
|
return False
|
@@ -545,11 +545,11 @@ class ProxyRegistrationManager:
|
|
545
545
|
True if unregistration was successful, False otherwise.
|
546
546
|
"""
|
547
547
|
if not self.is_enabled():
|
548
|
-
|
548
|
+
get_global_logger().info("Proxy registration is disabled, skipping unregistration")
|
549
549
|
return True
|
550
550
|
|
551
551
|
if not self.registered or not self.server_key:
|
552
|
-
|
552
|
+
get_global_logger().info("Server not registered with proxy, skipping unregistration")
|
553
553
|
return True
|
554
554
|
|
555
555
|
# Stop heartbeat
|
@@ -563,8 +563,8 @@ class ProxyRegistrationManager:
|
|
563
563
|
|
564
564
|
unregistration_data = {"server_id": self.server_id, "copy_number": copy_number}
|
565
565
|
|
566
|
-
|
567
|
-
|
566
|
+
get_global_logger().info(f"Attempting to unregister server from proxy at {self.proxy_url}")
|
567
|
+
get_global_logger().debug(f"Unregistration data: {unregistration_data}")
|
568
568
|
|
569
569
|
try:
|
570
570
|
success, result = await self._make_secure_unregistration_request(
|
@@ -574,20 +574,20 @@ class ProxyRegistrationManager:
|
|
574
574
|
if success:
|
575
575
|
unregistered = result.get("unregistered", False)
|
576
576
|
if unregistered:
|
577
|
-
|
577
|
+
get_global_logger().info("✅ Successfully unregistered from proxy")
|
578
578
|
else:
|
579
|
-
|
579
|
+
get_global_logger().warning("⚠️ Server was not found in proxy registry")
|
580
580
|
|
581
581
|
self.registered = False
|
582
582
|
self.server_key = None
|
583
583
|
return True
|
584
584
|
else:
|
585
585
|
error_msg = result.get("error", {}).get("message", "Unknown error")
|
586
|
-
|
586
|
+
get_global_logger().error(f"❌ Failed to unregister from proxy: {error_msg}")
|
587
587
|
return False
|
588
588
|
|
589
589
|
except Exception as e:
|
590
|
-
|
590
|
+
get_global_logger().error(f"❌ Unregistration failed with exception: {e}")
|
591
591
|
return False
|
592
592
|
|
593
593
|
async def _make_secure_registration_request(
|
@@ -626,10 +626,10 @@ class ProxyRegistrationManager:
|
|
626
626
|
) as response:
|
627
627
|
try:
|
628
628
|
result = await response.json()
|
629
|
-
|
629
|
+
get_global_logger().debug(f"Response JSON parsed successfully: {type(result)} - {result}")
|
630
630
|
except Exception as e:
|
631
631
|
text_body = await response.text()
|
632
|
-
|
632
|
+
get_global_logger().debug(f"JSON parsing failed: {e}, text_body: {text_body}")
|
633
633
|
result = {"success": False, "error": {"code": "NON_JSON_RESPONSE", "message": text_body}}
|
634
634
|
|
635
635
|
# Validate response headers if security framework available
|
@@ -648,7 +648,7 @@ class ProxyRegistrationManager:
|
|
648
648
|
|
649
649
|
# Handle duplicate server URL as successful registration
|
650
650
|
if error_code == "DUPLICATE_SERVER_URL":
|
651
|
-
|
651
|
+
get_global_logger().info(
|
652
652
|
f"✅ Server already registered: {error_msg}"
|
653
653
|
)
|
654
654
|
# Extract server_key from details if available
|
@@ -656,18 +656,18 @@ class ProxyRegistrationManager:
|
|
656
656
|
existing_server_key = details.get("existing_server_key")
|
657
657
|
if existing_server_key:
|
658
658
|
result["server_key"] = existing_server_key
|
659
|
-
|
659
|
+
get_global_logger().info(
|
660
660
|
f"✅ Retrieved existing server key: {existing_server_key}"
|
661
661
|
)
|
662
662
|
# Return success=True for duplicate registration
|
663
663
|
return True, result
|
664
664
|
else:
|
665
|
-
|
665
|
+
get_global_logger().warning(
|
666
666
|
f"Registration failed: {error_code} - {error_msg}"
|
667
667
|
)
|
668
668
|
return success, result
|
669
669
|
else:
|
670
|
-
|
670
|
+
get_global_logger().warning(
|
671
671
|
f"Registration failed with HTTP status: {response.status}"
|
672
672
|
)
|
673
673
|
# Ensure result is a dict for consistent error handling
|
@@ -727,12 +727,12 @@ class ProxyRegistrationManager:
|
|
727
727
|
error_info = result.get("error", {})
|
728
728
|
error_msg = error_info.get("message", "Unknown error")
|
729
729
|
error_code = error_info.get("code", "UNKNOWN_ERROR")
|
730
|
-
|
730
|
+
get_global_logger().warning(
|
731
731
|
f"Unregistration failed: {error_code} - {error_msg}"
|
732
732
|
)
|
733
733
|
return success, result
|
734
734
|
else:
|
735
|
-
|
735
|
+
get_global_logger().warning(
|
736
736
|
f"Unregistration failed with HTTP status: {response.status}"
|
737
737
|
)
|
738
738
|
return False, result
|
@@ -746,7 +746,7 @@ class ProxyRegistrationManager:
|
|
746
746
|
return
|
747
747
|
|
748
748
|
self.heartbeat_task = asyncio.create_task(self._heartbeat_loop())
|
749
|
-
|
749
|
+
get_global_logger().info("Heartbeat task started")
|
750
750
|
|
751
751
|
async def _stop_heartbeat(self) -> None:
|
752
752
|
"""Stop heartbeat task."""
|
@@ -756,7 +756,7 @@ class ProxyRegistrationManager:
|
|
756
756
|
await self.heartbeat_task
|
757
757
|
except asyncio.CancelledError:
|
758
758
|
pass
|
759
|
-
|
759
|
+
get_global_logger().info("Heartbeat task stopped")
|
760
760
|
|
761
761
|
async def _heartbeat_loop(self) -> None:
|
762
762
|
"""Heartbeat loop to keep registration alive."""
|
@@ -770,13 +770,13 @@ class ProxyRegistrationManager:
|
|
770
770
|
# Send heartbeat
|
771
771
|
success = await self._send_heartbeat()
|
772
772
|
if not success:
|
773
|
-
|
773
|
+
get_global_logger().warning("Heartbeat failed, attempting to re-register")
|
774
774
|
await self.register_server()
|
775
775
|
|
776
776
|
except asyncio.CancelledError:
|
777
777
|
break
|
778
778
|
except Exception as e:
|
779
|
-
|
779
|
+
get_global_logger().error(f"Heartbeat error: {e}")
|
780
780
|
|
781
781
|
async def heartbeat(self) -> bool:
|
782
782
|
"""
|
@@ -810,15 +810,15 @@ class ProxyRegistrationManager:
|
|
810
810
|
try:
|
811
811
|
async with session.get(url, headers=headers, timeout=timeout) as resp:
|
812
812
|
if resp.status == 200:
|
813
|
-
|
813
|
+
get_global_logger().debug("Heartbeat (GET) succeeded")
|
814
814
|
return True
|
815
815
|
# If method not allowed, fall back to POST
|
816
816
|
if resp.status != 405:
|
817
|
-
|
817
|
+
get_global_logger().warning(
|
818
818
|
f"Heartbeat (GET) failed with status: {resp.status}"
|
819
819
|
)
|
820
820
|
except Exception as ge:
|
821
|
-
|
821
|
+
get_global_logger().debug(f"Heartbeat (GET) error: {ge}")
|
822
822
|
|
823
823
|
# Fallback to POST if GET not supported
|
824
824
|
heartbeat_data = {
|
@@ -832,14 +832,14 @@ class ProxyRegistrationManager:
|
|
832
832
|
url, json=heartbeat_data, headers=post_headers, timeout=timeout
|
833
833
|
) as resp:
|
834
834
|
if resp.status == 200:
|
835
|
-
|
835
|
+
get_global_logger().debug("Heartbeat (POST) succeeded")
|
836
836
|
return True
|
837
|
-
|
837
|
+
get_global_logger().warning(
|
838
838
|
f"Heartbeat (POST) failed with status: {resp.status}"
|
839
839
|
)
|
840
840
|
return False
|
841
841
|
except Exception as e:
|
842
|
-
|
842
|
+
get_global_logger().error(f"Heartbeat error: {e}")
|
843
843
|
return False
|
844
844
|
finally:
|
845
845
|
if connector:
|
@@ -904,7 +904,7 @@ async def register_with_proxy(server_url: str) -> bool:
|
|
904
904
|
True if registration was successful, False otherwise.
|
905
905
|
"""
|
906
906
|
if not proxy_registration_manager:
|
907
|
-
|
907
|
+
get_global_logger().error("Proxy registration manager not initialized")
|
908
908
|
return False
|
909
909
|
|
910
910
|
proxy_registration_manager.set_server_url(server_url)
|
@@ -919,7 +919,7 @@ async def unregister_from_proxy() -> bool:
|
|
919
919
|
True if unregistration was successful, False otherwise.
|
920
920
|
"""
|
921
921
|
if not proxy_registration_manager:
|
922
|
-
|
922
|
+
get_global_logger().error("Proxy registration manager not initialized")
|
923
923
|
return False
|
924
924
|
|
925
925
|
return await proxy_registration_manager.unregister_server()
|