Skip to content

Commit 1ff7065

Browse files
committed
refactored out the events from the main Fast_API, and now we have a new Fast_API__With_Events that captures that (and can be used when events want to be captured)
added Middleware__Request_ID so that we always have an request id (specially when not using the events capture)
1 parent 2d31ec2 commit 1ff7065

15 files changed

Lines changed: 235 additions & 131 deletions

osbot_fast_api/api/Fast_API.py

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from osbot_fast_api.api.middlewares.Middleware__Http_Request import Middleware__Http_Request
2+
from osbot_fast_api.api.middlewares.Middleware__Request_ID import Middleware__Request_ID
13
from osbot_fast_api.schemas.Schema__Fast_API__Config import Schema__Fast_API__Config
24
from osbot_utils.type_safe.Type_Safe import Type_Safe
35
from osbot_utils.decorators.lists.index_by import index_by
@@ -6,32 +8,20 @@
68
from osbot_utils.utils.Json import json_loads, json_dumps
79
from starlette.staticfiles import StaticFiles
810
from osbot_fast_api.api.Fast_API__Offline_Docs import Fast_API__Offline_Docs, FILE_PATH__STATIC__DOCS, URL__STATIC__DOCS, NAME__STATIC__DOCS
9-
from osbot_fast_api.api.events.Fast_API__Http_Events import Fast_API__Http_Events
1011
from osbot_fast_api.api.routes.Routes__Config import Routes__Config
1112
from osbot_fast_api.api.routes.Routes__Set_Cookie import Routes__Set_Cookie
1213
from osbot_fast_api.schemas.consts.consts__Fast_API import ENV_VAR__FAST_API__AUTH__API_KEY__NAME, ENV_VAR__FAST_API__AUTH__API_KEY__VALUE
1314

1415

1516

1617
class Fast_API(Type_Safe):
17-
# base_path : Safe_Str__Fast_API__Route__Prefix = '/'
18-
# add_admin_ui : bool = False
19-
# docs_offline : bool = True
20-
# enable_cors : bool = False
21-
# enable_api_key : bool = False
22-
# default_routes : bool = True
23-
# name : Safe_Str__Fast_API__Name = None
24-
# version : Safe_Str__Version = version__osbot_fast_api
25-
# description : Safe_Str__Text = None
2618
config : Schema__Fast_API__Config
27-
http_events : Fast_API__Http_Events
2819
server_id : Random_Guid
2920

3021
def __init__(self, **kwargs):
3122
super().__init__(**kwargs)
3223
if not self.config.name:
33-
self.config.name = self.__class__.__name__
34-
self.http_events.fast_api_name = self.config.name
24+
self.config.name = self.__class__.__name__ # this makes the api name more user friendly
3525

3626
# todo: improve the error handling of validation errors (namely from Type_Safe_Primitive)
3727
# see code example in https://claude.ai/chat/f443e322-fa43-487f-9dd9-2d4cfb261b1e
@@ -166,8 +156,8 @@ def routes_paths_all(self):
166156

167157

168158
def setup_middlewares(self): # overwrite to add more middlewares
159+
self.setup_middleware__request_id () # sets the 'fast-api-request-id' headers
169160
self.setup_middleware__detect_disconnect()
170-
self.setup_middleware__http_events ()
171161
self.setup_middleware__cors ()
172162
self.setup_middleware__api_key_check ()
173163
return self
@@ -230,12 +220,8 @@ def setup_middleware__detect_disconnect(self):
230220

231221
self.app().add_middleware(Middleware__Detect_Disconnect)
232222

233-
def setup_middleware__http_events(self):
234-
from osbot_fast_api.api.middlewares.Middleware__Http_Request import Middleware__Http_Request
235-
236-
self.app().add_middleware(Middleware__Http_Request , http_events=self.http_events)
237-
return self
238-
223+
def setup_middleware__request_id(self):
224+
self.app().add_middleware(Middleware__Request_ID)
239225

240226
def user_middlewares(self, include_params=True):
241227
import types

osbot_fast_api/api/events/Fast_API__Http_Event.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import logging
22
import time
3-
from decimal import Decimal
4-
from fastapi import Response, Request
5-
from osbot_fast_api.api.events.Fast_API__Http_Event__Info import Fast_API__Http_Event__Info
6-
from osbot_fast_api.api.events.Fast_API__Http_Event__Request import Fast_API__Http_Event__Request
7-
from osbot_fast_api.api.events.Fast_API__Http_Event__Response import Fast_API__Http_Event__Response
8-
from osbot_fast_api.api.events.Fast_API__Http_Event__Traces import Fast_API__Http_Event__Traces
9-
from osbot_utils.type_safe.Type_Safe import Type_Safe
10-
from osbot_utils.type_safe.primitives.domains.identifiers.Random_Guid import Random_Guid
11-
from osbot_utils.helpers.trace.Trace_Call import Trace_Call
12-
from osbot_utils.utils.Misc import timestamp_utc_now, current_thread_id, str_to_bytes
13-
from osbot_utils.utils.Objects import pickle_to_bytes
3+
from decimal import Decimal
4+
from fastapi import Response, Request
5+
from osbot_fast_api.api.events.Fast_API__Http_Event__Info import Fast_API__Http_Event__Info
6+
from osbot_fast_api.api.events.Fast_API__Http_Event__Request import Fast_API__Http_Event__Request
7+
from osbot_fast_api.api.events.Fast_API__Http_Event__Response import Fast_API__Http_Event__Response
8+
from osbot_fast_api.api.events.Fast_API__Http_Event__Traces import Fast_API__Http_Event__Traces
9+
from osbot_utils.type_safe.Type_Safe import Type_Safe
10+
from osbot_utils.type_safe.primitives.domains.identifiers.Random_Guid import Random_Guid
11+
from osbot_utils.helpers.trace.Trace_Call import Trace_Call
12+
from osbot_utils.utils.Misc import timestamp_utc_now, current_thread_id, str_to_bytes
13+
from osbot_utils.utils.Objects import pickle_to_bytes
1414

1515
HEADER_NAME__FAST_API_REQUEST_ID = 'fast-api-request-id'
1616
HEADER_NAME__CACHE_CONTROL = "cache-control"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from fastapi import Request, Response
2+
from osbot_utils.utils.Misc import str_to_bytes
3+
from starlette.middleware.base import BaseHTTPMiddleware
4+
from osbot_utils.type_safe.primitives.domains.identifiers.Random_Guid import Random_Guid
5+
6+
7+
class Middleware__Request_ID(BaseHTTPMiddleware): # Lightweight middleware for request ID generation and propagation
8+
9+
async def dispatch(self, request: Request, call_next) -> Response:
10+
request_id = Random_Guid() # Generate request ID once
11+
request.state.request_id = request_id # Make available during request processing
12+
13+
14+
request.headers._list.append((b'fast-api-request-id', str_to_bytes(request_id))) # Also add to request headers for consistency (though request.state is the preferred access method)
15+
16+
response = await call_next(request) # Process request
17+
18+
response.headers['fast-api-request-id'] = str(request_id) # Add to response headers for client
19+
20+
return response

osbot_fast_api/api/routes/Fast_API__Routes.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import functools
22
import inspect
3-
from typing import get_type_hints
4-
from fastapi import APIRouter, FastAPI, HTTPException
5-
from osbot_utils.type_safe.Type_Safe import Type_Safe
6-
from osbot_utils.decorators.lists.index_by import index_by
7-
from osbot_utils.type_safe.Type_Safe__Primitive import Type_Safe__Primitive
8-
from fastapi.exceptions import RequestValidationError
9-
from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Cache import type_safe_cache
10-
from osbot_fast_api.api.routes.Fast_API__Route__Parser import Fast_API__Route__Parser
11-
from osbot_fast_api.api.transformers.Type_Safe__To__BaseModel import type_safe__to__basemodel
12-
from osbot_fast_api.schemas.safe_str.Safe_Str__Fast_API__Route__Prefix import Safe_Str__Fast_API__Route__Prefix
13-
from osbot_fast_api.schemas.safe_str.Safe_Str__Fast_API__Route__Tag import Safe_Str__Fast_API__Route__Tag
3+
from typing import get_type_hints
4+
from fastapi import APIRouter, FastAPI, HTTPException
5+
from osbot_utils.type_safe.Type_Safe import Type_Safe
6+
from osbot_utils.decorators.lists.index_by import index_by
7+
from osbot_utils.type_safe.Type_Safe__Primitive import Type_Safe__Primitive
8+
from fastapi.exceptions import RequestValidationError
9+
from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Cache import type_safe_cache
10+
from osbot_fast_api.api.routes.Fast_API__Route__Parser import Fast_API__Route__Parser
11+
from osbot_fast_api.api.transformers.Type_Safe__To__BaseModel import type_safe__to__basemodel
12+
from osbot_fast_api.schemas.safe_str.Safe_Str__Fast_API__Route__Prefix import Safe_Str__Fast_API__Route__Prefix
13+
from osbot_fast_api.schemas.safe_str.Safe_Str__Fast_API__Route__Tag import Safe_Str__Fast_API__Route__Tag
1414

1515

1616
class Fast_API__Routes(Type_Safe): # refactor to Fast_API__Routes
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from osbot_fast_api.api.Fast_API import Fast_API
2+
from osbot_fast_api.api.events.Fast_API__Http_Events import Fast_API__Http_Events
3+
4+
5+
class Fast_API__With_Events(Fast_API):
6+
http_events : Fast_API__Http_Events # Only in this subclass
7+
8+
def __init__(self, **kwargs):
9+
super().__init__(**kwargs)
10+
self.http_events.fast_api_name = self.config.name # Wire up the name
11+
12+
def setup_middlewares(self): # Add event middleware
13+
super().setup_middlewares() # Call parent middlewares first
14+
self.setup_middleware__http_events() # Then add events
15+
return self
16+
17+
def setup_middleware__http_events(self): # Moved from base class
18+
from osbot_fast_api.api.middlewares.Middleware__Http_Request import Middleware__Http_Request
19+
20+
self.app().add_middleware(Middleware__Http_Request, http_events=self.http_events)
21+
return self
22+
23+
def event_id(self, request): # Event tracking methods
24+
return self.http_events.event_id(request)
25+
26+
def request_data(self, request):
27+
return self.http_events.request_data(request)
28+
29+
def request_messages(self, request):
30+
return self.http_events.request_messages(request)
31+
32+
def add_background_task(self, task): # Background task management
33+
self.http_events.background_tasks.append(task)
34+
return self
35+
36+
def enable_request_tracing(self, config=None): # Tracing configuration
37+
self.http_events.trace_calls = True
38+
if config:
39+
self.http_events.trace_call_config = config
40+
return self
41+
42+
def disable_request_tracing(self):
43+
self.http_events.trace_calls = False
44+
return self
45+
46+
def set_callback_on_request(self, callback): # Event callbacks
47+
self.http_events.callback_on_request = callback
48+
return self
49+
50+
def set_callback_on_response(self, callback):
51+
self.http_events.callback_on_response = callback
52+
return self
53+
54+
def get_recent_requests(self, count=10): # Request history
55+
recent = list(self.http_events.requests_order)[-count:]
56+
return [self.http_events.requests_data.get(event_id) for event_id in recent]
57+
58+
def clear_request_history(self):
59+
self.http_events.requests_data.clear()
60+
self.http_events.requests_order.clear()
61+
return self

osbot_fast_api/events/__init__.py

Whitespace-only changes.

tests/unit/api/events/test_Fast_API__Http_Events.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import logging
2-
32
import pytest
43
from collections import deque
54
from decimal import Decimal

tests/unit/api/middlewares/test_MIddleware__Check_API_Key.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from unittest import TestCase
22
from osbot_fast_api.api.Fast_API import Fast_API, ENV_VAR__FAST_API__AUTH__API_KEY__NAME, ENV_VAR__FAST_API__AUTH__API_KEY__VALUE
33
from osbot_fast_api.api.middlewares.Middleware__Check_API_Key import ERROR_MESSAGE__NO_KEY_NAME_SETUP, ERROR_MESSAGE__NO_KEY_VALUE_SETUP, ERROR_MESSAGE__API_KEY_MISSING
4-
from osbot_fast_api.schemas.consts.consts__Fast_API import AUTH__EXCLUDED_PATHS
4+
from osbot_fast_api.schemas.consts.consts__Fast_API import AUTH__EXCLUDED_PATHS
55
from osbot_fast_api.utils.Fast_API__Server_Info import fast_api__server_info
66
from osbot_utils.testing.Temp_Env_Vars import Temp_Env_Vars
77
from osbot_utils.utils.Status import status_error

tests/unit/api/routes/test_Fast_API__Routes__client.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
from unittest import TestCase
2-
from fastapi import Request
3-
4-
from osbot_fast_api.schemas.Schema__Fast_API__Config import Schema__Fast_API__Config
5-
from osbot_utils.type_safe.Type_Safe import Type_Safe
6-
from osbot_fast_api.api.Fast_API import Fast_API
7-
from osbot_fast_api.api.routes.Fast_API__Routes import Fast_API__Routes
1+
from unittest import TestCase
2+
from fastapi import Request
3+
from osbot_fast_api.schemas.Schema__Fast_API__Config import Schema__Fast_API__Config
4+
from osbot_utils.type_safe.Type_Safe import Type_Safe
5+
from osbot_fast_api.api.Fast_API import Fast_API
6+
from osbot_fast_api.api.routes.Fast_API__Routes import Fast_API__Routes
87
from osbot_fast_api.schemas.safe_str.Safe_Str__Fast_API__Route__Prefix import Safe_Str__Fast_API__Route__Prefix
98

109

tests/unit/api/routes/test_Fast_API__Routes__with_path_params.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from unittest import TestCase
2-
from osbot_fast_api.api.Fast_API import Fast_API
3-
from osbot_fast_api.api.routes.Fast_API__Routes import Fast_API__Routes
1+
from unittest import TestCase
2+
from osbot_fast_api.api.Fast_API import Fast_API
3+
from osbot_fast_api.api.routes.Fast_API__Routes import Fast_API__Routes
44
from osbot_fast_api.schemas.Schema__Fast_API__Config import Schema__Fast_API__Config
55

66

0 commit comments

Comments
 (0)