79 lines
2.6 KiB
Python

from fastapi import FastAPI, Depends, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.exceptions import RequestValidationError
import uvicorn
from pathlib import Path
from sqlalchemy.orm import Session
import logging
import time
from app.database import get_db, Base, engine
from app.api.routers import assets, exchanges, markets, rates, health
from app.exceptions import (
CoinCapAPIException,
validation_exception_handler,
http_exception_handler,
coincap_api_exception_handler,
general_exception_handler
)
from app.utils.logging import setup_logging
from starlette.exceptions import HTTPException as StarletteHTTPException
# Setup logging
setup_logging(log_level="INFO")
logger = logging.getLogger(__name__)
# Create the FastAPI app
app = FastAPI(
title="Cryptocurrency Data Service",
description="Backend service for cryptocurrency data from CoinCap API",
version="0.1.0",
)
# Register exception handlers
app.add_exception_handler(RequestValidationError, validation_exception_handler)
app.add_exception_handler(StarletteHTTPException, http_exception_handler)
app.add_exception_handler(CoinCapAPIException, coincap_api_exception_handler)
app.add_exception_handler(Exception, general_exception_handler)
# CORS middleware configuration
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Request timing middleware
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
logger.debug(f"Request to {request.url.path} processed in {process_time:.4f} seconds")
return response
# Include routers
app.include_router(health.router)
app.include_router(assets.router, prefix="/api")
app.include_router(exchanges.router, prefix="/api")
app.include_router(markets.router, prefix="/api")
app.include_router(rates.router, prefix="/api")
# Startup event
@app.on_event("startup")
async def startup_event():
logger.info("Starting up Cryptocurrency Data Service")
# Create database tables at startup
# In production, you should use Alembic migrations instead
# Base.metadata.create_all(bind=engine)
# Shutdown event
@app.on_event("shutdown")
async def shutdown_event():
logger.info("Shutting down Cryptocurrency Data Service")
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)