Skip to content

Commit

Permalink
Remove HTTP 422 responses from OpenAPI schema (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
No767 authored Nov 18, 2024
1 parent 0ade06e commit 82bf5de
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
56 changes: 54 additions & 2 deletions server/core.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
from __future__ import annotations

import asyncio
from collections import OrderedDict
from contextlib import asynccontextmanager
from typing import Literal, NamedTuple, Optional
from itertools import chain
from typing import TYPE_CHECKING, Any, Generator, Literal, NamedTuple, Optional

import asyncpg
from fastapi import FastAPI
from fastapi import FastAPI, status
from fastapi.exceptions import RequestValidationError
from fastapi.openapi.utils import get_openapi
from fastapi.responses import ORJSONResponse
from typing_extensions import Self
from utils.config import KanaeConfig

if TYPE_CHECKING:
from utils.request import RouteRequest


class VersionInfo(NamedTuple):
major: int
Expand Down Expand Up @@ -47,8 +57,50 @@ def __init__(
lifespan=self.lifespan,
)
self.config = config
self.add_exception_handler(
RequestValidationError,
self.request_validation_error_handler, # type: ignore
)

### Exception Handlers

async def request_validation_error_handler(
self, request: RouteRequest, exc: RequestValidationError
) -> ORJSONResponse:
errors = ", ".join(
OrderedDict.fromkeys(
chain.from_iterable(exception["loc"] for exception in exc.errors())
).keys()
)
return ORJSONResponse(content=f"Field required at: {errors}", status_code=422)

### Server-related utilities

@asynccontextmanager
async def lifespan(self, app: Self):
async with asyncpg.create_pool(dsn=self.config["postgres_uri"]) as app.pool:
yield

def get_db(self) -> Generator[asyncpg.Pool, None, None]:
yield self.pool

def openapi(self) -> dict[str, Any]:
if not self.openapi_schema:
self.openapi_schema = get_openapi(
title=self.title,
version=self.version,
openapi_version=self.openapi_version,
description=self.description,
terms_of_service=self.terms_of_service,
contact=self.contact,
license_info=self.license_info,
routes=self.routes,
tags=self.openapi_tags,
servers=self.servers,
)
for path in self.openapi_schema["paths"].values():
for method in path.values():
responses = method.get("responses")
if str(status.HTTP_422_UNPROCESSABLE_ENTITY) in responses:
del responses[str(status.HTTP_422_UNPROCESSABLE_ENTITY)]
return self.openapi_schema
1 change: 0 additions & 1 deletion server/launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) # type: ignore
app.state.limiter = router.limiter


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
Expand Down

0 comments on commit 82bf5de

Please sign in to comment.