main.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. from fastapi import FastAPI, HTTPException, Request
  2. from fastapi.staticfiles import StaticFiles
  3. from fastapi.middleware.cors import CORSMiddleware
  4. from fastapi.exceptions import RequestValidationError
  5. from fastapi.responses import JSONResponse
  6. import traceback
  7. import os
  8. import locales
  9. import config
  10. from routers import auth, orders, catalog, portfolio, files, chat, blog, admin
  11. app = FastAPI(title="Radionica 3D API")
  12. # Configure CORS
  13. origins = [
  14. "http://localhost:5173",
  15. "http://127.0.0.1:5173",
  16. "http://localhost:5000",
  17. "https://radionica3d.me",
  18. "https://www.radionica3d.me",
  19. ]
  20. extra_origins = os.getenv("CORS_ORIGINS")
  21. if extra_origins:
  22. origins.extend(extra_origins.split(","))
  23. app.add_middleware(
  24. CORSMiddleware,
  25. allow_origins=origins,
  26. allow_credentials=True,
  27. allow_methods=["*"],
  28. allow_headers=["*"],
  29. )
  30. @app.exception_handler(RequestValidationError)
  31. async def validation_exception_handler(request: Request, exc: RequestValidationError):
  32. lang = request.query_params.get("lang", "en")
  33. errors = []
  34. for error in exc.errors():
  35. error_type = error.get("type", "unknown")
  36. ctx = error.get("ctx", {})
  37. translated_msg = locales.translate_error(error_type, lang, **ctx)
  38. loc = ".".join(str(l) for l in error.get("loc", [])[1:])
  39. errors.append({
  40. "loc": error.get("loc"),
  41. "msg": f"{loc}: {translated_msg}" if loc else translated_msg,
  42. "type": error_type
  43. })
  44. return JSONResponse(status_code=422, content={"detail": errors})
  45. @app.exception_handler(Exception)
  46. async def all_exception_handler(request: Request, exc: Exception):
  47. print(f"ERROR: {exc}")
  48. traceback.print_exc()
  49. if config.DEBUG:
  50. return JSONResponse(
  51. status_code=500,
  52. content={"detail": str(exc), "traceback": traceback.format_exc()}
  53. )
  54. return JSONResponse(status_code=500, content={"detail": "Internal server error"})
  55. # Add custom exception logging or other middleware here if needed
  56. # Include Routers
  57. app.include_router(auth.router)
  58. app.include_router(orders.router)
  59. app.include_router(catalog.router)
  60. app.include_router(portfolio.router)
  61. app.include_router(files.router)
  62. app.include_router(chat.router)
  63. app.include_router(blog.router)
  64. app.include_router(admin.router)
  65. # Mount Static Files
  66. if not os.path.exists("uploads"):
  67. os.makedirs("uploads")
  68. # Mount static files for uploads and previews with caching
  69. app.mount("/uploads", StaticFiles(directory="uploads", html=False), name="uploads")
  70. @app.middleware("http")
  71. async def add_cache_control_header(request, call_next):
  72. response = await call_next(request)
  73. if request.url.path.startswith("/uploads"):
  74. response.headers["Cache-Control"] = "public, max-age=604800, immutable"
  75. return response
  76. if __name__ == "__main__":
  77. import uvicorn
  78. uvicorn.run(app, host="0.0.0.0", port=8000)