Skip to content

Commit

Permalink
refactored imports
Browse files Browse the repository at this point in the history
  • Loading branch information
DinisCruz committed Nov 23, 2024
1 parent f23efed commit 5ac162e
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 39 deletions.
50 changes: 33 additions & 17 deletions osbot_fast_api/api/Fast_API.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,9 @@
import traceback
import types
from fastapi import FastAPI, Request, HTTPException
from fastapi.exceptions import RequestValidationError
from starlette.middleware.wsgi import WSGIMiddleware # todo replace this with a2wsgi
from osbot_fast_api.api.Fast_API__Http_Events import Fast_API__Http_Events
from osbot_fast_api.api.middlewares.Middleware__Detect_Disconnect import Middleware__Detect_Disconnect
from osbot_fast_api.api.middlewares.Middleware__Http_Request import Middleware__Http_Request
from osbot_fast_api.utils.Version import Version
from osbot_utils.base_classes.Type_Safe import Type_Safe
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import RedirectResponse, JSONResponse
from starlette.staticfiles import StaticFiles
from osbot_utils.helpers.Random_Guid import Random_Guid
from osbot_utils.utils.Lists import list_index_by
from osbot_utils.utils.Misc import list_set
from osbot_utils.decorators.lists.index_by import index_by
from osbot_utils.decorators.methods.cache_on_self import cache_on_self
from starlette.testclient import TestClient
from osbot_fast_api.api.routes.Routes_Config import Routes_Config
from osbot_fast_api.utils.http_shell.Http_Shell__Server import Model__Shell_Command, Http_Shell__Server
from osbot_fast_api.utils.Fast_API_Utils import Fast_API_Utils


DEFAULT_ROUTES_PATHS = ['/', '/config/status', '/config/version']
DEFAULT__NAME__FAST_API = 'Fast_API'
Expand All @@ -38,6 +22,11 @@ def __init__(self, **kwargs):
self.http_events.fast_api_name = self.name

def add_global_exception_handlers(self): # todo: move to Fast_API
import traceback
from fastapi import Request, HTTPException
from fastapi.exceptions import RequestValidationError
from starlette.responses import JSONResponse

app = self.app()
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
Expand All @@ -57,10 +46,13 @@ async def validation_exception_handler(request: Request, exc: RequestValidationE


def add_flask_app(self, path, flask_app):
from starlette.middleware.wsgi import WSGIMiddleware # todo replace this with a2wsgi

self.app().mount(path, WSGIMiddleware(flask_app))
return self

def add_shell_server(self):
from osbot_fast_api.utils.http_shell.Http_Shell__Server import Model__Shell_Command, Http_Shell__Server
def shell_server(shell_command: Model__Shell_Command):
return Http_Shell__Server().invoke(shell_command)
self.add_route_post(shell_server)
Expand All @@ -82,15 +74,19 @@ def add_routes(self, class_routes):

@cache_on_self
def app(self, **kwargs):
from fastapi import FastAPI
return FastAPI(**kwargs)

def app_router(self):
return self.app().router

def client(self):
from starlette.testclient import TestClient # moved here for performance reasons
return TestClient(self.app())

def fast_api_utils(self):
from osbot_fast_api.utils.Fast_API_Utils import Fast_API_Utils

return Fast_API_Utils(self.app())

def path_static_folder(self): # override this to add support for serving static files from this directory
Expand Down Expand Up @@ -120,10 +116,15 @@ def route_remove(self, path):
return False

def routes_methods(self):
from osbot_utils.utils.Misc import list_set

return list_set(self.routes(index_by='method_name'))


def routes_paths(self, include_default=False, expand_mounts=False):
from osbot_utils.utils.Lists import list_index_by
from osbot_utils.utils.Misc import list_set

routes_paths = self.routes(include_default=include_default, expand_mounts=expand_mounts)
return list_set(list_index_by(routes_paths, 'http_path'))

Expand All @@ -140,24 +141,32 @@ def setup_routes (self): return self # overwrite to add rules


def setup_default_routes(self):
from osbot_fast_api.api.routes.Routes_Config import Routes_Config

if self.default_routes:
self.setup_add_root_route()
self.add_routes(Routes_Config)

def setup_add_root_route(self):
from starlette.responses import RedirectResponse

def redirect_to_docs():
return RedirectResponse(url="/docs")
self.app_router().get("/")(redirect_to_docs)


def setup_static_routes(self):
from starlette.staticfiles import StaticFiles

path_static_folder = self.path_static_folder()
if path_static_folder:
path_static = "/static"
path_name = "static"
self.app().mount(path_static, StaticFiles(directory=path_static_folder), name=path_name)

def setup_middleware__cors(self): # todo: double check that this is working see bug test
from starlette.middleware.cors import CORSMiddleware

if self.enable_cors:
self.app().add_middleware(CORSMiddleware,
allow_origins = ["*"] ,
Expand All @@ -167,14 +176,20 @@ def setup_middleware__cors(self): # todo: double check that this i
expose_headers = ["Content-Type", "X-Requested-With", "Origin", "Accept", "Authorization"])

def setup_middleware__detect_disconnect(self):
from osbot_fast_api.api.middlewares.Middleware__Detect_Disconnect import Middleware__Detect_Disconnect

self.app().add_middleware(Middleware__Detect_Disconnect)

def setup_middleware__http_events(self):
from osbot_fast_api.api.middlewares.Middleware__Http_Request import Middleware__Http_Request

self.app().add_middleware(Middleware__Http_Request , http_events=self.http_events)
return self


def user_middlewares(self):
import types

middlewares = []
data = self.app().user_middleware
for item in data:
Expand All @@ -192,6 +207,7 @@ def user_middlewares(self):
return middlewares

def version__fast_api_server(self):
from osbot_fast_api.utils.Version import Version
return Version().value()

# def run_in_lambda(self):
Expand Down
8 changes: 4 additions & 4 deletions osbot_fast_api/api/Fast_API_Routes.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
from fastapi import APIRouter, FastAPI
from osbot_utils.base_classes.Type_Safe import Type_Safe
from osbot_utils.decorators.lists.index_by import index_by
from osbot_utils.utils.Misc import lower
from osbot_utils.utils.Str import str_safe
from osbot_fast_api.utils.Fast_API_Utils import Fast_API_Utils

#DEFAULT_ROUTES = ['/docs', '/docs/oauth2-redirect', '/openapi.json', '/redoc']

class Fast_API_Routes(Type_Safe): # refactor to Fast_API__Routes
router : APIRouter
Expand All @@ -14,6 +10,9 @@ class Fast_API_Routes(Type_Safe): # refactor to Fast_API__Routes
tag : str

def __init__(self, **kwargs):
from osbot_utils.utils.Str import str_safe
from osbot_utils.utils.Misc import lower

super().__init__(**kwargs)
self.prefix = f'/{lower(str_safe(self.tag))}'

Expand All @@ -35,6 +34,7 @@ def add_route_put(self, function):
return self.add_route(function=function, methods=['PUT'])

def fast_api_utils(self):
from osbot_fast_api.utils.Fast_API_Utils import Fast_API_Utils
return Fast_API_Utils(self.app)

@index_by
Expand Down
32 changes: 21 additions & 11 deletions osbot_fast_api/api/Fast_API__Http_Events.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import types
from collections import deque
from osbot_fast_api.api.Fast_API__Http_Event import Fast_API__Http_Event
from osbot_fast_api.api.Fast_API__Http_Event__Info import Fast_API__Http_Event__Info
from osbot_utils.base_classes.Type_Safe import Type_Safe
from fastapi import Request
from starlette.responses import Response
from osbot_utils.helpers.trace.Trace_Call import Trace_Call
from osbot_utils.helpers.trace.Trace_Call__Config import Trace_Call__Config
from osbot_utils.utils.Misc import str_md5


HTTP_EVENTS__MAX_REQUESTS_LOGGED = 50

from typing import TYPE_CHECKING
if TYPE_CHECKING:
from fastapi import Request
from starlette.responses import Response
from osbot_fast_api.api.Fast_API__Http_Event import Fast_API__Http_Event

class Fast_API__Http_Events(Type_Safe):
#log_requests : bool = False # todo: change this to save on S3 and disk
background_tasks : list
Expand All @@ -29,14 +30,14 @@ def __init__(self,**kwargs):
super().__init__(**kwargs)
self.trace_call_config.ignore_start_with = ['osbot_fast_api.api.Fast_API__Http_Events'] # so that we don't see traces from this

def on_http_request(self, request: Request):
def on_http_request(self, request: 'Request'):
with self.request_data(request) as _:
_.on_request(request)
self.request_trace_start(request)
if self.callback_on_request:
self.callback_on_request(_)

def on_http_response(self, request: Request, response:Response):
def on_http_response(self, request: 'Request', response: 'Response'):
with self.request_data(request) as _:
_.on_response(response)
# if StreamingResponse not in base_types(response): # handle the special case when the response is a StreamingResponse
Expand All @@ -45,12 +46,14 @@ def on_http_response(self, request: Request, response:Response):
if self.callback_on_response:
self.callback_on_response(response, _)

def clean_request_data(self, request_data: Fast_API__Http_Event):
def clean_request_data(self, request_data: 'Fast_API__Http_Event'):
if self.clean_data:
self.clean_request_data_field(request_data.http_event_request , 'headers', 'cookie')
self.clean_request_data_field(request_data.http_event_response, 'headers', 'cookie')

def clean_request_data_field(self, request_data, variable_name, field_name):
from osbot_utils.utils.Misc import str_md5

with request_data as _:
variable_data = getattr(_, variable_name)
if type(variable_data) is dict:
Expand All @@ -68,6 +71,9 @@ def clean_request_data_field(self, request_data, variable_name, field_name):
#print(f">>>>> on on_response_stream_end : {state}")

def create_request_data(self, request):
from osbot_fast_api.api.Fast_API__Http_Event import Fast_API__Http_Event
from osbot_fast_api.api.Fast_API__Http_Event__Info import Fast_API__Http_Event__Info

kwargs = dict(fast_api_name = self.fast_api_name)
http_event_info = Fast_API__Http_Event__Info(**kwargs)
http_event = Fast_API__Http_Event(http_event_info=http_event_info)
Expand All @@ -84,7 +90,7 @@ def create_request_data(self, request):

return http_event

def request_data(self, request: Request): # todo: refactor all this request_data into a Request_Data class
def request_data(self, request: 'Request'): # todo: refactor all this request_data into a Request_Data class
if not hasattr(request.state, "request_data"):
request_data = self.create_request_data(request)
else:
Expand All @@ -100,13 +106,17 @@ def request_messages(self, request):
return self.requests_data.get(event_id, {}).get('messages', [])

def request_trace_start(self, request):
from osbot_utils.helpers.trace.Trace_Call import Trace_Call

if self.trace_calls:
trace_call_config = self.trace_call_config
trace_call = Trace_Call(config=trace_call_config)
trace_call.start()
request.state.trace_call = trace_call

def request_trace_stop(self, request: Request): # pragma: no cover
def request_trace_stop(self, request: 'Request'):
from osbot_utils.helpers.trace.Trace_Call import Trace_Call
# pragma: no cover
if self.trace_calls:
trace_call: Trace_Call = request.state.trace_call
trace_call.stop()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from starlette.types import ASGIApp, Receive, Scope, Send
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from starlette.types import ASGIApp, Receive, Scope, Send

class Middleware__Detect_Disconnect:
def __init__(self, app: ASGIApp):
def __init__(self, app: 'ASGIApp'):
self.app = app

async def __call__(self, scope: Scope, receive: Receive, send: Send):
async def __call__(self, scope: 'Scope', receive: 'Receive', send: 'Send'):
async def disconnect_monitor_receive():
message = await receive()
if message["type"] == "http.disconnect":
Expand Down
10 changes: 7 additions & 3 deletions osbot_fast_api/api/middlewares/Middleware__Http_Request.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
from fastapi import Request, BackgroundTasks
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import Response
from osbot_fast_api.api.Fast_API__Http_Events import Fast_API__Http_Events

from typing import TYPE_CHECKING
if TYPE_CHECKING:
from fastapi import Request
from starlette.responses import Response

class Middleware__Http_Request(BaseHTTPMiddleware):

def __init__(self, app, http_events: Fast_API__Http_Events):
super().__init__(app)
self.http_events = http_events

async def dispatch(self, request: Request, call_next) -> Response:
async def dispatch(self, request: 'Request', call_next) -> 'Response':

self.http_events.on_http_request(request)
response = None
Expand All @@ -23,6 +25,8 @@ async def dispatch(self, request: Request, call_next) -> Response:

# todo: figure if this should be here or on the http_events.on_http_response
def add_background_tasks_to_live_response(self, request, response):
from fastapi import BackgroundTasks

background_tasks = BackgroundTasks()
for background_task in self.http_events.background_tasks:
background_tasks.add_task(background_task, request=request, response=response)
Expand Down
1 change: 0 additions & 1 deletion osbot_fast_api/utils/http_shell/Http_Shell__Server.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os

from osbot_utils.utils.Env import load_dotenv
from osbot_utils.utils.Misc import is_guid
from osbot_utils.utils.Process import Process
Expand Down

0 comments on commit 5ac162e

Please sign in to comment.