Repository: tiangolo/fastapi

Issue:
make swagger_ui_html, redoc_html and openapi.json handled by async function?
**Is your feature request related to a problem? Please describe.**
I add a loop on all my router of my app to check if the handler are all coroutine function to get better performance, but I fount that swagger_ui_html, redoc_html and openapi.json are handled by normal function.

https://github.com/tiangolo/fastapi/blob/56ab106bbbf8054af437821c6683491ca7952c3b/fastapi/applications.py#L80-L86

**Describe the solution you'd like**

I'm wondering if its possible to handle these 3 router with async function, as its only a simple `getattr` operator or concat string.

https://github.com/tiangolo/fastapi/blob/56ab106bbbf8054af437821c6683491ca7952c3b/fastapi/applications.py#L78

```python
    def setup(self) -> None:
        if self.openapi_url:

            async def openapi_handler(req):
                return JSONResponse(self.openapi())

            self.add_route(
                self.openapi_url,
                openapi_handler,
                include_in_schema=False,
            )
```
**Describe alternatives you've considered**

Disable default handlers and I write async handlers by my self to replace inner handlers.

**Additional context**

In `Starlette`, if a handler is not coroutine function, it will be executed by `loop.run_in_executor` . So this could improve performance a litte bit.(In my test, about 2800 r/s to 3200r/s)

 


Discussion:
Nice catch @Trim21 ! I'll fix it.
If you don't mind, could I give a PR to fix it?
Of course! PRs are very welcome.

Resolving patch:
diff --git a/fastapi/applications.py b/fastapi/applications.py
--- a/fastapi/applications.py
+++ b/fastapi/applications.py
@@ -9,7 +9,7 @@
 from starlette.exceptions import ExceptionMiddleware, HTTPException
 from starlette.middleware.errors import ServerErrorMiddleware
 from starlette.requests import Request
-from starlette.responses import JSONResponse, Response
+from starlette.responses import HTMLResponse, JSONResponse, Response
 from starlette.routing import BaseRoute
 
 
@@ -79,29 +79,28 @@ def openapi(self) -> Dict:
 
     def setup(self) -> None:
         if self.openapi_url:
-            self.add_route(
-                self.openapi_url,
-                lambda req: JSONResponse(self.openapi()),
-                include_in_schema=False,
-            )
+
+            async def openapi(req: Request) -> JSONResponse:
+                return JSONResponse(self.openapi())
+
+            self.add_route(self.openapi_url, openapi, include_in_schema=False)
+            openapi_url = self.openapi_prefix + self.openapi_url
         if self.openapi_url and self.docs_url:
-            self.add_route(
-                self.docs_url,
-                lambda r: get_swagger_ui_html(
-                    openapi_url=self.openapi_prefix + self.openapi_url,
-                    title=self.title + " - Swagger UI",
-                ),
-                include_in_schema=False,
-            )
+
+            async def swagger_ui_html(req: Request) -> HTMLResponse:
+                return get_swagger_ui_html(
+                    openapi_url=openapi_url, title=self.title + " - Swagger UI"
+                )
+
+            self.add_route(self.docs_url, swagger_ui_html, include_in_schema=False)
         if self.openapi_url and self.redoc_url:
-            self.add_route(
-                self.redoc_url,
-                lambda r: get_redoc_html(
-                    openapi_url=self.openapi_prefix + self.openapi_url,
-                    title=self.title + " - ReDoc",
-                ),
-                include_in_schema=False,
-            )
+
+            async def redoc_html(req: Request) -> HTMLResponse:
+                return get_redoc_html(
+                    openapi_url=openapi_url, title=self.title + " - ReDoc"
+                )
+
+            self.add_route(self.redoc_url, redoc_html, include_in_schema=False)
         self.add_exception_handler(HTTPException, http_exception)
 
     def add_api_route(


Test patch: