mcp-proxy-adapter 6.3.3__py3-none-any.whl → 6.3.5__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.
Files changed (129) hide show
  1. mcp_proxy_adapter/__init__.py +9 -5
  2. mcp_proxy_adapter/__main__.py +1 -1
  3. mcp_proxy_adapter/api/app.py +227 -176
  4. mcp_proxy_adapter/api/handlers.py +68 -60
  5. mcp_proxy_adapter/api/middleware/__init__.py +7 -5
  6. mcp_proxy_adapter/api/middleware/base.py +19 -16
  7. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
  8. mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
  9. mcp_proxy_adapter/api/middleware/factory.py +50 -52
  10. mcp_proxy_adapter/api/middleware/logging.py +46 -30
  11. mcp_proxy_adapter/api/middleware/performance.py +19 -16
  12. mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
  13. mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
  14. mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
  15. mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
  16. mcp_proxy_adapter/api/schemas.py +69 -43
  17. mcp_proxy_adapter/api/tool_integration.py +83 -63
  18. mcp_proxy_adapter/api/tools.py +60 -50
  19. mcp_proxy_adapter/commands/__init__.py +15 -6
  20. mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
  21. mcp_proxy_adapter/commands/base.py +108 -112
  22. mcp_proxy_adapter/commands/builtin_commands.py +28 -18
  23. mcp_proxy_adapter/commands/catalog_manager.py +394 -265
  24. mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
  25. mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
  26. mcp_proxy_adapter/commands/command_registry.py +275 -226
  27. mcp_proxy_adapter/commands/config_command.py +48 -33
  28. mcp_proxy_adapter/commands/dependency_container.py +22 -23
  29. mcp_proxy_adapter/commands/dependency_manager.py +65 -56
  30. mcp_proxy_adapter/commands/echo_command.py +15 -15
  31. mcp_proxy_adapter/commands/health_command.py +31 -29
  32. mcp_proxy_adapter/commands/help_command.py +97 -61
  33. mcp_proxy_adapter/commands/hooks.py +65 -49
  34. mcp_proxy_adapter/commands/key_management_command.py +148 -147
  35. mcp_proxy_adapter/commands/load_command.py +58 -40
  36. mcp_proxy_adapter/commands/plugins_command.py +80 -54
  37. mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
  38. mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
  39. mcp_proxy_adapter/commands/reload_command.py +43 -37
  40. mcp_proxy_adapter/commands/result.py +26 -33
  41. mcp_proxy_adapter/commands/role_test_command.py +26 -26
  42. mcp_proxy_adapter/commands/roles_management_command.py +176 -173
  43. mcp_proxy_adapter/commands/security_command.py +134 -122
  44. mcp_proxy_adapter/commands/settings_command.py +47 -56
  45. mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
  46. mcp_proxy_adapter/commands/token_management_command.py +129 -158
  47. mcp_proxy_adapter/commands/transport_management_command.py +41 -36
  48. mcp_proxy_adapter/commands/unload_command.py +42 -37
  49. mcp_proxy_adapter/config.py +36 -35
  50. mcp_proxy_adapter/core/__init__.py +19 -21
  51. mcp_proxy_adapter/core/app_factory.py +30 -9
  52. mcp_proxy_adapter/core/app_runner.py +81 -64
  53. mcp_proxy_adapter/core/auth_validator.py +176 -182
  54. mcp_proxy_adapter/core/certificate_utils.py +469 -426
  55. mcp_proxy_adapter/core/client.py +155 -126
  56. mcp_proxy_adapter/core/client_manager.py +60 -54
  57. mcp_proxy_adapter/core/client_security.py +108 -88
  58. mcp_proxy_adapter/core/config_converter.py +176 -143
  59. mcp_proxy_adapter/core/config_validator.py +12 -4
  60. mcp_proxy_adapter/core/crl_utils.py +21 -7
  61. mcp_proxy_adapter/core/errors.py +64 -20
  62. mcp_proxy_adapter/core/logging.py +34 -29
  63. mcp_proxy_adapter/core/mtls_asgi.py +29 -25
  64. mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
  65. mcp_proxy_adapter/core/protocol_manager.py +154 -104
  66. mcp_proxy_adapter/core/proxy_client.py +202 -144
  67. mcp_proxy_adapter/core/proxy_registration.py +12 -2
  68. mcp_proxy_adapter/core/role_utils.py +139 -125
  69. mcp_proxy_adapter/core/security_adapter.py +88 -77
  70. mcp_proxy_adapter/core/security_factory.py +50 -44
  71. mcp_proxy_adapter/core/security_integration.py +72 -24
  72. mcp_proxy_adapter/core/server_adapter.py +68 -64
  73. mcp_proxy_adapter/core/server_engine.py +71 -53
  74. mcp_proxy_adapter/core/settings.py +68 -58
  75. mcp_proxy_adapter/core/ssl_utils.py +69 -56
  76. mcp_proxy_adapter/core/transport_manager.py +72 -60
  77. mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
  78. mcp_proxy_adapter/core/utils.py +4 -2
  79. mcp_proxy_adapter/custom_openapi.py +107 -99
  80. mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
  81. mcp_proxy_adapter/examples/commands/__init__.py +1 -1
  82. mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
  83. mcp_proxy_adapter/examples/debug_request_state.py +38 -19
  84. mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
  85. mcp_proxy_adapter/examples/demo_client.py +48 -36
  86. mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
  87. mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
  88. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
  89. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  90. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
  91. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  92. mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
  93. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
  94. mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
  95. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
  96. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  97. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
  98. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  99. mcp_proxy_adapter/examples/full_application/main.py +27 -2
  100. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
  101. mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
  102. mcp_proxy_adapter/examples/generate_certificates.py +31 -16
  103. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
  104. mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
  105. mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
  106. mcp_proxy_adapter/examples/run_example.py +23 -5
  107. mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
  108. mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
  109. mcp_proxy_adapter/examples/run_security_tests.py +103 -41
  110. mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
  111. mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
  112. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
  113. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
  114. mcp_proxy_adapter/examples/security_test_client.py +196 -127
  115. mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
  116. mcp_proxy_adapter/examples/test_config.py +19 -4
  117. mcp_proxy_adapter/examples/test_config_generator.py +23 -7
  118. mcp_proxy_adapter/examples/test_examples.py +84 -56
  119. mcp_proxy_adapter/examples/universal_client.py +119 -62
  120. mcp_proxy_adapter/openapi.py +108 -115
  121. mcp_proxy_adapter/utils/config_generator.py +429 -274
  122. mcp_proxy_adapter/version.py +1 -2
  123. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
  124. mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
  125. mcp_proxy_adapter-6.3.3.dist-info/RECORD +0 -143
  126. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
  127. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
  128. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
  129. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -11,15 +11,16 @@ from fastapi import Request, Response
11
11
  from mcp_proxy_adapter.core.logging import logger
12
12
  from .base import BaseMiddleware
13
13
 
14
+
14
15
  class PerformanceMiddleware(BaseMiddleware):
15
16
  """
16
17
  Middleware for measuring performance.
17
18
  """
18
-
19
+
19
20
  def __init__(self, app):
20
21
  """
21
22
  Initializes performance middleware.
22
-
23
+
23
24
  Args:
24
25
  app: FastAPI application.
25
26
  """
@@ -27,47 +28,49 @@ class PerformanceMiddleware(BaseMiddleware):
27
28
  self.request_times: Dict[str, List[float]] = {}
28
29
  self.log_interval = 100 # Log statistics every 100 requests
29
30
  self.request_count = 0
30
-
31
- async def dispatch(self, request: Request, call_next: Callable[[Request], Awaitable[Response]]) -> Response:
31
+
32
+ async def dispatch(
33
+ self, request: Request, call_next: Callable[[Request], Awaitable[Response]]
34
+ ) -> Response:
32
35
  """
33
36
  Processes request and measures performance.
34
-
37
+
35
38
  Args:
36
39
  request: Request.
37
40
  call_next: Next handler.
38
-
41
+
39
42
  Returns:
40
43
  Response.
41
44
  """
42
45
  # Measure processing time
43
46
  start_time = time.time()
44
-
47
+
45
48
  # Call the next middleware or main handler
46
49
  response = await call_next(request)
47
-
50
+
48
51
  # Calculate processing time
49
52
  process_time = time.time() - start_time
50
-
53
+
51
54
  # Save time in statistics
52
55
  path = request.url.path
53
56
  if path not in self.request_times:
54
57
  self.request_times[path] = []
55
-
58
+
56
59
  self.request_times[path].append(process_time)
57
-
60
+
58
61
  # Logging statistics
59
62
  self.request_count += 1
60
63
  if self.request_count % self.log_interval == 0:
61
64
  self._log_stats()
62
-
65
+
63
66
  return response
64
-
67
+
65
68
  def _log_stats(self) -> None:
66
69
  """
67
70
  Logs performance statistics.
68
71
  """
69
72
  logger.info("Performance statistics:")
70
-
73
+
71
74
  for path, times in self.request_times.items():
72
75
  if len(times) > 1:
73
76
  avg_time = statistics.mean(times)
@@ -75,9 +78,9 @@ class PerformanceMiddleware(BaseMiddleware):
75
78
  max_time = max(times)
76
79
  # Calculate 95th percentile
77
80
  p95_time = sorted(times)[int(len(times) * 0.95)]
78
-
81
+
79
82
  logger.info(
80
83
  f"Path: {path}, Requests: {len(times)}, "
81
84
  f"Avg: {avg_time:.3f}s, Min: {min_time:.3f}s, "
82
85
  f"Max: {max_time:.3f}s, p95: {p95_time:.3f}s"
83
- )
86
+ )
@@ -16,11 +16,11 @@ from mcp_proxy_adapter.core.logging import logger
16
16
  class ProtocolMiddleware(BaseHTTPMiddleware):
17
17
  """
18
18
  Middleware for protocol validation.
19
-
19
+
20
20
  This middleware checks if the incoming request protocol is allowed
21
21
  based on the protocol configuration.
22
22
  """
23
-
23
+
24
24
  def __init__(self, app, app_config: Optional[Dict[str, Any]] = None):
25
25
  """
26
26
  Initialize protocol middleware.
@@ -34,48 +34,58 @@ class ProtocolMiddleware(BaseHTTPMiddleware):
34
34
  normalized_config: Optional[Dict[str, Any]]
35
35
  if app_config is None:
36
36
  normalized_config = None
37
- elif hasattr(app_config, 'get_all'):
37
+ elif hasattr(app_config, "get_all"):
38
38
  try:
39
39
  normalized_config = app_config.get_all()
40
40
  except Exception as e:
41
- logger.debug(f"ProtocolMiddleware - Error calling get_all(): {e}, type: {type(app_config)}")
41
+ logger.debug(
42
+ f"ProtocolMiddleware - Error calling get_all(): {e}, type: {type(app_config)}"
43
+ )
42
44
  normalized_config = None
43
- elif hasattr(app_config, 'keys'):
45
+ elif hasattr(app_config, "keys"):
44
46
  normalized_config = app_config # Already dict-like
45
47
  else:
46
- logger.debug(f"ProtocolMiddleware - app_config is not dict-like, type: {type(app_config)}, value: {repr(app_config)}")
48
+ logger.debug(
49
+ f"ProtocolMiddleware - app_config is not dict-like, type: {type(app_config)}, value: {repr(app_config)}"
50
+ )
47
51
  normalized_config = None
48
52
 
49
- logger.debug(f"ProtocolMiddleware - normalized_config type: {type(normalized_config)}")
53
+ logger.debug(
54
+ f"ProtocolMiddleware - normalized_config type: {type(normalized_config)}"
55
+ )
50
56
  if normalized_config:
51
- logger.debug(f"ProtocolMiddleware - protocols in config: {'protocols' in normalized_config}")
52
- if 'protocols' in normalized_config:
53
- logger.debug(f"ProtocolMiddleware - protocols type: {type(normalized_config['protocols'])}")
57
+ logger.debug(
58
+ f"ProtocolMiddleware - protocols in config: {'protocols' in normalized_config}"
59
+ )
60
+ if "protocols" in normalized_config:
61
+ logger.debug(
62
+ f"ProtocolMiddleware - protocols type: {type(normalized_config['protocols'])}"
63
+ )
54
64
 
55
65
  self.app_config = normalized_config
56
66
  # Get protocol manager with current configuration
57
67
  self.protocol_manager = get_protocol_manager(normalized_config)
58
-
68
+
59
69
  def update_config(self, new_config: Dict[str, Any]):
60
70
  """
61
71
  Update configuration and reload protocol manager.
62
-
72
+
63
73
  Args:
64
74
  new_config: New configuration dictionary
65
75
  """
66
76
  # Normalize new config
67
- if hasattr(new_config, 'get_all'):
77
+ if hasattr(new_config, "get_all"):
68
78
  try:
69
79
  self.app_config = new_config.get_all()
70
80
  except Exception:
71
81
  self.app_config = None
72
- elif hasattr(new_config, 'keys'):
82
+ elif hasattr(new_config, "keys"):
73
83
  self.app_config = new_config
74
84
  else:
75
85
  self.app_config = None
76
86
  self.protocol_manager = get_protocol_manager(self.app_config)
77
87
  logger.info("Protocol middleware configuration updated")
78
-
88
+
79
89
  async def dispatch(self, request: Request, call_next: Callable) -> Response:
80
90
  """
81
91
  Process request through protocol middleware.
@@ -87,76 +97,79 @@ class ProtocolMiddleware(BaseHTTPMiddleware):
87
97
  Returns:
88
98
  Response object
89
99
  """
90
- logger.debug(f"ProtocolMiddleware.dispatch called for {request.method} {request.url.path}")
100
+ logger.debug(
101
+ f"ProtocolMiddleware.dispatch called for {request.method} {request.url.path}"
102
+ )
91
103
  try:
92
104
  # Get protocol from request
93
105
  protocol = self._get_request_protocol(request)
94
-
106
+
95
107
  # Check if protocol is allowed
96
108
  if not self.protocol_manager.is_protocol_allowed(protocol):
97
- logger.warning(f"Protocol '{protocol}' not allowed for request to {request.url.path}")
109
+ logger.warning(
110
+ f"Protocol '{protocol}' not allowed for request to {request.url.path}"
111
+ )
98
112
  return JSONResponse(
99
113
  status_code=403,
100
114
  content={
101
115
  "error": "Protocol not allowed",
102
116
  "message": f"Protocol '{protocol}' is not allowed. Allowed protocols: {self.protocol_manager.get_allowed_protocols()}",
103
- "allowed_protocols": self.protocol_manager.get_allowed_protocols()
104
- }
117
+ "allowed_protocols": self.protocol_manager.get_allowed_protocols(),
118
+ },
105
119
  )
106
-
120
+
107
121
  # Continue processing
108
122
  response = await call_next(request)
109
123
  return response
110
-
124
+
111
125
  except Exception as e:
112
126
  logger.error(f"Protocol middleware error: {e}")
113
127
  return JSONResponse(
114
128
  status_code=500,
115
- content={
116
- "error": "Protocol validation error",
117
- "message": str(e)
118
- }
129
+ content={"error": "Protocol validation error", "message": str(e)},
119
130
  )
120
-
131
+
121
132
  def _get_request_protocol(self, request: Request) -> str:
122
133
  """
123
134
  Extract protocol from request.
124
-
135
+
125
136
  Args:
126
137
  request: FastAPI request object
127
-
138
+
128
139
  Returns:
129
140
  Protocol name (http, https, mtls)
130
141
  """
131
142
  # Check if request is secure (HTTPS)
132
143
  if request.url.scheme:
133
144
  scheme = request.url.scheme.lower()
134
-
145
+
135
146
  # If HTTPS, check if client certificate is provided (MTLS)
136
147
  if scheme == "https":
137
148
  # Check for client certificate in headers or SSL context
138
- if hasattr(request, 'scope') and 'ssl' in request.scope:
139
- ssl_context = request.scope.get('ssl')
140
- if ssl_context and hasattr(ssl_context, 'getpeercert'):
149
+ if hasattr(request, "scope") and "ssl" in request.scope:
150
+ ssl_context = request.scope.get("ssl")
151
+ if ssl_context and hasattr(ssl_context, "getpeercert"):
141
152
  try:
142
153
  cert = ssl_context.getpeercert()
143
154
  if cert:
144
155
  return "mtls"
145
156
  except:
146
157
  pass
147
-
158
+
148
159
  # Check for client certificate in headers
149
- if request.headers.get("ssl-client-cert") or request.headers.get("x-client-cert"):
160
+ if request.headers.get("ssl-client-cert") or request.headers.get(
161
+ "x-client-cert"
162
+ ):
150
163
  return "mtls"
151
-
164
+
152
165
  return "https"
153
-
166
+
154
167
  return scheme
155
-
168
+
156
169
  # Fallback to checking headers
157
170
  if request.headers.get("x-forwarded-proto"):
158
171
  return request.headers.get("x-forwarded-proto").lower()
159
-
172
+
160
173
  # Default to HTTP
161
174
  return "http"
162
175
 
@@ -174,28 +187,45 @@ def setup_protocol_middleware(app, app_config: Optional[Dict[str, Any]] = None):
174
187
  # Check if protocol management is enabled
175
188
  if app_config is None:
176
189
  from mcp_proxy_adapter.config import config
177
- app_config = config.get_all()
178
- logger.debug(f"setup_protocol_middleware - loaded from global config, type: {type(app_config)}")
179
-
180
- logger.debug(f"setup_protocol_middleware - final app_config type: {type(app_config)}")
181
190
 
182
- if hasattr(app_config, 'get'):
183
- logger.debug(f"setup_protocol_middleware - app_config keys: {list(app_config.keys()) if hasattr(app_config, 'keys') else 'no keys'}")
191
+ app_config = config.get_all()
192
+ logger.debug(
193
+ f"setup_protocol_middleware - loaded from global config, type: {type(app_config)}"
194
+ )
195
+
196
+ logger.debug(
197
+ f"setup_protocol_middleware - final app_config type: {type(app_config)}"
198
+ )
199
+
200
+ if hasattr(app_config, "get"):
201
+ logger.debug(
202
+ f"setup_protocol_middleware - app_config keys: {list(app_config.keys()) if hasattr(app_config, 'keys') else 'no keys'}"
203
+ )
184
204
  protocols_config = app_config.get("protocols", {})
185
- logger.debug(f"setup_protocol_middleware - protocols_config type: {type(protocols_config)}")
186
- enabled = protocols_config.get("enabled", True) if hasattr(protocols_config, 'get') else True
205
+ logger.debug(
206
+ f"setup_protocol_middleware - protocols_config type: {type(protocols_config)}"
207
+ )
208
+ enabled = (
209
+ protocols_config.get("enabled", True)
210
+ if hasattr(protocols_config, "get")
211
+ else True
212
+ )
187
213
  else:
188
- logger.debug(f"setup_protocol_middleware - app_config is not dict-like: {repr(app_config)}")
214
+ logger.debug(
215
+ f"setup_protocol_middleware - app_config is not dict-like: {repr(app_config)}"
216
+ )
189
217
  enabled = True
190
218
 
191
219
  logger.debug(f"setup_protocol_middleware - protocol management enabled: {enabled}")
192
220
 
193
221
  if enabled:
194
222
  # Create protocol middleware with current configuration
195
- logger.debug(f"setup_protocol_middleware - creating ProtocolMiddleware with config type: {type(app_config)}")
223
+ logger.debug(
224
+ f"setup_protocol_middleware - creating ProtocolMiddleware with config type: {type(app_config)}"
225
+ )
196
226
  middleware = ProtocolMiddleware(app, app_config)
197
227
  logger.debug(f"setup_protocol_middleware - adding middleware to app")
198
228
  app.add_middleware(ProtocolMiddleware, app_config=app_config)
199
229
  logger.info("Protocol middleware added to application")
200
230
  else:
201
- logger.info("Protocol management is disabled, skipping protocol middleware")
231
+ logger.info("Protocol management is disabled, skipping protocol middleware")
@@ -15,36 +15,38 @@ from mcp_proxy_adapter.core.logging import logger
15
15
 
16
16
  class TransportMiddleware(BaseHTTPMiddleware):
17
17
  """Middleware for transport validation."""
18
-
18
+
19
19
  def __init__(self, app, transport_manager_instance=None):
20
20
  """
21
21
  Initialize transport middleware.
22
-
22
+
23
23
  Args:
24
24
  app: FastAPI application
25
25
  transport_manager_instance: Transport manager instance (optional)
26
26
  """
27
27
  super().__init__(app)
28
28
  self.transport_manager = transport_manager_instance or transport_manager
29
-
29
+
30
30
  async def dispatch(self, request: Request, call_next: Callable) -> Response:
31
31
  """
32
32
  Process request through transport middleware.
33
-
33
+
34
34
  Args:
35
35
  request: Incoming request
36
36
  call_next: Next middleware/endpoint
37
-
37
+
38
38
  Returns:
39
39
  Response from next middleware/endpoint or error response
40
40
  """
41
41
  # Determine transport type from request
42
42
  transport_type = self._get_request_transport_type(request)
43
-
43
+
44
44
  # Check if request matches configured transport
45
45
  if not self._is_transport_allowed(transport_type):
46
46
  configured_type = self.transport_manager.get_transport_type()
47
- configured_type_str = configured_type.value if configured_type else "not configured"
47
+ configured_type_str = (
48
+ configured_type.value if configured_type else "not configured"
49
+ )
48
50
  logger.warning(f"Transport not allowed: {transport_type} for {request.url}")
49
51
  return JSONResponse(
50
52
  status_code=403,
@@ -52,24 +54,24 @@ class TransportMiddleware(BaseHTTPMiddleware):
52
54
  "error": "Transport not allowed",
53
55
  "message": f"Transport '{transport_type}' is not allowed. Configured transport: {configured_type_str}",
54
56
  "configured_transport": configured_type_str,
55
- "request_url": str(request.url)
56
- }
57
+ "request_url": str(request.url),
58
+ },
57
59
  )
58
-
60
+
59
61
  # Add transport info to request state
60
62
  request.state.transport_type = transport_type
61
63
  request.state.transport_allowed = True
62
-
64
+
63
65
  response = await call_next(request)
64
66
  return response
65
-
67
+
66
68
  def _get_request_transport_type(self, request: Request) -> str:
67
69
  """
68
70
  Determine transport type from request.
69
-
71
+
70
72
  Args:
71
73
  request: Incoming request
72
-
74
+
73
75
  Returns:
74
76
  Transport type string
75
77
  """
@@ -79,14 +81,14 @@ class TransportMiddleware(BaseHTTPMiddleware):
79
81
  return "mtls"
80
82
  return "https"
81
83
  return "http"
82
-
84
+
83
85
  def _has_client_certificate(self, request: Request) -> bool:
84
86
  """
85
87
  Check if request has client certificate.
86
-
88
+
87
89
  Args:
88
90
  request: Incoming request
89
-
91
+
90
92
  Returns:
91
93
  True if client certificate is present, False otherwise
92
94
  """
@@ -95,22 +97,22 @@ class TransportMiddleware(BaseHTTPMiddleware):
95
97
  client_cert_header = request.headers.get("ssl-client-cert")
96
98
  if client_cert_header:
97
99
  return True
98
-
100
+
99
101
  # Check if request has SSL client certificate context
100
102
  if hasattr(request, "client") and request.client:
101
103
  # In a real implementation, you would check the SSL context
102
104
  # For now, we'll assume HTTPS with client cert is MTLS
103
105
  return self.transport_manager.is_mtls()
104
-
106
+
105
107
  return False
106
-
108
+
107
109
  def _is_transport_allowed(self, transport_type: str) -> bool:
108
110
  """
109
111
  Check if transport type is allowed.
110
-
112
+
111
113
  Args:
112
114
  transport_type: Transport type to check
113
-
115
+
114
116
  Returns:
115
117
  True if transport is allowed, False otherwise
116
118
  """
@@ -118,5 +120,5 @@ class TransportMiddleware(BaseHTTPMiddleware):
118
120
  if not configured_type:
119
121
  logger.error("Transport not configured")
120
122
  return False
121
-
122
- return transport_type == configured_type.value
123
+
124
+ return transport_type == configured_type.value