error response due to language models are updated
This commit is contained in:
@@ -17,21 +17,11 @@ from prometheus_fastapi_instrumentator import Instrumentator
|
||||
from app_handler import setup_middleware, get_uvicorn_config
|
||||
|
||||
|
||||
print("Loading app.py module...")
|
||||
|
||||
# Initialize FastAPI application
|
||||
app = create_app(routers=routers)
|
||||
|
||||
# Setup Prometheus metrics
|
||||
Instrumentator().instrument(app=app).expose(app=app)
|
||||
|
||||
# Configure middleware and exception handlers
|
||||
setup_middleware(app)
|
||||
app = create_app(routers=routers) # Initialize FastAPI application
|
||||
Instrumentator().instrument(app=app).expose(app=app) # Setup Prometheus metrics
|
||||
setup_middleware(app) # Configure middleware and exception handlers
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Starting server from __main__...")
|
||||
# Run the application with Uvicorn
|
||||
uvicorn_config = get_uvicorn_config()
|
||||
print(f"Using config: {uvicorn_config}")
|
||||
uvicorn_config = get_uvicorn_config() # Run the application with Uvicorn
|
||||
uvicorn.Server(uvicorn.Config(**uvicorn_config)).run()
|
||||
|
||||
@@ -12,14 +12,8 @@ from typing import Dict, Any
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi import FastAPI, Request, HTTPException, status
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from ErrorHandlers.bases import (
|
||||
BaseErrorModelClass,
|
||||
StatusesModelClass,
|
||||
LanguageModelClass,
|
||||
)
|
||||
from ErrorHandlers import statuses
|
||||
from middleware.auth_middleware import MiddlewareModule
|
||||
from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
from middleware.auth_middleware import RequestTimingMiddleware
|
||||
|
||||
|
||||
def setup_cors_middleware(app: FastAPI) -> None:
|
||||
@@ -38,33 +32,6 @@ def setup_cors_middleware(app: FastAPI) -> None:
|
||||
)
|
||||
|
||||
|
||||
async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
|
||||
"""
|
||||
Handle HTTP exceptions and return formatted error responses.
|
||||
|
||||
Args:
|
||||
request: FastAPI request object
|
||||
exc: HTTP exception instance
|
||||
|
||||
Returns:
|
||||
JSONResponse: Formatted error response
|
||||
"""
|
||||
error_code = getattr(exc, "error_code", None)
|
||||
if error_code:
|
||||
status_code = StatusesModelClass.retrieve_error_by_code(error_code)
|
||||
error_message = LanguageModelClass.retrieve_error_by_code(
|
||||
error_code, request.headers.get("accept-language", "en")
|
||||
)
|
||||
else:
|
||||
status_code = exc.status_code
|
||||
error_message = str(exc.detail)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=status_code,
|
||||
content={"detail": error_message, "error_code": error_code},
|
||||
)
|
||||
|
||||
|
||||
async def generic_exception_handler(request: Request, exc: Exception) -> JSONResponse:
|
||||
"""
|
||||
Handle generic exceptions and return formatted error responses.
|
||||
@@ -89,7 +56,12 @@ def setup_exception_handlers(app: FastAPI) -> None:
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
app.add_exception_handler(HTTPException, http_exception_handler)
|
||||
from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler
|
||||
|
||||
custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse)
|
||||
app.add_exception_handler(
|
||||
HTTPExceptionApi, custom_exception_handler.handle_exception
|
||||
)
|
||||
app.add_exception_handler(Exception, generic_exception_handler)
|
||||
|
||||
|
||||
@@ -101,7 +73,7 @@ def setup_middleware(app: FastAPI) -> None:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
setup_cors_middleware(app)
|
||||
app.add_middleware(MiddlewareModule.RequestTimingMiddleware)
|
||||
app.add_middleware(RequestTimingMiddleware)
|
||||
setup_exception_handlers(app)
|
||||
|
||||
|
||||
@@ -118,4 +90,4 @@ def get_uvicorn_config() -> Dict[str, Any]:
|
||||
"port": 41575,
|
||||
"log_level": "info",
|
||||
"reload": True,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ This module provides functionality to create and configure a FastAPI application
|
||||
- Response class configuration
|
||||
- Security requirements for protected endpoints
|
||||
"""
|
||||
|
||||
from types import ModuleType
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
from fastapi import FastAPI, APIRouter
|
||||
@@ -36,10 +37,7 @@ def setup_security_schema() -> Dict[str, Any]:
|
||||
|
||||
|
||||
def configure_route_security(
|
||||
path: str,
|
||||
method: str,
|
||||
schema: Dict[str, Any],
|
||||
protected_paths: List[str]
|
||||
path: str, method: str, schema: Dict[str, Any], protected_paths: List[str]
|
||||
) -> None:
|
||||
"""
|
||||
Configure security requirements for a specific route.
|
||||
@@ -113,7 +111,7 @@ def create_app(routers: ModuleType) -> FastAPI:
|
||||
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):
|
||||
if any(d.__name__ == "auth_required" for d in route.dependencies):
|
||||
protected_paths.append(route.path)
|
||||
|
||||
# Include routers
|
||||
@@ -142,7 +140,7 @@ def create_app(routers: ModuleType) -> FastAPI:
|
||||
route.path,
|
||||
route.methods.pop().lower(),
|
||||
openapi_schema,
|
||||
protected_paths
|
||||
protected_paths,
|
||||
)
|
||||
|
||||
app.openapi_schema = openapi_schema
|
||||
|
||||
@@ -8,7 +8,7 @@ and a middleware for request timing measurements.
|
||||
from time import perf_counter
|
||||
from typing import Callable, Optional, Dict, Any, Tuple
|
||||
from functools import wraps
|
||||
from fastapi import HTTPException, Request, Response, status
|
||||
from fastapi import Request, Response
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from AllConfigs.Token.config import Auth
|
||||
from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApi
|
||||
@@ -21,7 +21,6 @@ class MiddlewareModule:
|
||||
This class provides:
|
||||
- Token extraction and validation
|
||||
- Authentication decorator for endpoints
|
||||
- Request timing middleware
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
@@ -40,23 +39,15 @@ class MiddlewareModule:
|
||||
"""
|
||||
auth_header = request.headers.get(Auth.ACCESS_TOKEN_TAG)
|
||||
if not auth_header:
|
||||
raise HTTPExceptionApi(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="No authorization header",
|
||||
)
|
||||
raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr")
|
||||
|
||||
try:
|
||||
scheme, token = auth_header.split()
|
||||
if scheme.lower() != "bearer":
|
||||
raise HTTPExceptionApi(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid authentication scheme",
|
||||
)
|
||||
raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr")
|
||||
return scheme, token
|
||||
except ValueError:
|
||||
raise HTTPExceptionApi(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token format"
|
||||
)
|
||||
raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr")
|
||||
|
||||
@staticmethod
|
||||
async def validate_token(token: str) -> Dict[str, Any]:
|
||||
@@ -78,10 +69,7 @@ class MiddlewareModule:
|
||||
# return jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
|
||||
return {"user_id": "test", "role": "user"} # Placeholder
|
||||
except Exception as e:
|
||||
raise HTTPExceptionApi(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail=f"Token validation failed: {str(e)}",
|
||||
)
|
||||
raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr")
|
||||
|
||||
@classmethod
|
||||
def auth_required(cls, func: Callable) -> Callable:
|
||||
@@ -122,58 +110,44 @@ class MiddlewareModule:
|
||||
return await func(request, *args, **kwargs)
|
||||
|
||||
except HTTPExceptionApi:
|
||||
raise
|
||||
raise HTTPExceptionApi(error_code="NOT_AUTHORIZED", lang="tr")
|
||||
except Exception as e:
|
||||
raise HTTPExceptionApi(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail=f"Authentication failed: {str(e)}",
|
||||
)
|
||||
|
||||
raise HTTPExceptionApi(error_code="NOT_AUTHORIZED", lang="tr")
|
||||
return wrapper
|
||||
|
||||
class RequestTimingMiddleware(BaseHTTPMiddleware):
|
||||
|
||||
class RequestTimingMiddleware(BaseHTTPMiddleware):
|
||||
"""
|
||||
Middleware for measuring and logging request timing.
|
||||
Only handles timing, no authentication.
|
||||
"""
|
||||
|
||||
async def dispatch(self, request: Request, call_next: Callable) -> Response:
|
||||
"""
|
||||
Middleware for measuring and logging request timing.
|
||||
Only handles timing, no authentication.
|
||||
Process each request through the middleware.
|
||||
|
||||
Args:
|
||||
request: FastAPI request object
|
||||
call_next: Next middleware in the chain
|
||||
|
||||
Returns:
|
||||
Response: Processed response with timing headers
|
||||
"""
|
||||
start_time = perf_counter()
|
||||
|
||||
async def dispatch(self, request: Request, call_next: Callable) -> Response:
|
||||
"""
|
||||
Process each request through the middleware.
|
||||
# Process the request
|
||||
response = await call_next(request)
|
||||
|
||||
Args:
|
||||
request: FastAPI request object
|
||||
call_next: Next middleware in the chain
|
||||
# Add timing information to response headers
|
||||
end_time = perf_counter()
|
||||
elapsed = (end_time - start_time) * 1000 # Convert to milliseconds
|
||||
|
||||
Returns:
|
||||
Response: Processed response with timing headers
|
||||
"""
|
||||
start_time = perf_counter()
|
||||
response.headers.update(
|
||||
{
|
||||
"request-start": f"{start_time:.6f}",
|
||||
"request-end": f"{end_time:.6f}",
|
||||
"request-duration": f"{elapsed:.2f}ms",
|
||||
}
|
||||
)
|
||||
|
||||
# Process the request
|
||||
response = await call_next(request)
|
||||
|
||||
# Add timing information to response headers
|
||||
self._add_timing_headers(response, start_time)
|
||||
|
||||
return response
|
||||
|
||||
@staticmethod
|
||||
def _add_timing_headers(response: Response, start_time: float) -> None:
|
||||
"""
|
||||
Add request timing information to response headers.
|
||||
|
||||
Args:
|
||||
response: FastAPI response object
|
||||
start_time: Time when request processing started
|
||||
"""
|
||||
end_time = perf_counter()
|
||||
elapsed = (end_time - start_time) * 1000 # Convert to milliseconds
|
||||
|
||||
response.headers.update(
|
||||
{
|
||||
"request-start": f"{start_time:.6f}",
|
||||
"request-end": f"{end_time:.6f}",
|
||||
"request-duration": f"{elapsed:.2f}ms",
|
||||
}
|
||||
)
|
||||
return response
|
||||
|
||||
@@ -173,15 +173,17 @@ class OpenAPISchemaCreator:
|
||||
# Add security schemes
|
||||
if "components" not in openapi_schema:
|
||||
openapi_schema["components"] = {}
|
||||
|
||||
openapi_schema["components"]["securitySchemes"] = self._create_security_schemes()
|
||||
|
||||
openapi_schema["components"][
|
||||
"securitySchemes"
|
||||
] = self._create_security_schemes()
|
||||
|
||||
# Configure route security and responses
|
||||
for route in self.app.routes:
|
||||
if isinstance(route, APIRoute) and route.include_in_schema:
|
||||
path = str(route.path)
|
||||
methods = [method.lower() for method in route.methods]
|
||||
|
||||
|
||||
for method in methods:
|
||||
self.configure_route_security(path, method, openapi_schema)
|
||||
|
||||
@@ -206,4 +208,4 @@ def create_openapi_schema(app: FastAPI) -> Dict[str, Any]:
|
||||
Dict[str, Any]: Complete OpenAPI schema
|
||||
"""
|
||||
creator = OpenAPISchemaCreator(app)
|
||||
return creator.create_schema()
|
||||
return creator.create_schema()
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from .base_router import test_route
|
||||
|
||||
__all__ = [
|
||||
"test_route"
|
||||
]
|
||||
__all__ = ["test_route"]
|
||||
|
||||
@@ -7,16 +7,16 @@ 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"}
|
||||
|
||||
# Initialize and include test routes
|
||||
def init_test_routes():
|
||||
return test_route
|
||||
|
||||
@@ -19,7 +19,10 @@ 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
|
||||
COPY ApiLibrary /app/ApiLibrary
|
||||
COPY ApiValidations /app/ApiValidations
|
||||
COPY AllConfigs /app/AllConfigs
|
||||
|
||||
@@ -6,32 +6,32 @@ This repository contains multiple microservices that can be run using Docker Com
|
||||
For regular development when dependencies haven't changed:
|
||||
```bash
|
||||
# Build and run Auth Service
|
||||
docker compose -f ../docker-compose-services.yml up auth-service
|
||||
docker compose -f docker-compose-services.yml up auth-service
|
||||
|
||||
# Build and run Event Service
|
||||
docker compose -f ../docker-compose-services.yml up event-service
|
||||
docker compose -f docker-compose-services.yml up event-service
|
||||
|
||||
# Build and run Validation Service
|
||||
docker compose -f ../docker-compose-services.yml up validation-service
|
||||
docker compose -f docker-compose-services.yml up validation-service
|
||||
|
||||
# Build and run all services
|
||||
docker compose -f ../docker-compose-services.yml up
|
||||
docker compose -f docker-compose-services.yml up
|
||||
```
|
||||
|
||||
## Clean Build (No Cache)
|
||||
Use these commands when changing Dockerfile or dependencies:
|
||||
```bash
|
||||
# Auth Service
|
||||
docker compose -f ../docker-compose-services.yml build --no-cache auth-service && docker compose -f ../docker-compose-services.yml up auth-service
|
||||
docker compose -f docker-compose-services.yml build --no-cache auth-service && docker compose -f docker-compose-services.yml up auth-service
|
||||
|
||||
# Event Service
|
||||
docker compose -f ../docker-compose-services.yml build --no-cache event-service && docker compose -f ../docker-compose-services.yml up event-service
|
||||
docker compose -f docker-compose-services.yml build --no-cache event-service && docker compose -f docker-compose-services.yml up event-service
|
||||
|
||||
# Validation Service
|
||||
docker compose -f ../docker-compose-services.yml build --no-cache validation-service && docker compose -f ../docker-compose-services.yml up validation-service
|
||||
docker compose -f docker-compose-services.yml build --no-cache validation-service && docker compose -f docker-compose-services.yml up validation-service
|
||||
|
||||
# All Services
|
||||
docker compose -f ../docker-compose-services.yml build --no-cache && docker compose -f ../docker-compose-services.yml up
|
||||
docker compose -f docker-compose-services.yml build --no-cache && docker compose -f docker-compose-services.yml up
|
||||
```
|
||||
|
||||
## Service Ports
|
||||
@@ -51,9 +51,9 @@ docker compose -f ../docker-compose-services.yml build --no-cache && docker comp
|
||||
- For faster development iterations
|
||||
- Run in detached mode:
|
||||
```bash
|
||||
docker compose -f ../docker-compose-services.yml up -d auth-service
|
||||
docker compose -f docker-compose-services.yml up -d auth-service
|
||||
```
|
||||
- Stop services:
|
||||
```bash
|
||||
docker compose -f ../docker-compose-services.yml down
|
||||
docker compose -f docker-compose-services.yml down
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user