mcp-proxy-adapter 2.0.1__py3-none-any.whl → 6.9.50__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.
Potentially problematic release.
This version of mcp-proxy-adapter might be problematic. Click here for more details.
- mcp_proxy_adapter/__init__.py +47 -0
- mcp_proxy_adapter/__main__.py +13 -0
- mcp_proxy_adapter/api/__init__.py +0 -0
- mcp_proxy_adapter/api/app.py +66 -0
- mcp_proxy_adapter/api/core/__init__.py +18 -0
- mcp_proxy_adapter/api/core/app_factory.py +400 -0
- mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
- mcp_proxy_adapter/api/core/registration_context.py +356 -0
- mcp_proxy_adapter/api/core/registration_manager.py +307 -0
- mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
- mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
- mcp_proxy_adapter/api/handlers.py +181 -0
- mcp_proxy_adapter/api/middleware/__init__.py +21 -0
- mcp_proxy_adapter/api/middleware/base.py +54 -0
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
- mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
- mcp_proxy_adapter/api/middleware/factory.py +147 -0
- mcp_proxy_adapter/api/middleware/logging.py +31 -0
- mcp_proxy_adapter/api/middleware/performance.py +51 -0
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
- mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
- mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
- mcp_proxy_adapter/api/openapi/__init__.py +21 -0
- mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
- mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
- mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
- mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
- mcp_proxy_adapter/api/schemas.py +270 -0
- mcp_proxy_adapter/api/tool_integration.py +131 -0
- mcp_proxy_adapter/api/tools.py +163 -0
- mcp_proxy_adapter/cli/__init__.py +12 -0
- mcp_proxy_adapter/cli/commands/__init__.py +15 -0
- mcp_proxy_adapter/cli/commands/client.py +100 -0
- mcp_proxy_adapter/cli/commands/config_generate.py +105 -0
- mcp_proxy_adapter/cli/commands/config_validate.py +94 -0
- mcp_proxy_adapter/cli/commands/generate.py +259 -0
- mcp_proxy_adapter/cli/commands/server.py +174 -0
- mcp_proxy_adapter/cli/commands/sets.py +132 -0
- mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
- mcp_proxy_adapter/cli/examples/__init__.py +8 -0
- mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
- mcp_proxy_adapter/cli/examples/https_token.py +96 -0
- mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
- mcp_proxy_adapter/cli/main.py +63 -0
- mcp_proxy_adapter/cli/parser.py +338 -0
- mcp_proxy_adapter/cli/validators.py +231 -0
- mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
- mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
- mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
- mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
- mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
- mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
- mcp_proxy_adapter/client/proxy.py +123 -0
- mcp_proxy_adapter/commands/__init__.py +66 -0
- mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
- mcp_proxy_adapter/commands/base.py +389 -0
- mcp_proxy_adapter/commands/builtin_commands.py +30 -0
- mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
- mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
- mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
- mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
- mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
- mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
- mcp_proxy_adapter/commands/catalog_manager.py +97 -0
- mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
- mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
- mcp_proxy_adapter/commands/command_registry.py +298 -0
- mcp_proxy_adapter/commands/config_command.py +102 -0
- mcp_proxy_adapter/commands/dependency_container.py +40 -0
- mcp_proxy_adapter/commands/dependency_manager.py +143 -0
- mcp_proxy_adapter/commands/echo_command.py +48 -0
- mcp_proxy_adapter/commands/health_command.py +142 -0
- mcp_proxy_adapter/commands/help_command.py +175 -0
- mcp_proxy_adapter/commands/hooks.py +172 -0
- mcp_proxy_adapter/commands/key_management_command.py +484 -0
- mcp_proxy_adapter/commands/load_command.py +123 -0
- mcp_proxy_adapter/commands/plugins_command.py +246 -0
- mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
- mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
- mcp_proxy_adapter/commands/queue_commands.py +750 -0
- mcp_proxy_adapter/commands/registration_status_command.py +76 -0
- mcp_proxy_adapter/commands/registry/__init__.py +18 -0
- mcp_proxy_adapter/commands/registry/command_info.py +103 -0
- mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
- mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
- mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
- mcp_proxy_adapter/commands/reload_command.py +136 -0
- mcp_proxy_adapter/commands/result.py +157 -0
- mcp_proxy_adapter/commands/role_test_command.py +99 -0
- mcp_proxy_adapter/commands/roles_management_command.py +502 -0
- mcp_proxy_adapter/commands/security_command.py +472 -0
- mcp_proxy_adapter/commands/settings_command.py +113 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
- mcp_proxy_adapter/commands/token_management_command.py +500 -0
- mcp_proxy_adapter/commands/transport_management_command.py +129 -0
- mcp_proxy_adapter/commands/unload_command.py +92 -0
- mcp_proxy_adapter/config.py +32 -0
- mcp_proxy_adapter/core/__init__.py +8 -0
- mcp_proxy_adapter/core/app_factory.py +560 -0
- mcp_proxy_adapter/core/app_runner.py +318 -0
- mcp_proxy_adapter/core/auth_validator.py +508 -0
- mcp_proxy_adapter/core/certificate/__init__.py +20 -0
- mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
- mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
- mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
- mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
- mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
- mcp_proxy_adapter/core/certificate_utils.py +249 -0
- mcp_proxy_adapter/core/client.py +608 -0
- mcp_proxy_adapter/core/client_manager.py +271 -0
- mcp_proxy_adapter/core/client_security.py +411 -0
- mcp_proxy_adapter/core/config/__init__.py +18 -0
- mcp_proxy_adapter/core/config/config.py +237 -0
- mcp_proxy_adapter/core/config/config_factory.py +22 -0
- mcp_proxy_adapter/core/config/config_loader.py +66 -0
- mcp_proxy_adapter/core/config/feature_manager.py +31 -0
- mcp_proxy_adapter/core/config/simple_config.py +204 -0
- mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
- mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
- mcp_proxy_adapter/core/config_converter.py +252 -0
- mcp_proxy_adapter/core/config_validator.py +211 -0
- mcp_proxy_adapter/core/crl_utils.py +362 -0
- mcp_proxy_adapter/core/errors.py +276 -0
- mcp_proxy_adapter/core/job_manager.py +54 -0
- mcp_proxy_adapter/core/logging.py +250 -0
- mcp_proxy_adapter/core/mtls_asgi.py +140 -0
- mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
- mcp_proxy_adapter/core/mtls_proxy.py +229 -0
- mcp_proxy_adapter/core/mtls_server.py +154 -0
- mcp_proxy_adapter/core/protocol_manager.py +232 -0
- mcp_proxy_adapter/core/proxy/__init__.py +19 -0
- mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
- mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
- mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
- mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
- mcp_proxy_adapter/core/proxy_client.py +184 -0
- mcp_proxy_adapter/core/proxy_registration.py +80 -0
- mcp_proxy_adapter/core/role_utils.py +103 -0
- mcp_proxy_adapter/core/security_adapter.py +343 -0
- mcp_proxy_adapter/core/security_factory.py +96 -0
- mcp_proxy_adapter/core/security_integration.py +342 -0
- mcp_proxy_adapter/core/server_adapter.py +251 -0
- mcp_proxy_adapter/core/server_engine.py +217 -0
- mcp_proxy_adapter/core/settings.py +260 -0
- mcp_proxy_adapter/core/signal_handler.py +107 -0
- mcp_proxy_adapter/core/ssl_utils.py +161 -0
- mcp_proxy_adapter/core/transport_manager.py +153 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
- mcp_proxy_adapter/core/utils.py +101 -0
- mcp_proxy_adapter/core/validation/__init__.py +21 -0
- mcp_proxy_adapter/core/validation/config_validator.py +219 -0
- mcp_proxy_adapter/core/validation/file_validator.py +131 -0
- mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
- mcp_proxy_adapter/core/validation/security_validator.py +140 -0
- mcp_proxy_adapter/core/validation/validation_result.py +27 -0
- mcp_proxy_adapter/custom_openapi.py +58 -0
- mcp_proxy_adapter/examples/__init__.py +16 -0
- mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
- mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
- mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
- mcp_proxy_adapter/examples/check_config.py +413 -0
- mcp_proxy_adapter/examples/client_usage_example.py +164 -0
- mcp_proxy_adapter/examples/commands/__init__.py +5 -0
- mcp_proxy_adapter/examples/config_builder.py +234 -0
- mcp_proxy_adapter/examples/config_cli.py +282 -0
- mcp_proxy_adapter/examples/create_test_configs.py +174 -0
- mcp_proxy_adapter/examples/debug_request_state.py +130 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
- mcp_proxy_adapter/examples/demo_client.py +287 -0
- mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
- mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
- mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
- mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
- mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
- mcp_proxy_adapter/examples/full_application/main.py +311 -0
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
- mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
- mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
- mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
- mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
- mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
- mcp_proxy_adapter/examples/generate_config.py +502 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
- mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
- mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
- mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
- mcp_proxy_adapter/examples/queue_server_example.py +85 -0
- mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
- mcp_proxy_adapter/examples/required_certificates.py +208 -0
- mcp_proxy_adapter/examples/run_example.py +77 -0
- mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
- mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
- mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
- mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
- mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
- mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
- mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
- mcp_proxy_adapter/examples/security_test_client.py +72 -0
- mcp_proxy_adapter/examples/setup/__init__.py +24 -0
- mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
- mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
- mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
- mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
- mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
- mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
- mcp_proxy_adapter/examples/setup_test_environment.py +235 -0
- mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
- mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
- mcp_proxy_adapter/examples/test_config.py +205 -0
- mcp_proxy_adapter/examples/test_config_builder.py +110 -0
- mcp_proxy_adapter/examples/test_examples.py +308 -0
- mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
- mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
- mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
- mcp_proxy_adapter/examples/universal_client.py +674 -0
- mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
- mcp_proxy_adapter/integrations/__init__.py +25 -0
- mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
- mcp_proxy_adapter/main.py +311 -0
- mcp_proxy_adapter/openapi.py +375 -0
- mcp_proxy_adapter/schemas/base_schema.json +114 -0
- mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
- mcp_proxy_adapter/schemas/roles.json +37 -0
- mcp_proxy_adapter/schemas/roles_schema.json +162 -0
- mcp_proxy_adapter/version.py +5 -0
- mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
- mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
- {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
- mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
- mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
- adapters/__init__.py +0 -16
- analyzers/__init__.py +0 -14
- analyzers/docstring_analyzer.py +0 -199
- analyzers/type_analyzer.py +0 -151
- cli/__init__.py +0 -12
- cli/__main__.py +0 -79
- cli/command_runner.py +0 -233
- dispatchers/__init__.py +0 -14
- dispatchers/base_dispatcher.py +0 -85
- dispatchers/json_rpc_dispatcher.py +0 -198
- generators/__init__.py +0 -14
- generators/endpoint_generator.py +0 -172
- generators/openapi_generator.py +0 -254
- generators/rest_api_generator.py +0 -207
- mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
- mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
- mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
- mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
- openapi_schema/__init__.py +0 -38
- openapi_schema/command_registry.py +0 -312
- openapi_schema/rest_schema.py +0 -510
- openapi_schema/rpc_generator.py +0 -307
- openapi_schema/rpc_schema.py +0 -416
- validators/__init__.py +0 -14
- validators/base_validator.py +0 -23
- validators/docstring_validator.py +0 -75
- validators/metadata_validator.py +0 -76
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Proxy Registration Endpoints
|
|
3
|
+
This module provides proxy registration endpoints for testing.
|
|
4
|
+
Author: Vasiliy Zdanovskiy
|
|
5
|
+
email: vasilyvz@gmail.com
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from fastapi import APIRouter, HTTPException
|
|
9
|
+
from pydantic import BaseModel
|
|
10
|
+
from typing import Dict, List, Optional, Any
|
|
11
|
+
import time
|
|
12
|
+
import uuid
|
|
13
|
+
|
|
14
|
+
# In-memory registry for testing
|
|
15
|
+
_registry: Dict[str, Dict] = {}
|
|
16
|
+
router = APIRouter(prefix="/proxy", tags=["proxy"])
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ServerRegistration(BaseModel):
|
|
20
|
+
"""Server registration request model."""
|
|
21
|
+
|
|
22
|
+
server_id: str
|
|
23
|
+
server_url: str
|
|
24
|
+
server_name: str
|
|
25
|
+
description: Optional[str] = None
|
|
26
|
+
version: Optional[str] = "1.0.0"
|
|
27
|
+
capabilities: Optional[List[str]] = None
|
|
28
|
+
endpoints: Optional[Dict[str, str]] = None
|
|
29
|
+
auth_method: Optional[str] = "none"
|
|
30
|
+
security_enabled: Optional[bool] = False
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ServerUnregistration(BaseModel):
|
|
34
|
+
"""Server unregistration request model."""
|
|
35
|
+
|
|
36
|
+
server_key: str # Use server_key directly
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class HeartbeatData(BaseModel):
|
|
40
|
+
"""Heartbeat data model."""
|
|
41
|
+
|
|
42
|
+
server_id: str
|
|
43
|
+
server_key: str
|
|
44
|
+
timestamp: Optional[int] = None
|
|
45
|
+
status: Optional[str] = "healthy"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class RegistrationResponse(BaseModel):
|
|
49
|
+
"""Registration response model."""
|
|
50
|
+
|
|
51
|
+
success: bool
|
|
52
|
+
server_key: str
|
|
53
|
+
message: str
|
|
54
|
+
copy_number: int
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class DiscoveryResponse(BaseModel):
|
|
58
|
+
"""Discovery response model."""
|
|
59
|
+
|
|
60
|
+
success: bool
|
|
61
|
+
servers: List[Dict]
|
|
62
|
+
total: int
|
|
63
|
+
active: int
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@router.post("/register", response_model=RegistrationResponse)
|
|
67
|
+
async def register_server(data: ServerRegistration) -> RegistrationResponse:
|
|
68
|
+
"""Register a server with the proxy."""
|
|
69
|
+
server_key = str(uuid.uuid4())
|
|
70
|
+
copy_number = 1
|
|
71
|
+
if data.server_id in _registry:
|
|
72
|
+
copy_number = len(_registry[data.server_id]) + 1
|
|
73
|
+
|
|
74
|
+
if data.server_id not in _registry:
|
|
75
|
+
_registry[data.server_id] = {}
|
|
76
|
+
|
|
77
|
+
_registry[data.server_id][server_key] = {
|
|
78
|
+
"server_id": data.server_id,
|
|
79
|
+
"server_url": data.server_url,
|
|
80
|
+
"server_name": data.server_name,
|
|
81
|
+
"description": data.description,
|
|
82
|
+
"version": data.version,
|
|
83
|
+
"capabilities": data.capabilities or [],
|
|
84
|
+
"endpoints": data.endpoints or {},
|
|
85
|
+
"auth_method": data.auth_method,
|
|
86
|
+
"security_enabled": data.security_enabled,
|
|
87
|
+
"registered_at": time.time(),
|
|
88
|
+
"last_heartbeat": time.time(),
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return RegistrationResponse(
|
|
92
|
+
success=True,
|
|
93
|
+
server_key=server_key,
|
|
94
|
+
message=f"Server {data.server_name} registered successfully",
|
|
95
|
+
copy_number=copy_number,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@router.post("/unregister")
|
|
100
|
+
async def unregister_server(data: ServerUnregistration) -> Dict[str, Any]:
|
|
101
|
+
"""Unregister a server from the proxy."""
|
|
102
|
+
for server_id, instances in _registry.items():
|
|
103
|
+
if data.server_key in instances:
|
|
104
|
+
del instances[data.server_key]
|
|
105
|
+
if not instances:
|
|
106
|
+
del _registry[server_id]
|
|
107
|
+
return {"success": True, "message": "Server unregistered"}
|
|
108
|
+
raise HTTPException(status_code=404, detail="Server not found")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@router.post("/heartbeat")
|
|
112
|
+
async def heartbeat(data: HeartbeatData) -> Dict[str, Any]:
|
|
113
|
+
"""Update server heartbeat."""
|
|
114
|
+
for server_id, instances in _registry.items():
|
|
115
|
+
if data.server_key in instances:
|
|
116
|
+
instances[data.server_key]["last_heartbeat"] = data.timestamp or time.time()
|
|
117
|
+
instances[data.server_key]["status"] = data.status
|
|
118
|
+
return {"success": True, "message": "Heartbeat updated"}
|
|
119
|
+
raise HTTPException(status_code=404, detail="Server not found")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@router.get("/discover", response_model=DiscoveryResponse)
|
|
123
|
+
async def discover_servers() -> DiscoveryResponse:
|
|
124
|
+
"""Discover all registered servers."""
|
|
125
|
+
servers = []
|
|
126
|
+
for server_id, instances in _registry.items():
|
|
127
|
+
for server_key, server_data in instances.items():
|
|
128
|
+
servers.append({**server_data, "server_key": server_key})
|
|
129
|
+
|
|
130
|
+
active = sum(1 for s in servers if time.time() - s.get("last_heartbeat", 0) < 60)
|
|
131
|
+
return DiscoveryResponse(
|
|
132
|
+
success=True,
|
|
133
|
+
servers=servers,
|
|
134
|
+
total=len(servers),
|
|
135
|
+
active=active,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@router.get("/status")
|
|
140
|
+
async def get_status() -> Dict[str, Any]:
|
|
141
|
+
"""Get proxy status."""
|
|
142
|
+
total_servers = sum(len(instances) for instances in _registry.values())
|
|
143
|
+
active_servers = sum(
|
|
144
|
+
1
|
|
145
|
+
for instances in _registry.values()
|
|
146
|
+
for server_data in instances.values()
|
|
147
|
+
if time.time() - server_data.get("last_heartbeat", 0) < 60
|
|
148
|
+
)
|
|
149
|
+
return {
|
|
150
|
+
"status": "running",
|
|
151
|
+
"total_servers": total_servers,
|
|
152
|
+
"active_servers": active_servers,
|
|
153
|
+
"registered_ids": list(_registry.keys()),
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@router.delete("/clear")
|
|
158
|
+
async def clear_registry() -> Dict[str, Any]:
|
|
159
|
+
"""Clear all registrations (for testing)."""
|
|
160
|
+
_registry.clear()
|
|
161
|
+
return {"success": True, "message": "Registry cleared"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
mTLS Full Application Runner
|
|
4
|
+
Runs the full application example with mTLS configuration.
|
|
5
|
+
|
|
6
|
+
Author: Vasiliy Zdanovskiy
|
|
7
|
+
email: vasilyvz@gmail.com
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
import argparse
|
|
12
|
+
import logging
|
|
13
|
+
import json
|
|
14
|
+
import ssl
|
|
15
|
+
import socket
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
# Add the framework to the path
|
|
19
|
+
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
|
20
|
+
|
|
21
|
+
def validate_mtls_config(config_path: str) -> bool:
|
|
22
|
+
"""Validate mTLS configuration file."""
|
|
23
|
+
try:
|
|
24
|
+
with open(config_path, 'r') as f:
|
|
25
|
+
config = json.load(f)
|
|
26
|
+
|
|
27
|
+
# Check required sections
|
|
28
|
+
required_sections = [
|
|
29
|
+
'uuid', 'server', 'logging', 'commands', 'transport',
|
|
30
|
+
'proxy_registration', 'debug', 'security', 'roles', 'ssl'
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
missing_sections = []
|
|
34
|
+
for section in required_sections:
|
|
35
|
+
if section not in config:
|
|
36
|
+
missing_sections.append(section)
|
|
37
|
+
|
|
38
|
+
if missing_sections:
|
|
39
|
+
print(f"❌ Missing required sections: {missing_sections}")
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
# Check SSL configuration
|
|
43
|
+
ssl_config = config.get('ssl', {})
|
|
44
|
+
if not ssl_config.get('enabled', False):
|
|
45
|
+
print("❌ SSL must be enabled for mTLS")
|
|
46
|
+
return False
|
|
47
|
+
|
|
48
|
+
# Check certificate files
|
|
49
|
+
cert_file = ssl_config.get('cert_file')
|
|
50
|
+
key_file = ssl_config.get('key_file')
|
|
51
|
+
ca_cert_file = ssl_config.get('ca_cert_file')
|
|
52
|
+
|
|
53
|
+
if not cert_file or not key_file or not ca_cert_file:
|
|
54
|
+
print("❌ SSL configuration missing certificate files")
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
# Check if certificate files exist
|
|
58
|
+
cert_path = Path(cert_file)
|
|
59
|
+
key_path = Path(key_file)
|
|
60
|
+
ca_path = Path(ca_cert_file)
|
|
61
|
+
|
|
62
|
+
if not cert_path.exists():
|
|
63
|
+
print(f"❌ Certificate file not found: {cert_file}")
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
if not key_path.exists():
|
|
67
|
+
print(f"❌ Key file not found: {key_file}")
|
|
68
|
+
return False
|
|
69
|
+
|
|
70
|
+
if not ca_path.exists():
|
|
71
|
+
print(f"❌ CA certificate file not found: {ca_cert_file}")
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
print("✅ mTLS Configuration validation passed")
|
|
75
|
+
return True
|
|
76
|
+
|
|
77
|
+
except FileNotFoundError:
|
|
78
|
+
print(f"❌ Configuration file not found: {config_path}")
|
|
79
|
+
return False
|
|
80
|
+
except json.JSONDecodeError as e:
|
|
81
|
+
print(f"❌ Invalid JSON in configuration: {e}")
|
|
82
|
+
return False
|
|
83
|
+
except Exception as e:
|
|
84
|
+
print(f"❌ Configuration validation error: {e}")
|
|
85
|
+
return False
|
|
86
|
+
|
|
87
|
+
def test_mtls_connection(config_path: str):
|
|
88
|
+
"""Test mTLS connection to the server."""
|
|
89
|
+
try:
|
|
90
|
+
with open(config_path, 'r') as f:
|
|
91
|
+
config = json.load(f)
|
|
92
|
+
|
|
93
|
+
server_config = config.get('server', {})
|
|
94
|
+
host = server_config.get('host', '0.0.0.0')
|
|
95
|
+
port = server_config.get('port', 8443)
|
|
96
|
+
|
|
97
|
+
ssl_config = config.get('ssl', {})
|
|
98
|
+
cert_file = ssl_config.get('cert_file')
|
|
99
|
+
key_file = ssl_config.get('key_file')
|
|
100
|
+
ca_cert_file = ssl_config.get('ca_cert_file')
|
|
101
|
+
|
|
102
|
+
print(f"🔐 Testing mTLS connection to {host}:{port}")
|
|
103
|
+
|
|
104
|
+
# Create SSL context
|
|
105
|
+
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
|
|
106
|
+
context.load_cert_chain(cert_file, key_file)
|
|
107
|
+
context.load_verify_locations(ca_cert_file)
|
|
108
|
+
context.verify_mode = ssl.CERT_REQUIRED
|
|
109
|
+
|
|
110
|
+
# Test connection
|
|
111
|
+
with socket.create_connection((host, port), timeout=5) as sock:
|
|
112
|
+
with context.wrap_socket(sock, server_hostname=host) as ssock:
|
|
113
|
+
print(f"✅ mTLS connection successful")
|
|
114
|
+
print(f"🔒 Cipher: {ssock.cipher()}")
|
|
115
|
+
print(f"📜 Protocol: {ssock.version()}")
|
|
116
|
+
return True
|
|
117
|
+
|
|
118
|
+
except Exception as e:
|
|
119
|
+
print(f"❌ mTLS connection failed: {e}")
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
def run_mtls_application(config_path: str):
|
|
123
|
+
"""Run the mTLS application example."""
|
|
124
|
+
print("🚀 Starting mTLS Full Application Example")
|
|
125
|
+
print(f"📁 Configuration: {config_path}")
|
|
126
|
+
|
|
127
|
+
# Validate configuration
|
|
128
|
+
if not validate_mtls_config(config_path):
|
|
129
|
+
print("❌ mTLS Configuration validation failed")
|
|
130
|
+
return False
|
|
131
|
+
|
|
132
|
+
# Load configuration
|
|
133
|
+
try:
|
|
134
|
+
with open(config_path, 'r') as f:
|
|
135
|
+
config = json.load(f)
|
|
136
|
+
|
|
137
|
+
server_config = config.get('server', {})
|
|
138
|
+
host = server_config.get('host', '0.0.0.0')
|
|
139
|
+
port = server_config.get('port', 8443)
|
|
140
|
+
protocol = server_config.get('protocol', 'https')
|
|
141
|
+
|
|
142
|
+
ssl_config = config.get('ssl', {})
|
|
143
|
+
proxy_config = config.get('proxy_registration', {})
|
|
144
|
+
|
|
145
|
+
print(f"🌐 Server: {host}:{port}")
|
|
146
|
+
print(f"🔗 Protocol: {protocol}")
|
|
147
|
+
print(f"🔒 SSL: {'Enabled' if ssl_config.get('enabled', False) else 'Disabled'}")
|
|
148
|
+
print(f"🔐 mTLS: {'Enabled' if ssl_config.get('verify_client', False) else 'Disabled'}")
|
|
149
|
+
print(f"🔒 Security: {'Enabled' if config.get('security', {}).get('enabled', False) else 'Disabled'}")
|
|
150
|
+
print(f"👥 Roles: {'Enabled' if config.get('roles', {}).get('enabled', False) else 'Disabled'}")
|
|
151
|
+
print(f"🌐 Proxy Registration: {'Enabled' if proxy_config.get('enabled', False) else 'Disabled'}")
|
|
152
|
+
|
|
153
|
+
if proxy_config.get('enabled', False):
|
|
154
|
+
proxy_url = proxy_config.get('proxy_url', 'https://localhost:3004')
|
|
155
|
+
server_id = proxy_config.get('server_id', 'unknown')
|
|
156
|
+
print(f"📡 Proxy URL: {proxy_url}")
|
|
157
|
+
print(f"🆔 Server ID: {server_id}")
|
|
158
|
+
|
|
159
|
+
# Simulate application startup
|
|
160
|
+
print("\n🔧 Setting up mTLS application components...")
|
|
161
|
+
print("✅ Configuration loaded and validated")
|
|
162
|
+
print("✅ SSL/TLS certificates loaded")
|
|
163
|
+
print("✅ mTLS context created")
|
|
164
|
+
print("✅ Logging configured")
|
|
165
|
+
print("✅ Command registry initialized")
|
|
166
|
+
print("✅ Transport layer configured with mTLS")
|
|
167
|
+
print("✅ Security layer configured")
|
|
168
|
+
print("✅ Proxy registration configured")
|
|
169
|
+
|
|
170
|
+
if proxy_config.get('enabled', False):
|
|
171
|
+
print("✅ Proxy registration enabled")
|
|
172
|
+
print(f"📡 Will register with proxy at: {proxy_config.get('proxy_url')}")
|
|
173
|
+
print(f"🆔 Server ID: {proxy_config.get('server_id')}")
|
|
174
|
+
|
|
175
|
+
print(f"\n🎉 mTLS Full Application Example started successfully!")
|
|
176
|
+
print(f"📡 Server listening on {host}:{port}")
|
|
177
|
+
print(f"🌐 Access via: {protocol}://{host}:{port}")
|
|
178
|
+
print("\n📋 Available features:")
|
|
179
|
+
print(" - Built-in commands (health, echo, list, help)")
|
|
180
|
+
print(" - Custom commands (custom_echo, dynamic_calculator)")
|
|
181
|
+
print(" - Application hooks")
|
|
182
|
+
print(" - Command hooks")
|
|
183
|
+
print(" - Proxy endpoints")
|
|
184
|
+
print(" - mTLS authentication")
|
|
185
|
+
print(" - Security (if enabled)")
|
|
186
|
+
print(" - Role management (if enabled)")
|
|
187
|
+
|
|
188
|
+
print("\n🔐 mTLS Configuration:")
|
|
189
|
+
print(f" - Certificate: {ssl_config.get('cert_file')}")
|
|
190
|
+
print(f" - Private Key: {ssl_config.get('key_file')}")
|
|
191
|
+
print(f" - CA Certificate: {ssl_config.get('ca_cert_file')}")
|
|
192
|
+
print(f" - Client Verification: {'Required' if ssl_config.get('verify_client', False) else 'Optional'}")
|
|
193
|
+
print(f" - Ciphers: {ssl_config.get('ciphers', 'Default')}")
|
|
194
|
+
print(f" - Protocols: {ssl_config.get('protocols', 'Default')}")
|
|
195
|
+
|
|
196
|
+
print("\n✅ mTLS Application simulation completed successfully")
|
|
197
|
+
print("💡 In a real application, the mTLS server would be running here")
|
|
198
|
+
return True
|
|
199
|
+
|
|
200
|
+
except Exception as e:
|
|
201
|
+
print(f"❌ Application startup error: {e}")
|
|
202
|
+
return False
|
|
203
|
+
|
|
204
|
+
def main():
|
|
205
|
+
"""Main function."""
|
|
206
|
+
parser = argparse.ArgumentParser(
|
|
207
|
+
description="Run mTLS Full Application Example",
|
|
208
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
209
|
+
epilog="""
|
|
210
|
+
Examples:
|
|
211
|
+
python run_mtls.py --config configs/mtls_no_roles_correct.json
|
|
212
|
+
python run_mtls.py --config configs/mtls_with_roles_correct.json
|
|
213
|
+
python run_mtls.py --config configs/mtls_no_roles_correct.json --test-connection
|
|
214
|
+
"""
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
parser.add_argument(
|
|
218
|
+
"--config",
|
|
219
|
+
default="configs/mtls_no_roles_correct.json",
|
|
220
|
+
help="Configuration file path"
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
parser.add_argument(
|
|
224
|
+
"--test-connection",
|
|
225
|
+
action="store_true",
|
|
226
|
+
help="Test mTLS connection"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
args = parser.parse_args()
|
|
230
|
+
|
|
231
|
+
# Check if config file exists
|
|
232
|
+
config_path = Path(args.config)
|
|
233
|
+
if not config_path.exists():
|
|
234
|
+
print(f"❌ Configuration file not found: {config_path}")
|
|
235
|
+
print("💡 Available mTLS configurations:")
|
|
236
|
+
configs_dir = Path("configs")
|
|
237
|
+
if configs_dir.exists():
|
|
238
|
+
for config_file in configs_dir.glob("*mtls*.json"):
|
|
239
|
+
print(f" - {config_file}")
|
|
240
|
+
return 1
|
|
241
|
+
|
|
242
|
+
# Test connection if requested
|
|
243
|
+
if args.test_connection:
|
|
244
|
+
success = test_mtls_connection(str(config_path))
|
|
245
|
+
return 0 if success else 1
|
|
246
|
+
|
|
247
|
+
# Run application
|
|
248
|
+
success = run_mtls_application(str(config_path))
|
|
249
|
+
return 0 if success else 1
|
|
250
|
+
|
|
251
|
+
if __name__ == "__main__":
|
|
252
|
+
sys.exit(main())
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Simple Full Application Runner
|
|
4
|
+
Runs the full application example without complex imports.
|
|
5
|
+
|
|
6
|
+
Author: Vasiliy Zdanovskiy
|
|
7
|
+
email: vasilyvz@gmail.com
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
import argparse
|
|
12
|
+
import logging
|
|
13
|
+
import json
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
# Add the framework to the path
|
|
17
|
+
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
|
18
|
+
|
|
19
|
+
def validate_config(config_path: str) -> bool:
|
|
20
|
+
"""Validate configuration file."""
|
|
21
|
+
try:
|
|
22
|
+
with open(config_path, 'r') as f:
|
|
23
|
+
config = json.load(f)
|
|
24
|
+
|
|
25
|
+
# Check required sections
|
|
26
|
+
required_sections = [
|
|
27
|
+
'uuid', 'server', 'logging', 'commands', 'transport',
|
|
28
|
+
'proxy_registration', 'debug', 'security', 'roles'
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
missing_sections = []
|
|
32
|
+
for section in required_sections:
|
|
33
|
+
if section not in config:
|
|
34
|
+
missing_sections.append(section)
|
|
35
|
+
|
|
36
|
+
if missing_sections:
|
|
37
|
+
print(f"❌ Missing required sections: {missing_sections}")
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
# Check server section
|
|
41
|
+
server = config.get('server', {})
|
|
42
|
+
if 'host' not in server or 'port' not in server:
|
|
43
|
+
print("❌ Server section missing host or port")
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
print("✅ Configuration validation passed")
|
|
47
|
+
return True
|
|
48
|
+
|
|
49
|
+
except FileNotFoundError:
|
|
50
|
+
print(f"❌ Configuration file not found: {config_path}")
|
|
51
|
+
return False
|
|
52
|
+
except json.JSONDecodeError as e:
|
|
53
|
+
print(f"❌ Invalid JSON in configuration: {e}")
|
|
54
|
+
return False
|
|
55
|
+
except Exception as e:
|
|
56
|
+
print(f"❌ Configuration validation error: {e}")
|
|
57
|
+
return False
|
|
58
|
+
|
|
59
|
+
def run_application(config_path: str):
|
|
60
|
+
"""Run the full application example."""
|
|
61
|
+
print("🚀 Starting Full Application Example")
|
|
62
|
+
print(f"📁 Configuration: {config_path}")
|
|
63
|
+
|
|
64
|
+
# Validate configuration
|
|
65
|
+
if not validate_config(config_path):
|
|
66
|
+
print("❌ Configuration validation failed")
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
# Load configuration
|
|
70
|
+
try:
|
|
71
|
+
with open(config_path, 'r') as f:
|
|
72
|
+
config = json.load(f)
|
|
73
|
+
|
|
74
|
+
server_config = config.get('server', {})
|
|
75
|
+
host = server_config.get('host', '0.0.0.0')
|
|
76
|
+
port = server_config.get('port', 8000)
|
|
77
|
+
protocol = server_config.get('protocol', 'http')
|
|
78
|
+
|
|
79
|
+
print(f"🌐 Server: {host}:{port}")
|
|
80
|
+
print(f"🔗 Protocol: {protocol}")
|
|
81
|
+
print(f"🔒 Security: {'Enabled' if config.get('security', {}).get('enabled', False) else 'Disabled'}")
|
|
82
|
+
print(f"👥 Roles: {'Enabled' if config.get('roles', {}).get('enabled', False) else 'Disabled'}")
|
|
83
|
+
|
|
84
|
+
# Simulate application startup
|
|
85
|
+
print("\n🔧 Setting up application components...")
|
|
86
|
+
print("✅ Configuration loaded")
|
|
87
|
+
print("✅ Logging configured")
|
|
88
|
+
print("✅ Command registry initialized")
|
|
89
|
+
print("✅ Transport layer configured")
|
|
90
|
+
print("✅ Security layer configured")
|
|
91
|
+
print("✅ Proxy registration configured")
|
|
92
|
+
|
|
93
|
+
print(f"\n🎉 Full Application Example started successfully!")
|
|
94
|
+
print(f"📡 Server listening on {host}:{port}")
|
|
95
|
+
print(f"🌐 Access via: {protocol}://{host}:{port}")
|
|
96
|
+
print("\n📋 Available features:")
|
|
97
|
+
print(" - Built-in commands (health, echo, list, help)")
|
|
98
|
+
print(" - Custom commands (custom_echo, dynamic_calculator)")
|
|
99
|
+
print(" - Application hooks")
|
|
100
|
+
print(" - Command hooks")
|
|
101
|
+
print(" - Proxy endpoints")
|
|
102
|
+
print(" - Security (if enabled)")
|
|
103
|
+
print(" - Role management (if enabled)")
|
|
104
|
+
|
|
105
|
+
print("\n🛑 Press Ctrl+C to stop the server")
|
|
106
|
+
|
|
107
|
+
# Simulate running server (non-blocking)
|
|
108
|
+
print("✅ Server simulation completed successfully")
|
|
109
|
+
print("💡 In a real application, the server would be running here")
|
|
110
|
+
return True
|
|
111
|
+
|
|
112
|
+
except Exception as e:
|
|
113
|
+
print(f"❌ Application startup error: {e}")
|
|
114
|
+
return False
|
|
115
|
+
|
|
116
|
+
def main():
|
|
117
|
+
"""Main function."""
|
|
118
|
+
parser = argparse.ArgumentParser(
|
|
119
|
+
description="Run Full Application Example",
|
|
120
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
121
|
+
epilog="""
|
|
122
|
+
Examples:
|
|
123
|
+
python run_simple.py --config configs/http_simple_correct.json
|
|
124
|
+
python run_simple.py --config configs/http_auth_correct.json
|
|
125
|
+
"""
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
parser.add_argument(
|
|
129
|
+
"--config",
|
|
130
|
+
default="configs/http_simple_correct.json",
|
|
131
|
+
help="Configuration file path"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
args = parser.parse_args()
|
|
135
|
+
|
|
136
|
+
# Check if config file exists
|
|
137
|
+
config_path = Path(args.config)
|
|
138
|
+
if not config_path.exists():
|
|
139
|
+
print(f"❌ Configuration file not found: {config_path}")
|
|
140
|
+
print("💡 Available configurations:")
|
|
141
|
+
configs_dir = Path("configs")
|
|
142
|
+
if configs_dir.exists():
|
|
143
|
+
for config_file in configs_dir.glob("*.json"):
|
|
144
|
+
print(f" - {config_file}")
|
|
145
|
+
return 1
|
|
146
|
+
|
|
147
|
+
# Run application
|
|
148
|
+
success = run_application(str(config_path))
|
|
149
|
+
return 0 if success else 1
|
|
150
|
+
|
|
151
|
+
if __name__ == "__main__":
|
|
152
|
+
sys.exit(main())
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Minimal server test without lifespan issues.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
# Add the project root to the path
|
|
11
|
+
project_root = Path(__file__).parent.parent.parent.parent
|
|
12
|
+
sys.path.insert(0, str(project_root))
|
|
13
|
+
|
|
14
|
+
from fastapi import FastAPI
|
|
15
|
+
import uvicorn
|
|
16
|
+
|
|
17
|
+
def main():
|
|
18
|
+
"""Test minimal server startup."""
|
|
19
|
+
print("🚀 Testing Minimal Server Startup")
|
|
20
|
+
print("=" * 50)
|
|
21
|
+
|
|
22
|
+
# Create minimal FastAPI app
|
|
23
|
+
app = FastAPI(
|
|
24
|
+
title="Test Server",
|
|
25
|
+
description="Minimal test server",
|
|
26
|
+
version="1.0.0"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Add health endpoint
|
|
30
|
+
@app.get("/health")
|
|
31
|
+
|
|
32
|
+
# Add JSON-RPC endpoint
|
|
33
|
+
@app.post("/api/jsonrpc")
|
|
34
|
+
|
|
35
|
+
print("✅ FastAPI app created successfully")
|
|
36
|
+
|
|
37
|
+
# Start server
|
|
38
|
+
print("🚀 Starting server on http://0.0.0.0:8000")
|
|
39
|
+
print("📡 Test with: curl -X POST http://localhost:8000/api/jsonrpc -H 'Content-Type: application/json' -d '{\"jsonrpc\": \"2.0\", \"method\": \"health\", \"id\": 1}'")
|
|
40
|
+
print("🛑 Press Ctrl+C to stop")
|
|
41
|
+
|
|
42
|
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
43
|
+
|
|
44
|
+
if __name__ == "__main__":
|
|
45
|
+
main()
|