latest version of apis event and cahce ablitites added
This commit is contained in:
40
DockerApiServices/EventServiceApi/Dockerfile
Normal file
40
DockerApiServices/EventServiceApi/Dockerfile
Normal file
@@ -0,0 +1,40 @@
|
||||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies and Poetry
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& pip install --no-cache-dir poetry
|
||||
|
||||
# Copy Poetry configuration
|
||||
COPY DockerApiServices/pyproject.toml ./pyproject.toml
|
||||
|
||||
# Configure Poetry and install dependencies with optimizations
|
||||
RUN poetry config virtualenvs.create false \
|
||||
&& poetry install --no-interaction --no-ansi --no-root --only main \
|
||||
&& pip cache purge \
|
||||
&& rm -rf ~/.cache/pypoetry
|
||||
|
||||
# Copy application code
|
||||
COPY DockerApiServices/EventServiceApi /app
|
||||
|
||||
# Copy application code
|
||||
COPY ApiLayers /app/ApiLayers
|
||||
COPY Services /app/Services
|
||||
|
||||
# Events
|
||||
COPY Events/Engine /app/Events/Engine
|
||||
COPY Events/base_request_model.py /app/Events/base_request_model.py
|
||||
COPY Events/AllEvents/events /app/Events/AllEvents/events
|
||||
COPY DockerApiServices/EventServiceApi/events_file.py /app/Events/AllEvents/events_file.py
|
||||
|
||||
# Set Python path to include app directory
|
||||
ENV PYTHONPATH=/app \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
# Run the application using the configured uvicorn server
|
||||
CMD ["poetry", "run", "python", "app.py"]
|
||||
27
DockerApiServices/EventServiceApi/app.py
Normal file
27
DockerApiServices/EventServiceApi/app.py
Normal file
@@ -0,0 +1,27 @@
|
||||
"""
|
||||
FastAPI Application Entry Point
|
||||
|
||||
This module initializes and configures the FastAPI application with:
|
||||
- CORS middleware for cross-origin requests
|
||||
- Request timing middleware for performance monitoring
|
||||
- Custom exception handlers for consistent error responses
|
||||
- Prometheus instrumentation for metrics
|
||||
- API routers for endpoint organization
|
||||
"""
|
||||
|
||||
import uvicorn
|
||||
|
||||
from prometheus_fastapi_instrumentator import Instrumentator
|
||||
from app_handler import setup_middleware
|
||||
from create_file import create_app
|
||||
from config import ApiConfig
|
||||
|
||||
|
||||
app = create_app() # Initialize FastAPI application
|
||||
Instrumentator().instrument(app=app).expose(app=app) # Setup Prometheus metrics
|
||||
setup_middleware(app) # Configure middleware and exception handlers
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the application with Uvicorn
|
||||
uvicorn.Server(uvicorn.Config(**ApiConfig.as_dict())).run()
|
||||
82
DockerApiServices/EventServiceApi/app_handler.py
Normal file
82
DockerApiServices/EventServiceApi/app_handler.py
Normal file
@@ -0,0 +1,82 @@
|
||||
"""
|
||||
FastAPI Application Handler Module
|
||||
|
||||
This module contains all the handler functions for configuring and setting up the FastAPI application:
|
||||
- CORS middleware configuration
|
||||
- Exception handlers setup
|
||||
- Uvicorn server configuration
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI, Request, status
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
from ApiLayers.Middleware.auth_middleware import (
|
||||
RequestTimingMiddleware,
|
||||
LoggerTimingMiddleware,
|
||||
)
|
||||
|
||||
|
||||
def setup_cors_middleware(app: FastAPI) -> None:
|
||||
"""
|
||||
Configure CORS middleware for the application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
async def generic_exception_handler(request: Request, exc: Exception) -> JSONResponse:
|
||||
"""
|
||||
Handle generic exceptions and return formatted error responses.
|
||||
|
||||
Args:
|
||||
request: FastAPI request object
|
||||
exc: Exception instance
|
||||
|
||||
Returns:
|
||||
JSONResponse: Formatted error response
|
||||
"""
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content={"detail": "Internal server error", "error_code": "INTERNAL_ERROR"},
|
||||
)
|
||||
|
||||
|
||||
def setup_exception_handlers(app: FastAPI) -> None:
|
||||
"""
|
||||
Configure custom exception handlers for the application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
from ApiLayers.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)
|
||||
|
||||
|
||||
def setup_middleware(app: FastAPI) -> None:
|
||||
"""
|
||||
Configure all middleware for the application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
setup_cors_middleware(app)
|
||||
app.add_middleware(RequestTimingMiddleware)
|
||||
app.add_middleware(LoggerTimingMiddleware)
|
||||
setup_exception_handlers(app)
|
||||
59
DockerApiServices/EventServiceApi/config.py
Normal file
59
DockerApiServices/EventServiceApi/config.py
Normal file
@@ -0,0 +1,59 @@
|
||||
class DefaultApiConfig:
|
||||
app: str
|
||||
host: str
|
||||
port: int
|
||||
log_level: str
|
||||
reload: bool
|
||||
|
||||
@classmethod
|
||||
def as_dict(cls):
|
||||
return {
|
||||
"app": cls.app,
|
||||
"host": cls.host,
|
||||
"port": int(cls.port),
|
||||
"log_level": cls.log_level,
|
||||
"reload": bool(cls.reload),
|
||||
}
|
||||
|
||||
|
||||
class ApiStatic:
|
||||
PLACEHOLDER = "https://s.tmimgcdn.com/scr/800x500/276800/building-home-nature-logo-vector-template-3_276851-original.jpg"
|
||||
FORGOT_LINK = "https://www.evyos.com.tr/password/create?tokenUrl="
|
||||
BLACKLIST_LINK = "https://www.evyos.com.tr/support/unknown-login-notice/"
|
||||
APP_DIR = "/home/berkay/git-evyos/api-managment-backend/"
|
||||
|
||||
@classmethod
|
||||
def forgot_link(cls, forgot_key):
|
||||
return cls.FORGOT_LINK + forgot_key
|
||||
|
||||
@classmethod
|
||||
def blacklist_login(cls, record_id):
|
||||
return cls.BLACKLIST_LINK + record_id
|
||||
|
||||
|
||||
class ApiConfig(DefaultApiConfig):
|
||||
# Api configuration
|
||||
APP_NAME = "evyos-event-api-gateway"
|
||||
TITLE = "WAG API Event Api Gateway"
|
||||
DESCRIPTION = (
|
||||
"This api is serves as web event api gateway only to evyos web services."
|
||||
)
|
||||
APP_URL = "https://www.event.eys.gen.tr"
|
||||
|
||||
# Uvicorn server configuration
|
||||
app = "app:app"
|
||||
host = "0.0.0.0"
|
||||
port = 41576
|
||||
log_level = "info"
|
||||
reload = True
|
||||
|
||||
|
||||
class MainConfig:
|
||||
# Date and Time Configuration
|
||||
DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss Z"
|
||||
DATETIME_FORMAT_JS = "YYYY-MM-DD HH:mm:ss +0"
|
||||
|
||||
# Timezone Configuration
|
||||
DEFAULT_TIMEZONE = "GMT+3" # Default timezone for the application
|
||||
SYSTEM_TIMEZONE = "GMT+0" # System timezone (used for internal operations)
|
||||
SUPPORTED_TIMEZONES = ["GMT+0", "GMT+3"] # List of supported timezones
|
||||
48
DockerApiServices/EventServiceApi/create_file.py
Normal file
48
DockerApiServices/EventServiceApi/create_file.py
Normal file
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
FastAPI Application Factory Module
|
||||
|
||||
This module provides functionality to create and configure a FastAPI application with:
|
||||
- Custom OpenAPI schema configuration
|
||||
- Security scheme configuration for Bearer authentication
|
||||
- Automatic router registration
|
||||
- Response class configuration
|
||||
- Security requirements for protected endpoints
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
|
||||
from config import ApiConfig
|
||||
from create_routes import get_all_routers
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
"""
|
||||
Create and configure a FastAPI application with dynamic route creation.
|
||||
|
||||
Returns:
|
||||
FastAPI: Configured FastAPI application instance
|
||||
"""
|
||||
|
||||
from open_api_creator import create_openapi_schema
|
||||
|
||||
app = FastAPI(
|
||||
title=ApiConfig.TITLE,
|
||||
description=ApiConfig.DESCRIPTION,
|
||||
default_response_class=JSONResponse,
|
||||
) # Initialize FastAPI app
|
||||
|
||||
@app.get("/", include_in_schema=False, summary=str(ApiConfig.DESCRIPTION))
|
||||
def home() -> RedirectResponse:
|
||||
"""Redirect root path to API documentation."""
|
||||
return RedirectResponse(url="/docs")
|
||||
|
||||
# Get all routers and protected routes using the dynamic route creation
|
||||
prepare_routing = get_all_routers()
|
||||
|
||||
# Include all routers
|
||||
for router in prepare_routing.routers:
|
||||
app.include_router(router)
|
||||
|
||||
app.openapi = lambda app=app: create_openapi_schema(app)
|
||||
return app
|
||||
42
DockerApiServices/EventServiceApi/create_routes.py
Normal file
42
DockerApiServices/EventServiceApi/create_routes.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""
|
||||
Route configuration and factory module.
|
||||
Handles dynamic route creation based on configurations.
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from Events.Engine.set_defaults.run import get_cluster_controller_group
|
||||
from Events.Engine.set_defaults.setClusters import (
|
||||
PrepareRouting,
|
||||
SetItems2Redis,
|
||||
PrepareEvents,
|
||||
)
|
||||
|
||||
|
||||
routers: Optional[PrepareRouting] = None
|
||||
|
||||
|
||||
def get_all_routers() -> PrepareRouting:
|
||||
"""
|
||||
Get all routers and protected routes from route configurations.
|
||||
|
||||
Returns:
|
||||
tuple: PrepareRouting
|
||||
"""
|
||||
global routers
|
||||
if routers:
|
||||
return routers
|
||||
|
||||
cluster_list = get_cluster_controller_group()
|
||||
routers = PrepareRouting(cluster_controller_group=cluster_list)
|
||||
return routers
|
||||
|
||||
|
||||
# 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}
|
||||
11
DockerApiServices/EventServiceApi/events_file.py
Normal file
11
DockerApiServices/EventServiceApi/events_file.py
Normal file
@@ -0,0 +1,11 @@
|
||||
import Events.AllEvents.events as events_events
|
||||
|
||||
|
||||
events_list = (events_events,)
|
||||
|
||||
|
||||
def retrieve_cluster_by_name(cluster_name: str):
|
||||
for module in events_list:
|
||||
if hasattr(module, cluster_name):
|
||||
return getattr(module, cluster_name, None)
|
||||
return
|
||||
256
DockerApiServices/EventServiceApi/open_api_creator.py
Normal file
256
DockerApiServices/EventServiceApi/open_api_creator.py
Normal file
@@ -0,0 +1,256 @@
|
||||
"""
|
||||
OpenAPI Schema Creator Module
|
||||
|
||||
This module provides functionality to create and customize OpenAPI documentation:
|
||||
- Custom security schemes (Bearer Auth, API Key)
|
||||
- Response schemas and examples
|
||||
- Tag management and descriptions
|
||||
- Error responses and validation
|
||||
- Custom documentation extensions
|
||||
"""
|
||||
|
||||
from typing import Any, Dict
|
||||
from fastapi import FastAPI
|
||||
from fastapi.routing import APIRoute
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
|
||||
from create_routes import get_all_routers
|
||||
from config import ApiConfig
|
||||
|
||||
|
||||
class OpenAPISchemaCreator:
|
||||
"""
|
||||
OpenAPI schema creator and customizer for FastAPI applications.
|
||||
"""
|
||||
|
||||
def __init__(self, app: FastAPI):
|
||||
"""
|
||||
Initialize the OpenAPI schema creator.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
self.app = app
|
||||
self.cluster = get_all_routers()
|
||||
self.safe_endpoint_list = (
|
||||
self.cluster.safe_endpoints
|
||||
if hasattr(self.cluster, "safe_endpoints")
|
||||
else []
|
||||
)
|
||||
|
||||
def _create_security_schemes(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Create security scheme definitions.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Security scheme configurations
|
||||
"""
|
||||
from ApiLayers.AllConfigs.Token.config import Auth
|
||||
|
||||
return {
|
||||
"BearerAuth": {
|
||||
"type": "apiKey",
|
||||
"in": "header",
|
||||
"name": Auth.ACCESS_TOKEN_TAG,
|
||||
"description": "Enter: **'Bearer <JWT>'**, where JWT is the access token",
|
||||
}
|
||||
}
|
||||
|
||||
def _create_common_responses(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Create common response schemas.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Common response configurations
|
||||
"""
|
||||
return {
|
||||
"401": {
|
||||
"description": "Unauthorized - Invalid or missing credentials",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/HTTPValidationError"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden - Insufficient permissions",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/HTTPValidationError"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/HTTPValidationError"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {"type": "string"},
|
||||
"error_code": {"type": "string"},
|
||||
},
|
||||
},
|
||||
"example": {
|
||||
"detail": "Internal server error occurred",
|
||||
"error_code": "INTERNAL_ERROR",
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def _process_request_body(
|
||||
self, path: str, method: str, schema: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
Process request body to include examples from model config.
|
||||
|
||||
Args:
|
||||
path: Route path
|
||||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
"""
|
||||
try:
|
||||
route_schema = schema["paths"][path][method]
|
||||
if "requestBody" in route_schema:
|
||||
request_body = route_schema["requestBody"]
|
||||
if "content" in request_body:
|
||||
content = request_body["content"]
|
||||
if "application/json" in content:
|
||||
json_content = content["application/json"]
|
||||
if (
|
||||
"schema" in json_content
|
||||
and "$ref" in json_content["schema"]
|
||||
):
|
||||
ref = json_content["schema"]["$ref"]
|
||||
model_name = ref.split("/")[-1]
|
||||
if model_name in schema["components"]["schemas"]:
|
||||
model_schema = schema["components"]["schemas"][
|
||||
model_name
|
||||
]
|
||||
if "example" in model_schema:
|
||||
json_content["example"] = model_schema["example"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def _process_response_examples(
|
||||
self, path: str, method: str, schema: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
Process response body to include examples from model config.
|
||||
|
||||
Args:
|
||||
path: Route path
|
||||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
"""
|
||||
try:
|
||||
route_schema = schema["paths"][path][method]
|
||||
if "responses" in route_schema:
|
||||
responses = route_schema["responses"]
|
||||
if "200" in responses:
|
||||
response = responses["200"]
|
||||
if "content" in response:
|
||||
content = response["content"]
|
||||
if "application/json" in content:
|
||||
json_content = content["application/json"]
|
||||
if (
|
||||
"schema" in json_content
|
||||
and "$ref" in json_content["schema"]
|
||||
):
|
||||
ref = json_content["schema"]["$ref"]
|
||||
model_name = ref.split("/")[-1]
|
||||
if model_name in schema["components"]["schemas"]:
|
||||
model_schema = schema["components"]["schemas"][
|
||||
model_name
|
||||
]
|
||||
if "example" in model_schema:
|
||||
json_content["example"] = model_schema[
|
||||
"example"
|
||||
]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def configure_route_security(
|
||||
self, path: str, method: str, schema: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
Configure security requirements for a specific route.
|
||||
|
||||
Args:
|
||||
path: Route path
|
||||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
"""
|
||||
if not schema.get("paths", {}).get(path, {}).get(method):
|
||||
return
|
||||
|
||||
# Check if endpoint is in safe list
|
||||
endpoint_path = f"{path}:{method}"
|
||||
if endpoint_path not in [
|
||||
f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list
|
||||
]:
|
||||
if "security" not in schema["paths"][path][method]:
|
||||
schema["paths"][path][method]["security"] = []
|
||||
schema["paths"][path][method]["security"].append({"BearerAuth": []})
|
||||
|
||||
def create_schema(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Create the complete OpenAPI schema.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Complete OpenAPI schema
|
||||
"""
|
||||
openapi_schema = get_openapi(
|
||||
title=ApiConfig.TITLE,
|
||||
description=ApiConfig.DESCRIPTION,
|
||||
version="1.1.1",
|
||||
routes=self.app.routes,
|
||||
)
|
||||
|
||||
# Add security schemes
|
||||
if "components" not in openapi_schema:
|
||||
openapi_schema["components"] = {}
|
||||
|
||||
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)
|
||||
|
||||
# Add custom documentation extensions
|
||||
openapi_schema["x-documentation"] = {
|
||||
"postman_collection": "/docs/postman",
|
||||
"swagger_ui": "/docs",
|
||||
"redoc": "/redoc",
|
||||
}
|
||||
return openapi_schema
|
||||
|
||||
|
||||
def create_openapi_schema(app: FastAPI) -> Dict[str, Any]:
|
||||
"""
|
||||
Create OpenAPI schema for a FastAPI application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Complete OpenAPI schema
|
||||
"""
|
||||
creator = OpenAPISchemaCreator(app)
|
||||
return creator.create_schema()
|
||||
Reference in New Issue
Block a user