event to functon handler completed
This commit is contained in:
@@ -10,14 +10,53 @@ This module initializes and configures the FastAPI application with:
|
||||
"""
|
||||
|
||||
import uvicorn
|
||||
import routers
|
||||
|
||||
from create_file import create_app
|
||||
from fastapi import FastAPI
|
||||
from create_routes import get_all_routers
|
||||
from prometheus_fastapi_instrumentator import Instrumentator
|
||||
from app_handler import setup_middleware, get_uvicorn_config
|
||||
from create_file import setup_security_schema, configure_route_security
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
|
||||
|
||||
app = create_app(routers=routers) # Initialize FastAPI application
|
||||
def create_app() -> FastAPI:
|
||||
"""Create and configure the FastAPI application."""
|
||||
app = FastAPI()
|
||||
|
||||
# Get all routers and protected routes from the new configuration
|
||||
routers, protected_routes = get_all_routers()
|
||||
|
||||
# Include all routers
|
||||
for router in routers:
|
||||
app.include_router(router)
|
||||
|
||||
# Configure OpenAPI schema with security
|
||||
def custom_openapi():
|
||||
if app.openapi_schema:
|
||||
return app.openapi_schema
|
||||
|
||||
openapi_schema = get_openapi(
|
||||
title="WAG Management API",
|
||||
version="4.0.0",
|
||||
description="WAG Management API Service",
|
||||
routes=app.routes,
|
||||
)
|
||||
|
||||
# Add security scheme
|
||||
openapi_schema.update(setup_security_schema())
|
||||
|
||||
# Configure security for protected routes
|
||||
for path, methods in protected_routes.items():
|
||||
for method in methods:
|
||||
configure_route_security(path, method, openapi_schema, list(protected_routes.keys()))
|
||||
|
||||
app.openapi_schema = openapi_schema
|
||||
return app.openapi_schema
|
||||
|
||||
app.openapi = custom_openapi
|
||||
return app
|
||||
|
||||
|
||||
app = create_app() # Initialize FastAPI application
|
||||
Instrumentator().instrument(app=app).expose(app=app) # Setup Prometheus metrics
|
||||
setup_middleware(app) # Configure middleware and exception handlers
|
||||
|
||||
|
||||
@@ -9,15 +9,14 @@ This module provides functionality to create and configure a FastAPI application
|
||||
- Security requirements for protected endpoints
|
||||
"""
|
||||
|
||||
from types import ModuleType
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
from typing import Any, Dict, List, Tuple
|
||||
from fastapi import FastAPI, APIRouter
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
from fastapi.routing import APIRoute
|
||||
from AllConfigs.main import MainConfig as Config
|
||||
from middleware.auth_middleware import MiddlewareModule
|
||||
|
||||
from AllConfigs.main import MainConfig as Config
|
||||
|
||||
from create_routes import get_all_routers
|
||||
|
||||
def setup_security_schema() -> Dict[str, Any]:
|
||||
"""
|
||||
@@ -27,15 +26,18 @@ def setup_security_schema() -> Dict[str, Any]:
|
||||
Dict[str, Any]: Security schema configuration
|
||||
"""
|
||||
return {
|
||||
"Bearer": {
|
||||
"type": "http",
|
||||
"scheme": "bearer",
|
||||
"bearerFormat": "JWT",
|
||||
"description": "Enter the token",
|
||||
"components": {
|
||||
"securitySchemes": {
|
||||
"Bearer": {
|
||||
"type": "http",
|
||||
"scheme": "bearer",
|
||||
"bearerFormat": "JWT",
|
||||
"description": "Enter the token"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def configure_route_security(
|
||||
path: str, method: str, schema: Dict[str, Any], protected_paths: List[str]
|
||||
) -> None:
|
||||
@@ -49,42 +51,13 @@ def configure_route_security(
|
||||
protected_paths: List of paths that require authentication
|
||||
"""
|
||||
if path in protected_paths:
|
||||
if "paths" not in schema:
|
||||
schema["paths"] = {}
|
||||
if "paths" in schema and path in schema["paths"]:
|
||||
if method.lower() in schema["paths"][path]:
|
||||
schema["paths"][path][method.lower()]["security"] = [{"Bearer": []}]
|
||||
|
||||
if path not in schema["paths"]:
|
||||
schema["paths"][path] = {}
|
||||
|
||||
if method not in schema["paths"][path]:
|
||||
schema["paths"][path][method] = {}
|
||||
|
||||
schema["paths"][path][method]["security"] = [{"Bearer": []}]
|
||||
|
||||
|
||||
def get_routers(routers_module: ModuleType) -> List[APIRouter]:
|
||||
def create_app() -> FastAPI:
|
||||
"""
|
||||
Extract all routers from the routers module.
|
||||
|
||||
Args:
|
||||
routers_module: Module containing router definitions
|
||||
|
||||
Returns:
|
||||
List[APIRouter]: List of router instances
|
||||
"""
|
||||
routers = []
|
||||
for attr_name in dir(routers_module):
|
||||
attr = getattr(routers_module, attr_name)
|
||||
if isinstance(attr, APIRouter):
|
||||
routers.append(attr)
|
||||
return routers
|
||||
|
||||
|
||||
def create_app(routers: ModuleType) -> FastAPI:
|
||||
"""
|
||||
Create and configure a FastAPI application.
|
||||
|
||||
Args:
|
||||
routers: Module containing router definitions
|
||||
Create and configure a FastAPI application with dynamic route creation.
|
||||
|
||||
Returns:
|
||||
FastAPI: Configured FastAPI application instance
|
||||
@@ -95,53 +68,39 @@ def create_app(routers: ModuleType) -> FastAPI:
|
||||
description=Config.DESCRIPTION,
|
||||
default_response_class=JSONResponse,
|
||||
)
|
||||
|
||||
# Add home route that redirects to API documentation
|
||||
|
||||
@app.get("/", include_in_schema=False, summary=str(Config.DESCRIPTION))
|
||||
async def home() -> RedirectResponse:
|
||||
"""Redirect root path to API documentation."""
|
||||
return RedirectResponse(url="/docs")
|
||||
|
||||
# Get all routers
|
||||
router_instances = get_routers(routers)
|
||||
|
||||
# Find protected paths
|
||||
protected_paths = []
|
||||
for router in router_instances:
|
||||
for route in router.routes:
|
||||
if isinstance(route, APIRoute):
|
||||
# Check if the route has auth_required decorator
|
||||
if any(d.__name__ == "auth_required" for d in route.dependencies):
|
||||
protected_paths.append(route.path)
|
||||
|
||||
# Include routers
|
||||
for router in router_instances:
|
||||
# Get all routers and protected routes using the dynamic route creation
|
||||
routers, protected_routes = get_all_routers()
|
||||
|
||||
# Include all routers
|
||||
for router in routers:
|
||||
app.include_router(router)
|
||||
|
||||
# Configure custom OpenAPI schema
|
||||
|
||||
# Configure OpenAPI schema with security
|
||||
def custom_openapi():
|
||||
if app.openapi_schema:
|
||||
return app.openapi_schema
|
||||
|
||||
openapi_schema = get_openapi(
|
||||
title=Config.TITLE,
|
||||
version="1.0.0",
|
||||
description=Config.DESCRIPTION,
|
||||
title="WAG Management API",
|
||||
version="4.0.0",
|
||||
description="WAG Management API Service",
|
||||
routes=app.routes,
|
||||
)
|
||||
|
||||
# Add security schemes
|
||||
openapi_schema["components"] = {"securitySchemes": setup_security_schema()}
|
||||
# Add security scheme
|
||||
security_schema = setup_security_schema()
|
||||
openapi_schema.update(security_schema)
|
||||
|
||||
# Configure security for each route
|
||||
for route in app.routes:
|
||||
if isinstance(route, APIRoute):
|
||||
configure_route_security(
|
||||
route.path,
|
||||
route.methods.pop().lower(),
|
||||
openapi_schema,
|
||||
protected_paths,
|
||||
)
|
||||
# Configure security for protected routes
|
||||
for path, methods in protected_routes.items():
|
||||
for method in methods:
|
||||
configure_route_security(path, method, openapi_schema, list(protected_routes.keys()))
|
||||
|
||||
app.openapi_schema = openapi_schema
|
||||
return app.openapi_schema
|
||||
|
||||
119
DockerApiServices/AllApiNeeds/create_routes.py
Normal file
119
DockerApiServices/AllApiNeeds/create_routes.py
Normal file
@@ -0,0 +1,119 @@
|
||||
"""
|
||||
Route configuration and factory module.
|
||||
Handles dynamic route creation based on configurations.
|
||||
"""
|
||||
|
||||
from typing import Optional, Dict, Any, List, Callable, TypeVar, ParamSpec
|
||||
|
||||
P = ParamSpec('P') # For function parameters
|
||||
R = TypeVar('R') # For return type
|
||||
|
||||
from dataclasses import dataclass
|
||||
from functools import wraps
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.routing import APIRoute
|
||||
from middleware.auth_middleware import MiddlewareModule
|
||||
from pydantic import BaseModel
|
||||
from AllConfigs.main import MainConfig as Config
|
||||
from ApiEvents.EventServiceApi.route_configs import get_route_configs
|
||||
|
||||
|
||||
@dataclass
|
||||
class EndpointFactoryConfig:
|
||||
endpoint: str
|
||||
method: str
|
||||
summary: str
|
||||
description: str
|
||||
endpoint_function: Callable[P, R] # Now accepts any parameters and return type
|
||||
response_model: Optional[type] = None
|
||||
request_model: Optional[type] = None
|
||||
is_auth_required: bool = True
|
||||
is_event_required: bool = False
|
||||
extra_options: Dict[str, Any] = None
|
||||
|
||||
def __post_init__(self):
|
||||
if self.extra_options is None:
|
||||
self.extra_options = {}
|
||||
|
||||
|
||||
class EnhancedEndpointFactory:
|
||||
def __init__(self, router_config: dict):
|
||||
self.router = APIRouter(
|
||||
prefix=router_config['prefix'],
|
||||
tags=router_config['tags'],
|
||||
include_in_schema=router_config.get('include_in_schema', True)
|
||||
)
|
||||
self.endpoints = router_config['endpoints']
|
||||
self.protected_routes: Dict[str, List[str]] = {}
|
||||
|
||||
def create_endpoint(self, config: EndpointFactoryConfig):
|
||||
"""
|
||||
Create an endpoint directly from the configuration.
|
||||
|
||||
Args:
|
||||
config: EndpointFactoryConfig instance containing endpoint configuration
|
||||
"""
|
||||
endpoint_path = config.endpoint
|
||||
endpoint_function = config.endpoint_function
|
||||
|
||||
if config.is_auth_required:
|
||||
endpoint_function = MiddlewareModule.auth_required(endpoint_function)
|
||||
# Track protected routes
|
||||
full_path = f"{self.router.prefix}{endpoint_path}"
|
||||
if full_path not in self.protected_routes:
|
||||
self.protected_routes[full_path] = []
|
||||
self.protected_routes[full_path].append(config.method.lower())
|
||||
|
||||
# Register the endpoint with FastAPI router
|
||||
getattr(self.router, config.method.lower())(
|
||||
endpoint_path,
|
||||
response_model=config.response_model,
|
||||
summary=config.summary,
|
||||
description=config.description,
|
||||
**config.extra_options
|
||||
)(endpoint_function)
|
||||
|
||||
def get_router(self) -> APIRouter:
|
||||
"""Get the configured router."""
|
||||
return self.router
|
||||
|
||||
def get_protected_routes(self) -> Dict[str, List[str]]:
|
||||
"""Get the protected routes mapping."""
|
||||
return self.protected_routes
|
||||
|
||||
|
||||
async def health_check(request: Request):
|
||||
"""Default health check endpoint."""
|
||||
return {"status": "healthy", "message": "Service is running"}
|
||||
|
||||
|
||||
async def ping_test(request: Request, service_name: str = "base-router"):
|
||||
"""Default ping test endpoint."""
|
||||
return {"ping": "pong", "service": service_name}
|
||||
|
||||
|
||||
def get_all_routers() -> tuple[List[APIRouter], Dict[str, List[str]]]:
|
||||
"""
|
||||
Get all configured routers and their protected routes.
|
||||
|
||||
Returns:
|
||||
tuple: (routers, protected_routes)
|
||||
"""
|
||||
routers = []
|
||||
all_protected_routes = {}
|
||||
|
||||
# Get route configurations from the registry
|
||||
route_configs = get_route_configs()
|
||||
|
||||
for config in route_configs:
|
||||
factory = EnhancedEndpointFactory(config)
|
||||
|
||||
# Create endpoints from configuration
|
||||
for endpoint_config in config['endpoints']:
|
||||
factory.create_endpoint(endpoint_config)
|
||||
|
||||
# Add router and protected routes
|
||||
routers.append(factory.get_router())
|
||||
all_protected_routes.update(factory.get_protected_routes())
|
||||
|
||||
return routers, all_protected_routes
|
||||
@@ -113,6 +113,7 @@ class MiddlewareModule:
|
||||
raise HTTPExceptionApi(error_code="NOT_AUTHORIZED", lang="tr")
|
||||
except Exception as e:
|
||||
raise HTTPExceptionApi(error_code="NOT_AUTHORIZED", lang="tr")
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
from .base_router import test_route
|
||||
|
||||
__all__ = ["test_route"]
|
||||
@@ -1,22 +0,0 @@
|
||||
"""
|
||||
Base router configuration and setup.
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from middleware.auth_middleware import MiddlewareModule
|
||||
|
||||
# Create test router
|
||||
test_route = APIRouter(prefix="/test", tags=["Test"])
|
||||
test_route.include_router(test_route, include_in_schema=True)
|
||||
|
||||
|
||||
@test_route.get("/health")
|
||||
@MiddlewareModule.auth_required
|
||||
async def health_check(request: Request):
|
||||
return {"status": "healthy", "message": "Service is running"}
|
||||
|
||||
|
||||
@test_route.get("/ping")
|
||||
async def ping_test():
|
||||
return {"ping": "pong", "service": "base-router"}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.9-slim
|
||||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -19,7 +19,6 @@ RUN poetry config virtualenvs.create false \
|
||||
&& rm -rf ~/.cache/pypoetry
|
||||
|
||||
# Copy application code
|
||||
|
||||
COPY DockerApiServices/AllApiNeeds /app/
|
||||
COPY ErrorHandlers /app/ErrorHandlers
|
||||
COPY LanguageModels /app/LanguageModels
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.9-slim
|
||||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.9-slim
|
||||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@ pytest-cov = "^4.1.0"
|
||||
prometheus-client = "^0.19.0"
|
||||
prometheus-fastapi-instrumentator = "^6.1.0"
|
||||
|
||||
# Cryptography
|
||||
cryptography = "^43.0.3"
|
||||
|
||||
# Utilities
|
||||
python-dateutil = "^2.8.2"
|
||||
typing-extensions = "^4.8.0"
|
||||
|
||||
Reference in New Issue
Block a user