Skip to content

Commit ac6f438

Browse files
committed
migrate to fastapi
1 parent 4183394 commit ac6f438

38 files changed

+473
-3295
lines changed

Pipfile

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ verify_ssl = true
66
[dev-packages]
77
black = "*"
88
flake8 = "*"
9+
requests = "*"
910
pre-commit = "*"
1011
pytest-asyncio = "*"
1112

1213
[packages]
13-
quart = "*"
14-
quart-cors = "*"
15-
postdb = "*"
1614
pyjwt = "*"
15+
postdb = "*"
1716
aiohttp = "*"
17+
fastapi = "*"
18+
uvicorn = {extras = ["standard"], version = "*"}
1819
uvloop = {markers = "platform_system == 'linux'", version = "*"}
1920

2021
[requires]
@@ -24,4 +25,5 @@ python_version = "3.8"
2425
allow_prereleases = true
2526

2627
[scripts]
28+
test = "pytest"
2729
lint = "pre-commit run --all-files"

Pipfile.lock

+377-363
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/app.py

+20-52
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,22 @@
1-
from quart import Quart, Response, exceptions, jsonify
2-
from datetime import datetime, date
3-
from aiohttp import ClientSession
4-
from typing import Any, Optional
5-
from quart_cors import cors
1+
from fastapi import FastAPI, HTTPException, Request
2+
from utils.response import JSONResponse
63
import logging
7-
import json
8-
9-
import utils
10-
11-
from api.blueprints import auth, guilds, users
124

135

146
log = logging.getLogger()
157

168

17-
class JSONEncoder(json.JSONEncoder):
18-
def default(self, o: Any) -> Any:
19-
if isinstance(o, (datetime, date)):
20-
o.replace(microsecond=0)
21-
return o.isoformat()
22-
23-
return super().default(o)
24-
25-
26-
class API(Quart):
27-
"""Quart subclass to implement more API like handling."""
28-
29-
http_session: Optional[ClientSession] = None
30-
request_class = utils.Request
31-
json_encoder = JSONEncoder
32-
9+
class API(FastAPI):
10+
"""FastAPI subclass to implement more API like handling."""
3311
def __init__(self, *args, **kwargs):
34-
kwargs.setdefault("static_folder", None)
3512
super().__init__(*args, **kwargs)
3613

37-
async def handle_request(self, request: utils.Request) -> Response:
14+
async def handle_request(self, request: Request):
3815
response = await super().handle_request(request)
3916
log.info(f"{request.method} @ {request.base_url} -> {response.status_code}")
4017
return response
4118

42-
async def handle_http_exception(self, error: exceptions.HTTPException):
19+
async def handle_http_exception(self, error: HTTPException):
4320
"""
4421
Returns errors as JSON instead of default HTML
4522
Uses custom error handler if one exists.
@@ -53,35 +30,26 @@ async def handle_http_exception(self, error: exceptions.HTTPException):
5330
headers = error.get_headers()
5431
headers["Content-Type"] = "application/json"
5532

56-
return (
57-
jsonify(error=error.name, message=error.description),
58-
error.status_code,
59-
headers,
33+
return JSONResponse(
34+
headers=headers,
35+
status_code=error.status_code,
36+
content={"error": error.name, "message": error.description}
6037
)
6138

62-
async def startup(self) -> None:
63-
self.http_session = ClientSession()
64-
return await super().startup()
65-
6639

67-
# Set up app
68-
app = API(__name__)
69-
app.asgi_app = utils.TokenAuthMiddleware(app.asgi_app, app)
70-
app = cors(app, allow_origin="*") # TODO: Restrict the origin(s) in production.
71-
# Set up blueprints
72-
auth.setup(app=app, url_prefix="/auth")
73-
users.setup(app=app, url_prefix="/users")
74-
guilds.setup(app=app, url_prefix="/guilds")
40+
app = API()
41+
app.router.default_response_class = JSONResponse
42+
app.add_exception_handler(HTTPException, app.handle_http_exception)
7543

7644

77-
@app.route("/")
45+
@app.get("/")
7846
async def index():
7947
"""Index endpoint used for testing."""
80-
return jsonify(status="OK")
48+
return {"status": "ok"}
8149

8250

83-
@app.errorhandler(500)
84-
async def error_500(error: BaseException):
51+
@app.exception_handler(500)
52+
async def error_500(request, error: HTTPException):
8553
"""
8654
TODO: Handle the error with our own error handling system.
8755
"""
@@ -90,7 +58,7 @@ async def error_500(error: BaseException):
9058
exc_info=(type(error), error, error.__traceback__),
9159
)
9260

93-
return (
94-
jsonify(error="Internal Server Error", message="Server got itself in trouble"),
95-
500,
61+
return JSONResponse(
62+
status_code=500,
63+
content={"error": "Internal Server Error", "message": "Server got itself in trouble"}
9664
)

api/blueprints/auth/__init__.py

-13
This file was deleted.

api/blueprints/auth/views/__init__.py

-1
This file was deleted.

api/blueprints/auth/views/tokens.py

-198
This file was deleted.

api/blueprints/guilds/__init__.py

-13
This file was deleted.

api/blueprints/guilds/views/__init__.py

-1
This file was deleted.

0 commit comments

Comments
 (0)