-
Notifications
You must be signed in to change notification settings - Fork 2
/
server.py
160 lines (134 loc) · 5.13 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
__import__("gooeysite.wsgi") # Note: this must always be at the top
import logging
import traceback
from time import time
import anyio
from decouple import config
from fastapi import FastAPI
from fastapi.exception_handlers import (
http_exception_handler,
request_validation_exception_handler,
)
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi.routing import APIRoute
from fastapi.staticfiles import StaticFiles
from starlette._utils import is_async_callable
from starlette.exceptions import HTTPException
from starlette.middleware.authentication import AuthenticationMiddleware
from starlette.middleware.sessions import SessionMiddleware
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.status import (
HTTP_404_NOT_FOUND,
HTTP_405_METHOD_NOT_ALLOWED,
)
import url_shortener.routers as url_shortener
from auth.auth_backend import (
SessionAuthBackend,
)
from daras_ai_v2 import settings
from daras_ai_v2.github_tools import github_url_for_exc
from daras_ai_v2.pydantic_validation import convert_errors
from daras_ai_v2.settings import templates
from gooeysite.bg_db_conn import db_middleware
from routers import (
account,
facebook_api,
api,
root,
slack_api,
paypal,
stripe,
broadcast_api,
bots_api,
twilio_api,
static_pages,
)
app = FastAPI(title="GOOEY.AI", docs_url=None, redoc_url="/docs")
app.mount("/static", StaticFiles(directory="static"), name="static")
app.include_router(bots_api.app)
app.include_router(api.app)
app.include_router(broadcast_api.app)
app.include_router(account.app, include_in_schema=False)
app.include_router(facebook_api.app, include_in_schema=False)
app.include_router(slack_api.router, include_in_schema=False)
app.include_router(url_shortener.app, include_in_schema=False)
app.include_router(paypal.router, include_in_schema=False)
app.include_router(stripe.router, include_in_schema=False)
app.include_router(twilio_api.router, include_in_schema=False)
app.include_router(static_pages.app, include_in_schema=False)
app.include_router(root.app, include_in_schema=False) # this has a catch-all route
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.add_middleware(AuthenticationMiddleware, backend=SessionAuthBackend())
app.add_middleware(SessionMiddleware, secret_key=settings.SECRET_KEY)
# monkey patch to make django db work with fastapi
for route in app.routes:
if isinstance(route, APIRoute) and not is_async_callable(route.endpoint):
route.endpoint = db_middleware(route.endpoint)
@app.on_event("startup")
async def startup():
limiter = anyio.to_thread.current_default_thread_limiter()
limiter.total_tokens = config("MAX_THREADS", default=limiter.total_tokens, cast=int)
@app.add_middleware
def request_time_middleware(app):
logger = logging.getLogger("uvicorn.time")
async def middleware(scope, receive, send):
start_time = time()
await app(scope, receive, send)
response_time = (time() - start_time) * 1000
logger.info(
f"{scope.get('method')} {scope.get('path')} - {response_time:.3f} ms"
)
return middleware
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
## https://fastapi.tiangolo.com/tutorial/handling-errors/#override-request-validation-exceptions
convert_errors(exc.errors())
return await request_validation_exception_handler(request, exc)
@app.exception_handler(HTTP_404_NOT_FOUND)
@app.exception_handler(HTTP_405_METHOD_NOT_ALLOWED)
async def not_found_exception_handler(request: Request, exc: HTTPException):
return await _exc_handler(request, exc, "errors/404.html")
@app.exception_handler(Exception)
async def server_error_exception_handler(request: Request, exc: Exception):
return await _exc_handler(request, exc, "errors/unknown.html")
async def _exc_handler(request: Request, exc: Exception, template_name: str):
from celeryapp.tasks import err_msg_for_exc
if request.headers.get("X-GOOEY-GUI-ROUTE"):
return templates.TemplateResponse(
template_name,
context=dict(
request=request,
settings=settings,
error=err_msg_for_exc(exc),
github_url=github_url_for_exc(exc),
traceback=traceback.format_exc(),
),
status_code=getattr(exc, "status_code", None) or 500,
)
elif isinstance(exc, HTTPException):
return await http_exception_handler(request, exc)
else:
return JSONResponse(
dict(
detail=err_msg_for_exc(exc),
github_url=github_url_for_exc(exc),
traceback=traceback.format_exc(),
),
status_code=500,
)
if __name__ == "__main__":
from gooey_gui.core.reloader import runserver
runserver(
"server:app",
port=8080,
reload=True,
reload_excludes=["models.py", "admin.py", "api.py"],
)