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,147 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Middleware Factory for creating and managing middleware components.
|
|
3
|
+
|
|
4
|
+
This module provides a factory for creating middleware components with proper
|
|
5
|
+
configuration and dependency management.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Dict, Any, List, Optional, Type
|
|
10
|
+
|
|
11
|
+
from fastapi import FastAPI
|
|
12
|
+
|
|
13
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
14
|
+
from mcp_proxy_adapter.core.security_factory import SecurityFactory
|
|
15
|
+
from .base import BaseMiddleware
|
|
16
|
+
from .unified_security import UnifiedSecurityMiddleware
|
|
17
|
+
from .error_handling import ErrorHandlingMiddleware
|
|
18
|
+
from .logging import LoggingMiddleware
|
|
19
|
+
from .user_info_middleware import UserInfoMiddleware
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class MiddlewareFactory:
|
|
23
|
+
"""
|
|
24
|
+
Factory for creating and managing middleware components.
|
|
25
|
+
|
|
26
|
+
Provides methods to create middleware components with proper configuration
|
|
27
|
+
and dependency management.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, app: FastAPI, config: Dict[str, Any]):
|
|
31
|
+
"""
|
|
32
|
+
Initialize middleware factory.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
app: FastAPI application
|
|
36
|
+
config: Application configuration
|
|
37
|
+
"""
|
|
38
|
+
self.app = app
|
|
39
|
+
self.config = config
|
|
40
|
+
self.middleware_stack: List[BaseMiddleware] = []
|
|
41
|
+
|
|
42
|
+
get_global_logger().info("Middleware factory initialized")
|
|
43
|
+
|
|
44
|
+
def create_security_middleware(self) -> Optional[UnifiedSecurityMiddleware]:
|
|
45
|
+
"""
|
|
46
|
+
Create unified security middleware.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
UnifiedSecurityMiddleware instance or None if creation failed
|
|
50
|
+
"""
|
|
51
|
+
try:
|
|
52
|
+
security_config = self.config.get("security", {})
|
|
53
|
+
|
|
54
|
+
if not security_config.get("enabled", True):
|
|
55
|
+
get_global_logger().info("Security middleware disabled by configuration")
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
middleware = UnifiedSecurityMiddleware(self.app, self.config)
|
|
59
|
+
self.middleware_stack.append(middleware)
|
|
60
|
+
|
|
61
|
+
get_global_logger().info("Unified security middleware created successfully")
|
|
62
|
+
return middleware
|
|
63
|
+
|
|
64
|
+
except Exception as e:
|
|
65
|
+
get_global_logger().error(f"Failed to create unified security middleware: {e}")
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
def create_error_handling_middleware(self) -> Optional[ErrorHandlingMiddleware]:
|
|
69
|
+
"""
|
|
70
|
+
Create error handling middleware.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
ErrorHandlingMiddleware instance or None if creation failed
|
|
74
|
+
"""
|
|
75
|
+
try:
|
|
76
|
+
# Import here to avoid circular imports
|
|
77
|
+
from .error_handling import ErrorHandlingMiddleware
|
|
78
|
+
|
|
79
|
+
middleware = ErrorHandlingMiddleware(self.app)
|
|
80
|
+
self.middleware_stack.append(middleware)
|
|
81
|
+
|
|
82
|
+
get_global_logger().info("Error handling middleware created successfully")
|
|
83
|
+
return middleware
|
|
84
|
+
|
|
85
|
+
except Exception as e:
|
|
86
|
+
get_global_logger().error(f"Failed to create error handling middleware: {e}")
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
def create_logging_middleware(self) -> Optional[LoggingMiddleware]:
|
|
90
|
+
"""
|
|
91
|
+
Create logging middleware.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
LoggingMiddleware instance or None if creation failed
|
|
95
|
+
"""
|
|
96
|
+
try:
|
|
97
|
+
# Import here to avoid circular imports
|
|
98
|
+
from .logging import LoggingMiddleware
|
|
99
|
+
|
|
100
|
+
middleware = LoggingMiddleware(self.app, self.config)
|
|
101
|
+
self.middleware_stack.append(middleware)
|
|
102
|
+
|
|
103
|
+
get_global_logger().info("Logging middleware created successfully")
|
|
104
|
+
return middleware
|
|
105
|
+
|
|
106
|
+
except Exception as e:
|
|
107
|
+
get_global_logger().error(f"Failed to create logging middleware: {e}")
|
|
108
|
+
return None
|
|
109
|
+
|
|
110
|
+
def create_user_info_middleware(self) -> Optional[UserInfoMiddleware]:
|
|
111
|
+
"""
|
|
112
|
+
Create user info middleware.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
UserInfoMiddleware instance or None if creation failed
|
|
116
|
+
"""
|
|
117
|
+
try:
|
|
118
|
+
middleware = UserInfoMiddleware(self.app, self.config)
|
|
119
|
+
self.middleware_stack.append(middleware)
|
|
120
|
+
|
|
121
|
+
get_global_logger().info("User info middleware created successfully")
|
|
122
|
+
return middleware
|
|
123
|
+
|
|
124
|
+
except Exception as e:
|
|
125
|
+
get_global_logger().error(f"Failed to create user info middleware: {e}")
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def get_middleware_by_type(
|
|
130
|
+
self, middleware_type: Type[BaseMiddleware]
|
|
131
|
+
) -> Optional[BaseMiddleware]:
|
|
132
|
+
"""
|
|
133
|
+
Get middleware instance by type.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
middleware_type: Type of middleware to find
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Middleware instance or None if not found
|
|
140
|
+
"""
|
|
141
|
+
for middleware in self.middleware_stack:
|
|
142
|
+
if isinstance(middleware, middleware_type):
|
|
143
|
+
return middleware
|
|
144
|
+
return None
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Middleware for request logging.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import time
|
|
6
|
+
import json
|
|
7
|
+
import uuid
|
|
8
|
+
from typing import Callable, Awaitable, Dict, Any
|
|
9
|
+
|
|
10
|
+
from fastapi import Request, Response
|
|
11
|
+
|
|
12
|
+
from mcp_proxy_adapter.core.logging import get_global_logger, RequestLogger
|
|
13
|
+
from .base import BaseMiddleware
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class LoggingMiddleware(BaseMiddleware):
|
|
17
|
+
"""
|
|
18
|
+
Middleware for logging requests and responses.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, app, config: Dict[str, Any] = None):
|
|
22
|
+
"""
|
|
23
|
+
Initialize logging middleware.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
app: FastAPI application
|
|
27
|
+
config: Application configuration (optional)
|
|
28
|
+
"""
|
|
29
|
+
super().__init__(app)
|
|
30
|
+
self.config = config or {}
|
|
31
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Middleware for performance monitoring.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import time
|
|
6
|
+
import statistics
|
|
7
|
+
from typing import Dict, List, Callable, Awaitable
|
|
8
|
+
|
|
9
|
+
from fastapi import Request, Response
|
|
10
|
+
|
|
11
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
12
|
+
from .base import BaseMiddleware
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PerformanceMiddleware(BaseMiddleware):
|
|
16
|
+
"""
|
|
17
|
+
Middleware for measuring performance.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, app):
|
|
21
|
+
"""
|
|
22
|
+
Initializes performance middleware.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
app: FastAPI application.
|
|
26
|
+
"""
|
|
27
|
+
super().__init__(app)
|
|
28
|
+
self.request_times: Dict[str, List[float]] = {}
|
|
29
|
+
self.log_interval = 100 # Log statistics every 100 requests
|
|
30
|
+
self.request_count = 0
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _log_stats(self) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Logs performance statistics.
|
|
36
|
+
"""
|
|
37
|
+
get_global_logger().info("Performance statistics:")
|
|
38
|
+
|
|
39
|
+
for path, times in self.request_times.items():
|
|
40
|
+
if len(times) > 1:
|
|
41
|
+
avg_time = statistics.mean(times)
|
|
42
|
+
min_time = min(times)
|
|
43
|
+
max_time = max(times)
|
|
44
|
+
# Calculate 95th percentile
|
|
45
|
+
p95_time = sorted(times)[int(len(times) * 0.95)]
|
|
46
|
+
|
|
47
|
+
get_global_logger().info(
|
|
48
|
+
f"Path: {path}, Requests: {len(times)}, "
|
|
49
|
+
f"Avg: {avg_time:.3f}s, Min: {min_time:.3f}s, "
|
|
50
|
+
f"Max: {max_time:.3f}s, p95: {p95_time:.3f}s"
|
|
51
|
+
)
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Protocol middleware module.
|
|
3
|
+
|
|
4
|
+
This module provides middleware for validating protocol access based on configuration.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Callable, Dict, Any, Optional
|
|
8
|
+
from fastapi import Request, Response
|
|
9
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
10
|
+
from starlette.responses import JSONResponse
|
|
11
|
+
|
|
12
|
+
from mcp_proxy_adapter.core.protocol_manager import ProtocolManager
|
|
13
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ProtocolMiddleware(BaseHTTPMiddleware):
|
|
17
|
+
"""
|
|
18
|
+
Middleware for protocol validation.
|
|
19
|
+
|
|
20
|
+
This middleware checks if the incoming request protocol is allowed
|
|
21
|
+
based on the protocol configuration.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, app, app_config: Optional[Dict[str, Any]] = None):
|
|
25
|
+
"""
|
|
26
|
+
Initialize protocol middleware.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
app: FastAPI application
|
|
30
|
+
app_config: Application configuration dictionary (optional)
|
|
31
|
+
"""
|
|
32
|
+
super().__init__(app)
|
|
33
|
+
# Normalize config to dictionary
|
|
34
|
+
normalized_config: Optional[Dict[str, Any]]
|
|
35
|
+
if app_config is None:
|
|
36
|
+
normalized_config = None
|
|
37
|
+
elif hasattr(app_config, "get_all"):
|
|
38
|
+
try:
|
|
39
|
+
normalized_config = app_config.get_all()
|
|
40
|
+
except Exception as e:
|
|
41
|
+
get_global_logger().debug(
|
|
42
|
+
f"ProtocolMiddleware - Error calling get_all(): {e}, type: {type(app_config)}"
|
|
43
|
+
)
|
|
44
|
+
normalized_config = None
|
|
45
|
+
elif hasattr(app_config, "keys"):
|
|
46
|
+
normalized_config = app_config # Already dict-like
|
|
47
|
+
else:
|
|
48
|
+
get_global_logger().debug(
|
|
49
|
+
f"ProtocolMiddleware - app_config is not dict-like, type: {type(app_config)}, value: {repr(app_config)}"
|
|
50
|
+
)
|
|
51
|
+
normalized_config = None
|
|
52
|
+
|
|
53
|
+
get_global_logger().debug(
|
|
54
|
+
f"ProtocolMiddleware - normalized_config type: {type(normalized_config)}"
|
|
55
|
+
)
|
|
56
|
+
if normalized_config:
|
|
57
|
+
get_global_logger().debug(
|
|
58
|
+
f"ProtocolMiddleware - protocols in config: {'protocols' in normalized_config}"
|
|
59
|
+
)
|
|
60
|
+
if "protocols" in normalized_config:
|
|
61
|
+
get_global_logger().debug(
|
|
62
|
+
f"ProtocolMiddleware - protocols type: {type(normalized_config['protocols'])}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
self.app_config = normalized_config
|
|
66
|
+
# Get protocol manager with current configuration
|
|
67
|
+
self.protocol_manager = ProtocolManager(normalized_config)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _get_request_protocol(self, request: Request) -> str:
|
|
72
|
+
"""
|
|
73
|
+
Extract protocol from request.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
request: FastAPI request object
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Protocol name (http, https, mtls)
|
|
80
|
+
"""
|
|
81
|
+
try:
|
|
82
|
+
# Check if request is secure (HTTPS)
|
|
83
|
+
if request.url.scheme:
|
|
84
|
+
scheme = request.url.scheme.lower()
|
|
85
|
+
|
|
86
|
+
# If HTTPS, check if client certificate is provided (MTLS)
|
|
87
|
+
if scheme == "https":
|
|
88
|
+
# Check for client certificate in ASGI scope
|
|
89
|
+
try:
|
|
90
|
+
# Method 1: Check transport info in ASGI scope
|
|
91
|
+
if hasattr(request, "scope") and request.scope:
|
|
92
|
+
transport = request.scope.get("transport")
|
|
93
|
+
if transport and hasattr(transport, "get_extra_info"):
|
|
94
|
+
try:
|
|
95
|
+
ssl_object = transport.get_extra_info("ssl_object")
|
|
96
|
+
if ssl_object:
|
|
97
|
+
try:
|
|
98
|
+
cert = ssl_object.getpeercert()
|
|
99
|
+
if cert:
|
|
100
|
+
get_global_logger().debug(f"mTLS client certificate detected: {cert.get('subject', 'unknown')}")
|
|
101
|
+
return "mtls"
|
|
102
|
+
except Exception:
|
|
103
|
+
pass
|
|
104
|
+
except Exception:
|
|
105
|
+
pass
|
|
106
|
+
except Exception:
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
# Check for client certificate in headers (proxy forwarded)
|
|
110
|
+
try:
|
|
111
|
+
mtls_headers = [
|
|
112
|
+
request.headers.get("ssl-client-cert"),
|
|
113
|
+
request.headers.get("x-client-cert"),
|
|
114
|
+
request.headers.get("x-ssl-cert"),
|
|
115
|
+
request.headers.get("x-forwarded-client-cert")
|
|
116
|
+
]
|
|
117
|
+
if any(mtls_headers):
|
|
118
|
+
get_global_logger().debug("mTLS client certificate detected in headers")
|
|
119
|
+
return "mtls"
|
|
120
|
+
except Exception:
|
|
121
|
+
pass
|
|
122
|
+
|
|
123
|
+
return "https"
|
|
124
|
+
|
|
125
|
+
return scheme
|
|
126
|
+
|
|
127
|
+
# Fallback to checking headers
|
|
128
|
+
x_forwarded_proto = request.headers.get("x-forwarded-proto")
|
|
129
|
+
if x_forwarded_proto:
|
|
130
|
+
return x_forwarded_proto.lower()
|
|
131
|
+
|
|
132
|
+
# Default to HTTP
|
|
133
|
+
return "http"
|
|
134
|
+
|
|
135
|
+
except Exception as e:
|
|
136
|
+
get_global_logger().error(f"Error extracting protocol from request: {e}", exc_info=True)
|
|
137
|
+
# Fallback to HTTP if there's any error
|
|
138
|
+
return "http"
|
|
139
|
+
|
|
140
|
+
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Transport Middleware Module
|
|
3
|
+
|
|
4
|
+
This module provides middleware for transport validation in the MCP Proxy Adapter.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Callable
|
|
8
|
+
from fastapi import Request, Response
|
|
9
|
+
from fastapi.responses import JSONResponse
|
|
10
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
11
|
+
|
|
12
|
+
from mcp_proxy_adapter.core.transport_manager import transport_manager
|
|
13
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TransportMiddleware(BaseHTTPMiddleware):
|
|
17
|
+
"""Middleware for transport validation."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, app, transport_manager_instance=None):
|
|
20
|
+
"""
|
|
21
|
+
Initialize transport middleware.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
app: FastAPI application
|
|
25
|
+
transport_manager_instance: Transport manager instance (optional)
|
|
26
|
+
"""
|
|
27
|
+
super().__init__(app)
|
|
28
|
+
self.transport_manager = transport_manager_instance or transport_manager
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _get_request_transport_type(self, request: Request) -> str:
|
|
32
|
+
"""
|
|
33
|
+
Determine transport type from request.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
request: Incoming request
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Transport type string
|
|
40
|
+
"""
|
|
41
|
+
if request.url.scheme == "https":
|
|
42
|
+
# Check for client certificate for MTLS
|
|
43
|
+
if self._has_client_certificate(request):
|
|
44
|
+
return "mtls"
|
|
45
|
+
return "https"
|
|
46
|
+
return "http"
|
|
47
|
+
|
|
48
|
+
def _has_client_certificate(self, request: Request) -> bool:
|
|
49
|
+
"""
|
|
50
|
+
Check if request has client certificate.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
request: Incoming request
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
True if client certificate is present, False otherwise
|
|
57
|
+
"""
|
|
58
|
+
# Check for client certificate in request headers or SSL context
|
|
59
|
+
# This is a simplified check - in production, you might need more sophisticated detection
|
|
60
|
+
client_cert_header = request.headers.get("ssl-client-cert")
|
|
61
|
+
if client_cert_header:
|
|
62
|
+
return True
|
|
63
|
+
|
|
64
|
+
# Check if request has SSL client certificate context
|
|
65
|
+
if hasattr(request, "client") and request.client:
|
|
66
|
+
# In a real implementation, you would check the SSL context
|
|
67
|
+
# For now, we'll assume HTTPS with client cert is MTLS
|
|
68
|
+
return self.transport_manager.is_mtls()
|
|
69
|
+
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
def _is_transport_allowed(self, transport_type: str) -> bool:
|
|
73
|
+
"""
|
|
74
|
+
Check if transport type is allowed.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
transport_type: Transport type to check
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
True if transport is allowed, False otherwise
|
|
81
|
+
"""
|
|
82
|
+
configured_type = self.transport_manager.get_transport_type()
|
|
83
|
+
if not configured_type:
|
|
84
|
+
get_global_logger().error("Transport not configured")
|
|
85
|
+
return False
|
|
86
|
+
|
|
87
|
+
return transport_type == configured_type.value
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unified Security Middleware - Direct Framework Integration
|
|
3
|
+
|
|
4
|
+
This middleware now directly uses mcp_security_framework components
|
|
5
|
+
instead of custom implementations.
|
|
6
|
+
|
|
7
|
+
Author: Vasiliy Zdanovskiy
|
|
8
|
+
email: vasilyvz@gmail.com
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import time
|
|
12
|
+
import logging
|
|
13
|
+
from typing import Dict, Any, Callable, Awaitable
|
|
14
|
+
from fastapi import Request, Response
|
|
15
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
16
|
+
|
|
17
|
+
# Direct import from framework
|
|
18
|
+
try:
|
|
19
|
+
from mcp_security_framework.middleware import (
|
|
20
|
+
FastAPISecurityMiddleware,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
SECURITY_FRAMEWORK_AVAILABLE = True
|
|
24
|
+
except ImportError as e:
|
|
25
|
+
# NO FALLBACK! mcp_security_framework is REQUIRED
|
|
26
|
+
raise RuntimeError(
|
|
27
|
+
f"CRITICAL: mcp_security_framework is required but not available: {e}. "
|
|
28
|
+
"Install it with: pip install mcp_security_framework>=1.2.8"
|
|
29
|
+
) from e
|
|
30
|
+
|
|
31
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
32
|
+
# from mcp_proxy_adapter.core.security_integration import create_security_integration
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SecurityValidationError(Exception):
|
|
36
|
+
"""Security validation error."""
|
|
37
|
+
|
|
38
|
+
def __init__(self, message: str, error_code: int):
|
|
39
|
+
self.message = message
|
|
40
|
+
self.error_code = error_code
|
|
41
|
+
super().__init__(self.message)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class UnifiedSecurityMiddleware(BaseHTTPMiddleware):
|
|
45
|
+
"""
|
|
46
|
+
Unified security middleware using mcp_security_framework.
|
|
47
|
+
|
|
48
|
+
This middleware now directly uses the security framework's FastAPI middleware
|
|
49
|
+
and components instead of custom implementations.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(self, app, config: Dict[str, Any]):
|
|
53
|
+
"""
|
|
54
|
+
Initialize unified security middleware.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
app: FastAPI application
|
|
58
|
+
config: mcp_proxy_adapter configuration dictionary
|
|
59
|
+
"""
|
|
60
|
+
super().__init__(app)
|
|
61
|
+
self.config = config
|
|
62
|
+
|
|
63
|
+
# Create security integration
|
|
64
|
+
try:
|
|
65
|
+
security_config = config.get("security", {})
|
|
66
|
+
|
|
67
|
+
# Check if security is enabled - use mcp_security_framework if needed
|
|
68
|
+
security_enabled = security_config.get("enabled", False)
|
|
69
|
+
|
|
70
|
+
if security_enabled:
|
|
71
|
+
# self.security_integration = create_security_integration(security_config)
|
|
72
|
+
self.security_integration = None
|
|
73
|
+
# Use framework's FastAPI middleware
|
|
74
|
+
# self.framework_middleware = (
|
|
75
|
+
# self.security_integration.security_manager.create_fastapi_middleware()
|
|
76
|
+
# )
|
|
77
|
+
self.framework_middleware = None
|
|
78
|
+
get_global_logger().info("Security disabled - no middleware")
|
|
79
|
+
# IMPORTANT: Don't replace self.app! This breaks the middleware chain.
|
|
80
|
+
# Instead, store the framework middleware for use in dispatch method.
|
|
81
|
+
get_global_logger().info("Framework middleware will be used in dispatch method")
|
|
82
|
+
else:
|
|
83
|
+
get_global_logger().info("Security disabled, skipping mcp_security_framework integration")
|
|
84
|
+
self.security_integration = None
|
|
85
|
+
self.framework_middleware = None
|
|
86
|
+
except Exception as e:
|
|
87
|
+
get_global_logger().error(f"Security framework integration failed: {e}")
|
|
88
|
+
# Instead of raising error, log warning and continue without security
|
|
89
|
+
get_global_logger().warning(
|
|
90
|
+
"Continuing without security framework - some security features will be disabled"
|
|
91
|
+
)
|
|
92
|
+
self.security_integration = None
|
|
93
|
+
self.framework_middleware = None
|
|
94
|
+
# Keep original app in place when framework middleware is unavailable
|
|
95
|
+
# BaseHTTPMiddleware initialized it via super().__init__(app)
|
|
96
|
+
|
|
97
|
+
get_global_logger().info("Unified security middleware initialized")
|
|
98
|
+
|
|
99
|
+
async def dispatch(
|
|
100
|
+
self, request: Request, call_next: Callable[[Request], Awaitable[Response]]
|
|
101
|
+
) -> Response:
|
|
102
|
+
"""
|
|
103
|
+
Process request using framework middleware.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
request: Request object
|
|
107
|
+
call_next: Next handler
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
Response object
|
|
111
|
+
"""
|
|
112
|
+
try:
|
|
113
|
+
# Simple built-in API key enforcement if configured
|
|
114
|
+
security_cfg = (
|
|
115
|
+
self.config.get("security", {}) if isinstance(self.config, dict) else {}
|
|
116
|
+
)
|
|
117
|
+
# Use new simplified structure
|
|
118
|
+
public_paths = set(["/health", "/docs", "/openapi.json"])
|
|
119
|
+
# JSON-RPC endpoint must not be public when API key is required
|
|
120
|
+
public_paths.discard("/api/jsonrpc")
|
|
121
|
+
path = request.url.path
|
|
122
|
+
methods = set(["api_key"]) # Use token-based authentication
|
|
123
|
+
api_keys: Dict[str, str] = security_cfg.get("tokens", {}) or {}
|
|
124
|
+
|
|
125
|
+
# Enforce only for non-public paths when api_key method configured
|
|
126
|
+
if (
|
|
127
|
+
security_cfg.get("enabled", False)
|
|
128
|
+
and ("api_key" in methods)
|
|
129
|
+
and (path not in public_paths)
|
|
130
|
+
):
|
|
131
|
+
# Accept either X-API-Key or Authorization: Bearer
|
|
132
|
+
token = request.headers.get("X-API-Key")
|
|
133
|
+
if not token:
|
|
134
|
+
authz = request.headers.get("Authorization", "")
|
|
135
|
+
if authz.startswith("Bearer "):
|
|
136
|
+
token = authz[7:]
|
|
137
|
+
if not token or (api_keys and token not in api_keys.values()):
|
|
138
|
+
from fastapi.responses import JSONResponse
|
|
139
|
+
|
|
140
|
+
return JSONResponse(
|
|
141
|
+
status_code=401,
|
|
142
|
+
content={
|
|
143
|
+
"error": {
|
|
144
|
+
"code": 401,
|
|
145
|
+
"message": "Unauthorized: invalid or missing API key",
|
|
146
|
+
"type": "authentication_error",
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Continue with framework middleware or regular flow
|
|
152
|
+
if self.framework_middleware:
|
|
153
|
+
# If framework middleware exists, we need to call it manually
|
|
154
|
+
# This is a workaround since we can't chain ASGI apps in BaseHTTPMiddleware
|
|
155
|
+
get_global_logger().debug(
|
|
156
|
+
"Framework middleware exists, continuing with regular call_next"
|
|
157
|
+
)
|
|
158
|
+
return await call_next(request)
|
|
159
|
+
else:
|
|
160
|
+
# No framework middleware, continue normally
|
|
161
|
+
return await call_next(request)
|
|
162
|
+
|
|
163
|
+
except SecurityValidationError as e:
|
|
164
|
+
# Handle security validation errors
|
|
165
|
+
return await self._handle_security_error(request, e)
|
|
166
|
+
except Exception as e:
|
|
167
|
+
# Handle other errors
|
|
168
|
+
get_global_logger().error(f"Unexpected error in unified security middleware: {e}")
|
|
169
|
+
return await self._handle_general_error(request, e)
|
|
170
|
+
|
|
171
|
+
async def _handle_security_error(
|
|
172
|
+
self, request: Request, error: SecurityValidationError
|
|
173
|
+
) -> Response:
|
|
174
|
+
"""
|
|
175
|
+
Handle security validation errors.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
request: Request object
|
|
179
|
+
error: Security validation error
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
Error response
|
|
183
|
+
"""
|
|
184
|
+
from fastapi.responses import JSONResponse
|
|
185
|
+
|
|
186
|
+
error_response = {
|
|
187
|
+
"error": {
|
|
188
|
+
"code": error.error_code,
|
|
189
|
+
"message": error.message,
|
|
190
|
+
"type": "security_validation_error",
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
get_global_logger().warning(f"Security validation failed: {error.message}")
|
|
195
|
+
|
|
196
|
+
return JSONResponse(status_code=error.error_code, content=error_response)
|
|
197
|
+
|
|
198
|
+
async def _handle_general_error(
|
|
199
|
+
self, request: Request, error: Exception
|
|
200
|
+
) -> Response:
|
|
201
|
+
"""
|
|
202
|
+
Handle general errors.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
request: Request object
|
|
206
|
+
error: General error
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
Error response
|
|
210
|
+
"""
|
|
211
|
+
from fastapi.responses import JSONResponse
|
|
212
|
+
|
|
213
|
+
error_response = {
|
|
214
|
+
"error": {
|
|
215
|
+
"code": 500,
|
|
216
|
+
"message": "Internal server error",
|
|
217
|
+
"type": "general_error",
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
get_global_logger().error(f"General error in security middleware: {error}")
|
|
222
|
+
|
|
223
|
+
return JSONResponse(status_code=500, content=error_response)
|