allow all origins for cors
This commit is contained in:
parent
8db0013f26
commit
6a5649a49c
@ -1,16 +1,38 @@
|
|||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
# Get the project root directory
|
# Get the project root directory (using an absolute path)
|
||||||
PROJECT_ROOT = Path(__file__).parent.parent.parent.absolute()
|
PROJECT_ROOT = Path(__file__).parent.parent.parent.absolute()
|
||||||
|
|
||||||
# Create the directory for the SQLite database if it doesn't exist
|
try:
|
||||||
DB_DIR = PROJECT_ROOT / "app" / "storage" / "db"
|
# Create the directory for the SQLite database if it doesn't exist
|
||||||
DB_DIR.mkdir(parents=True, exist_ok=True)
|
DB_DIR = PROJECT_ROOT / "app" / "storage" / "db"
|
||||||
|
DB_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
SQLALCHEMY_DATABASE_URL = f"sqlite:///{DB_DIR}/db.sqlite"
|
|
||||||
|
# Ensure the directory is writable
|
||||||
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
|
test_file = DB_DIR / ".test_write_access"
|
||||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
with open(test_file, "w") as f:
|
||||||
|
f.write("test")
|
||||||
|
os.remove(test_file)
|
||||||
|
|
||||||
|
# Use a simplified database path for better compatibility
|
||||||
|
DB_FILE = DB_DIR / "db.sqlite"
|
||||||
|
SQLALCHEMY_DATABASE_URL = f"sqlite:///{DB_FILE}"
|
||||||
|
|
||||||
|
print(f"Database URL: {SQLALCHEMY_DATABASE_URL}")
|
||||||
|
print(f"Database directory: {DB_DIR}")
|
||||||
|
|
||||||
|
engine = create_engine(
|
||||||
|
SQLALCHEMY_DATABASE_URL,
|
||||||
|
connect_args={"check_same_thread": False},
|
||||||
|
# Echo SQL for debugging (remove in production)
|
||||||
|
echo=False,
|
||||||
|
)
|
||||||
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error setting up database connection: {e}")
|
||||||
|
raise
|
||||||
|
164
debug_app.py
Executable file
164
debug_app.py
Executable file
@ -0,0 +1,164 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
Debug script to diagnose FastAPI application startup issues.
|
||||||
|
This script checks for common issues that might prevent the app from starting.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Configure the Python path
|
||||||
|
current_dir = Path(__file__).parent.absolute()
|
||||||
|
sys.path.insert(0, str(current_dir))
|
||||||
|
|
||||||
|
def check_import(module_name):
|
||||||
|
"""Try to import a module and report any errors."""
|
||||||
|
try:
|
||||||
|
importlib.import_module(module_name)
|
||||||
|
print(f"✅ Successfully imported {module_name}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Failed to import {module_name}: {e}")
|
||||||
|
print("Traceback:")
|
||||||
|
traceback.print_exc()
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_file_exists(file_path):
|
||||||
|
"""Check if a file exists."""
|
||||||
|
path = Path(file_path)
|
||||||
|
if path.exists():
|
||||||
|
print(f"✅ File exists: {file_path}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"❌ File does not exist: {file_path}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_directory_exists(dir_path):
|
||||||
|
"""Check if a directory exists and try to create it if it doesn't."""
|
||||||
|
path = Path(dir_path)
|
||||||
|
if path.exists() and path.is_dir():
|
||||||
|
print(f"✅ Directory exists: {dir_path}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"❌ Directory does not exist: {dir_path}")
|
||||||
|
try:
|
||||||
|
path.mkdir(parents=True, exist_ok=True)
|
||||||
|
print(f"✅ Created directory: {dir_path}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Failed to create directory {dir_path}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_directory_writable(dir_path):
|
||||||
|
"""Check if a directory is writable."""
|
||||||
|
path = Path(dir_path)
|
||||||
|
if not path.exists():
|
||||||
|
print(f"❌ Directory does not exist: {dir_path}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
test_file = path / "write_test_file.txt"
|
||||||
|
with open(test_file, "w") as f:
|
||||||
|
f.write("Test write access")
|
||||||
|
test_file.unlink() # Remove the test file
|
||||||
|
print(f"✅ Directory is writable: {dir_path}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Directory is not writable: {dir_path}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_database():
|
||||||
|
"""Check database configuration and connectivity."""
|
||||||
|
try:
|
||||||
|
from app.db.session import SQLALCHEMY_DATABASE_URL, engine
|
||||||
|
|
||||||
|
print(f"✅ Database URL: {SQLALCHEMY_DATABASE_URL}")
|
||||||
|
|
||||||
|
# Check the database directory
|
||||||
|
db_path = Path(SQLALCHEMY_DATABASE_URL.replace("sqlite:///", ""))
|
||||||
|
db_dir = db_path.parent
|
||||||
|
|
||||||
|
check_directory_exists(db_dir)
|
||||||
|
check_directory_writable(db_dir)
|
||||||
|
|
||||||
|
# Try to connect to the database
|
||||||
|
try:
|
||||||
|
conn = engine.connect()
|
||||||
|
conn.close()
|
||||||
|
print("✅ Successfully connected to the database")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Failed to connect to the database: {e}")
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error checking database: {e}")
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def check_app_startup():
|
||||||
|
"""Try to import the FastAPI app and check for errors."""
|
||||||
|
try:
|
||||||
|
# First check if we can import FastAPI
|
||||||
|
import fastapi
|
||||||
|
print(f"✅ FastAPI version: {fastapi.__version__}")
|
||||||
|
|
||||||
|
# Then try to import the app
|
||||||
|
from main import app
|
||||||
|
print("✅ Successfully imported the FastAPI app")
|
||||||
|
|
||||||
|
# Check app configuration
|
||||||
|
print(f"✅ App title: {app.title}")
|
||||||
|
print(f"✅ App version: {app.version}")
|
||||||
|
print(f"✅ OpenAPI URL: {app.openapi_url}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error during app startup: {e}")
|
||||||
|
traceback.print_exc()
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run all checks."""
|
||||||
|
print("\n=== Python Environment ===")
|
||||||
|
print(f"Python version: {sys.version}")
|
||||||
|
print(f"Python executable: {sys.executable}")
|
||||||
|
print(f"Current directory: {os.getcwd()}")
|
||||||
|
|
||||||
|
print("\n=== Checking Critical Imports ===")
|
||||||
|
check_import("fastapi")
|
||||||
|
check_import("uvicorn")
|
||||||
|
check_import("sqlalchemy")
|
||||||
|
check_import("pydantic")
|
||||||
|
check_import("alembic")
|
||||||
|
|
||||||
|
print("\n=== Checking App Imports ===")
|
||||||
|
check_import("app")
|
||||||
|
check_import("app.api")
|
||||||
|
check_import("app.core")
|
||||||
|
check_import("app.db")
|
||||||
|
check_import("app.models")
|
||||||
|
check_import("app.schemas")
|
||||||
|
|
||||||
|
print("\n=== Checking Critical Files ===")
|
||||||
|
check_file_exists("main.py")
|
||||||
|
check_file_exists("app/core/config.py")
|
||||||
|
check_file_exists("app/db/session.py")
|
||||||
|
|
||||||
|
print("\n=== Checking Storage Directories ===")
|
||||||
|
project_root = Path(__file__).parent.absolute()
|
||||||
|
app_storage_dir = project_root / "app" / "storage" / "db"
|
||||||
|
check_directory_exists(app_storage_dir)
|
||||||
|
check_directory_writable(app_storage_dir)
|
||||||
|
|
||||||
|
print("\n=== Checking Database ===")
|
||||||
|
check_database()
|
||||||
|
|
||||||
|
print("\n=== Testing App Startup ===")
|
||||||
|
check_app_startup()
|
||||||
|
|
||||||
|
print("\n=== Debug Complete ===")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
155
main.py
155
main.py
@ -1,100 +1,153 @@
|
|||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from app.api.v1.api import api_router
|
# Print current directory and Python path for debugging
|
||||||
from app.core.config import settings
|
print(f"Current directory: {os.getcwd()}")
|
||||||
from app.core.logging import setup_logging
|
print(f"Python path: {sys.path}")
|
||||||
|
|
||||||
|
# Ensure app is in Python path
|
||||||
|
PROJECT_ROOT = Path(__file__).parent.absolute()
|
||||||
|
if str(PROJECT_ROOT) not in sys.path:
|
||||||
|
sys.path.insert(0, str(PROJECT_ROOT))
|
||||||
|
print(f"Added {PROJECT_ROOT} to Python path")
|
||||||
|
|
||||||
|
try:
|
||||||
|
from app.api.v1.api import api_router
|
||||||
|
from app.core.config import settings
|
||||||
|
from app.core.logging import setup_logging
|
||||||
|
print("Successfully imported application modules")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error importing application modules: {e}")
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
# Simplified lifespan to prevent startup errors
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
"""
|
"""
|
||||||
Context manager for FastAPI app lifespan events.
|
Context manager for FastAPI app lifespan events.
|
||||||
|
Simplified to prevent startup errors.
|
||||||
Startup and shutdown events run on application startup and shutdown.
|
|
||||||
"""
|
"""
|
||||||
# Setup logging on startup
|
print("Starting application lifespan...")
|
||||||
try:
|
# Don't use complex startup logic that might fail
|
||||||
setup_logging()
|
yield
|
||||||
logger.info(f"Starting up {settings.PROJECT_NAME}")
|
print("Application shutdown...")
|
||||||
|
|
||||||
# Verify imports and application setup
|
|
||||||
logger.info("Application initialized successfully")
|
|
||||||
|
|
||||||
yield # Run the application
|
|
||||||
|
|
||||||
# Clean up resources on shutdown
|
|
||||||
logger.info(f"Shutting down {settings.PROJECT_NAME}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error during application startup: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
|
# Create the FastAPI application with a simplified configuration
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title=settings.PROJECT_NAME,
|
title=settings.PROJECT_NAME,
|
||||||
openapi_url="/openapi.json",
|
openapi_url="/openapi.json",
|
||||||
version=settings.VERSION,
|
version=settings.VERSION,
|
||||||
lifespan=lifespan,
|
|
||||||
docs_url="/docs",
|
docs_url="/docs",
|
||||||
redoc_url="/redoc",
|
redoc_url="/redoc",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Set up basic logging
|
||||||
|
try:
|
||||||
|
setup_logging()
|
||||||
|
logger.info(f"Starting up {settings.PROJECT_NAME}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error setting up logging: {e}")
|
||||||
|
# Continue without logging rather than failing startup
|
||||||
|
|
||||||
# Add middleware
|
|
||||||
|
# Simple process time middleware with error handling
|
||||||
@app.middleware("http")
|
@app.middleware("http")
|
||||||
async def add_process_time_header(request: Request, call_next):
|
async def add_process_time_header(request: Request, call_next):
|
||||||
"""
|
"""
|
||||||
Middleware to add X-Process-Time header to response.
|
Middleware to add X-Process-Time header to response.
|
||||||
|
Includes error handling.
|
||||||
"""
|
"""
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
response = await call_next(request)
|
try:
|
||||||
process_time = time.time() - start_time
|
response = await call_next(request)
|
||||||
response.headers["X-Process-Time"] = str(process_time)
|
process_time = time.time() - start_time
|
||||||
|
response.headers["X-Process-Time"] = str(process_time)
|
||||||
|
|
||||||
|
# Log request details (using print as a fallback if logger fails)
|
||||||
|
try:
|
||||||
|
logger.info(
|
||||||
|
f"{request.method} {request.url.path} "
|
||||||
|
f"Status: {response.status_code} "
|
||||||
|
f"Process Time: {process_time:.4f}s"
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
print(
|
||||||
|
f"{request.method} {request.url.path} "
|
||||||
|
f"Status: {response.status_code} "
|
||||||
|
f"Process Time: {process_time:.4f}s"
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
except Exception as e:
|
||||||
|
process_time = time.time() - start_time
|
||||||
|
print(f"Error processing request {request.url.path}: {e}")
|
||||||
|
return JSONResponse(
|
||||||
|
status_code=500,
|
||||||
|
content={"detail": "Internal server error"},
|
||||||
|
)
|
||||||
|
|
||||||
# Log request details
|
|
||||||
logger.info(
|
# Simple CORS middleware
|
||||||
f"{request.method} {request.url.path} "
|
try:
|
||||||
f"Status: {response.status_code} "
|
# Set all CORS enabled origins
|
||||||
f"Process Time: {process_time:.4f}s"
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=["*"], # Allow all origins
|
||||||
|
allow_credentials=True,
|
||||||
|
allow_methods=["*"], # Allow all methods
|
||||||
|
allow_headers=["*"], # Allow all headers
|
||||||
)
|
)
|
||||||
|
print("CORS middleware added")
|
||||||
return response
|
except Exception as e:
|
||||||
|
print(f"Error adding CORS middleware: {e}")
|
||||||
|
|
||||||
|
|
||||||
# Set all CORS enabled origins
|
# Try to include API router
|
||||||
app.add_middleware(
|
try:
|
||||||
CORSMiddleware,
|
app.include_router(api_router, prefix=settings.API_V1_STR)
|
||||||
allow_origins=["*"], # Allow all origins
|
print(f"API router added with prefix: {settings.API_V1_STR}")
|
||||||
allow_credentials=True,
|
except Exception as e:
|
||||||
allow_methods=["*"], # Allow all methods
|
print(f"Error including API router: {e}")
|
||||||
allow_headers=["*"], # Allow all headers
|
# Add a fallback router if the main one fails
|
||||||
)
|
fallback_router = FastAPI()
|
||||||
|
app.include_router(fallback_router)
|
||||||
app.include_router(api_router, prefix=settings.API_V1_STR)
|
|
||||||
|
|
||||||
|
|
||||||
|
# Basic health check endpoint
|
||||||
@app.get("/health", tags=["health"])
|
@app.get("/health", tags=["health"])
|
||||||
async def health_check():
|
async def health_check():
|
||||||
"""
|
"""
|
||||||
Health check endpoint to verify the API is running.
|
Health check endpoint to verify the API is running.
|
||||||
"""
|
"""
|
||||||
logger.debug("Health check endpoint called")
|
try:
|
||||||
|
logger.debug("Health check endpoint called")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
return {"status": "healthy"}
|
return {"status": "healthy"}
|
||||||
|
|
||||||
|
|
||||||
|
# Simple root endpoint
|
||||||
|
@app.get("/", tags=["root"])
|
||||||
|
async def root():
|
||||||
|
"""
|
||||||
|
Root endpoint for quick testing.
|
||||||
|
"""
|
||||||
|
return {"message": "Manga Inventory API is running"}
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
# Simplified server startup
|
||||||
logger.info("Starting server with uvicorn...")
|
print("Starting server with uvicorn...")
|
||||||
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to start server: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
sys.exit(1)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user