---
tags: note,openapi,fastapi,swaggerapi,flask,python,web-framework
---
# [OpenAPI] with [FastAPI] and [Flask]
## 目錄
[TOC]
## What is [OpenAPI]
Reference: [[OpenAPI]], [[Swagger]]
Read More: [[GraphQL]], [[gRPC]], [[Restful API]], [[OpenAPI vs gRPC vs Resful-API]][understanding-grpc-openapi-and-rest-and-when-to-use-them]
Other Program Language: [[Java spring boot]][OpenAPI in Java with spring boot], [[All Program Language..?]][OpenAPI Generator]
[OpenAPI]前身為[SwaggerAPI][Swagger],只是後來將其spec(規範)的部分貢獻給開源社群(抑或是貢獻給Linux基金會)
但[Swagger]還是有在持續開發,但主要負責UI、轉換工具等部分,其APISpec就照著[OpenAPI]了
[OpenAPI]好處有甚麼:
1. 解放前後端溝通成本
> 在[[1]]裡有提到,前端可以使用工具直接取得整合好的[API.js][Swagger-JS]
> 可以直接import進來直接使用,不用再自己寫落落長的js、fetch
> 這代表前端可以解放串接時跟後端的溝通,與資料格式討論等等,直接把openapi拿來就可以串接了
2. 寫好openapi spec就有docs可以看,參閱下面[Document UI章節](#Document-UIDocs-Viewer)
### Document UI(Docs Viewer)
Reference:
1. [Swagger-UI] [][Swagger-UI] [][Swagger-UI]
2. [Redoc] [][Redoc] [][Redoc]
3. [RapiDoc] [][RapiDoc] [][RapiDoc]
4. [StopLight] [][StopLight] [][StopLight]
OpenAPI搭配[Swagger-UI]等相關的自動建立API Viewer可以自動建立docs網頁
且可以在web上面直接測試,不用再自己使用如[PostMan]
若覺得[Swagger-UI]沒那麼喜歡,可以參考Reference的其他幾個
---
## 比較 [FastAPI] 與 [Flask]
Reference: [[1]], [[2]], [[3]], [[4]]
### [FastAPI] [][FastAPI] [][FastAPI]
最大特點為快、新、不用自己寫OpenAPI的文件、原生支援async
缺點為不像[Flask]一樣直接附帶一個web server,需要使用到其他web server。如官方推薦使用[Uvicorn]或[Hypercorn]
或是也可以配合[Flask], [WSGI][WSGI & ASGI]來撰寫,該部分請參閱[[6]]
但不用自己寫文件的實際情況,就是沒有summary、description等等OpenAPI的文件內容,都是使用預設的
但也可以自己寫,但就直接寫在API code裡
#### 配合的其他lib
##### [uvicorn] [][uvicorn] [][uvicorn]
推薦使用這個當作web server,主要原因為使用人數較多、較為成熟
##### [hypercorn] [][Hypercorn] [][Hypercorn]
是個選擇,但使用人數較少,社群不夠強大,所以若遇到使用上的問題可能不是那麼好解決
##### [fastapi-utils] [][Fastapi-Utils] [][Fastapi-Utils]
主要拿來撰寫 class base view(cbv) 的工具,若不使用會不能直觀的用裝飾器方式寫 class 形式的 API
但也有其他的寫法,請參閱[[5]]
但不推薦這一個,主要原因為長期沒有在維護了,推薦使用下面的[fastapi-restful]
一般使用還是可以用,但有發現以下使用方法會有問題
```python
# 該lib使用prefix時, 會發生path是"prefix/prefix"
# 如下面path會變成"http://host:port/foo/foo"
from fastapi import Depends, FastAPI
from fastapi_utils.cbv import cbv
from fastapi_utils.inferring_router import InferringRouter
app = FastAPI()
router = InferringRouter(prefix="/foo") # prefix會重複兩遍
@cbv(router)
class Foo:
x: int = 10
@router.get("/")
def bar(self) -> int:
return self.x
app.include_router(router)
```
##### [fastapi-restful] [][Fastapi-Restful] [][Fastapi-Restful]
雖然該 repo 的 star 很少,但有確定使用後不會像 [fastapi-utils] 一樣會有 prefix 重複的問題
---
### [Flask] [][Flask] [][Flask]
在python裡的老牌API框架
其優點為成熟到不能再成熟、踩過雷的人多、所以社群廣、且文件多
缺點如[[3]]與[[4]]所提:
1. 使用到很多第三方的工具開發
2. sync的開發
3. 與[FastAPI]相比跟OpenAPI的整合需要依賴第三方工具
#### 有整合OpenAPI的框架
##### [connexion] [][connexion] [][connexion]
> 實際上是要自己寫OpenAPI的文件的
> 如果沒有寫文件那等於無法提供給OpenAPI-UI自動有文件說明網頁
> 只提供swagger,沒有redoc
##### [flasgger] [][flasgger] [][flasgger]
> flasgger:
> TODO: 未測試
##### [flask-openapi3] [][flask-openapi3] [][flask-openapi3]
> flask-openapi3:
> TODO: 未測試
> 有提供多種swagger-UI
> 太新,2022/12/07時star數才45
---
## Add Docs Viewer in FastAPI
FastAPI內建就提供 [Swagger-UI] 與 [Redoc],以下再提供其他兩種
Swagger-UI使用參考圖:

Redoc使用參考圖:

### [RapiDoc]
Reference: https://github.com/tiangolo/fastapi/issues/1198
```python=
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.get("/rapidoc", response_class=HTMLResponse, include_in_schema=False)
async def rapidoc():
"""Reference: https://github.com/tiangolo/fastapi/issues/1198"""
return f"""<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script
type="module"
src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"
></script>
</head>
<body>
<rapi-doc spec-url="{app.openapi_url}"></rapi-doc>
</body>
</html>
"""
async def get_openapi_url_in_route(req: Request):
return req.app.openapi_url
```
RapiDoc使用參考圖:

### [StopLight]
Reference: https://github.com/stoplightio/elements#web-component
```python=
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.get("/stoplight", response_class=HTMLResponse, include_in_schema=False)
async def stoplight():
"""Reference: https://github.com/stoplightio/elements#web-component"""
return f"""<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Elements in HTML</title>
<!-- Embed elements Elements via Web Component -->
<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">
</head>
<body>
<elements-api
apiDescriptionUrl="{app.openapi_url}"
router="hash"
layout="sidebar"
/>
</body>
</html>
"""
# 不確定這個需不需要
async def get_openapi_url_in_route(req: Request):
return req.app.openapi_url
```
StopLight使用參考圖:

---
## Use [Uvicorn] in code with FastAPI
[FastAPI官方][FastAPI]只說可以這樣使用[uvicorn]
Reference: https://github.com/tiangolo/fastapi#run-it
```bash
uvicorn <code.py>:<Variable Name of FastAPI in code> --reload
```
但也可以這樣使用
```python
from fastapi import FastAPI
import uvicorn
app = FastAPI()
uvicorn.run(app, host="127.0.0.1", port=8000, reload=True)
```
---
## Example code for use FastAPI
https://github.com/cool9203/fastapi-example
---
## 延伸閱讀
[awesome-flask] [][awesome-flask] [][awesome-flask]
[flask-restful] [][flask-restful] [][flask-restful]
[flask-api] [][flask-api] [][flask-api]
[github star圖示]
[markdown reference圖示]
[Open API UI Framework 介紹:Swagger 與 ReDoc]
[WSGI & ASGI]
[OpenAPI vs gRPC vs Resful-API][understanding-grpc-openapi-and-rest-and-when-to-use-them]
[understanding-rest-grpc-graphql-and-openapi-to-build-your-apis]
[graphql-vs-grpc-vs-rest-choosing-right-api]
[OpenAPI in Java with spring boot]
[OpenAPI with All Program Language..?][OpenAPI Generator]
---
## Reference
### Framework
#### FastAPI相關
[FastAPI]
[OpenAPI]
[Swagger]
[Swagger-UI]
[Swagger-JS]
[Redoc]
[RapiDoc]
[StopLight]
[Uvicorn]
[Hypercorn]
[Fastapi-Utils]
[Fastapi-Restful]
#### Flask相關
[Flask]
[connexion]
[flasgger]
[flask-openapi3]
### 參考文章
[OpenAPI 打通前後端任督二脈][1]
[真・用 OpenAPI 打通前後端任督二脈][2]
[FastAPI vs Flask 的功能比較][3]
[Django,Flask ,FastAPI 怎麼選?][4]
---
[FastAPI]:https://github.com/tiangolo/fastapi "FastAPI"
[OpenAPI]:https://www.openapis.org/
[Swagger]:https://swagger.io/ "Swagger"
[Swagger-UI]:https://github.com/swagger-api/swagger-ui "Swagger-UI"
[Swagger-JS]:https://github.com/swagger-api/swagger-js "Swagger-JS"
[Redoc]:https://github.com/Redocly/redoc "Redoc"
[RapiDoc]:https://github.com/rapi-doc/RapiDoc "RapiDoc"
[StopLight]:https://github.com/stoplightio/elements "StopLight/elements-Docs"
[Uvicorn]:https://github.com/encode/uvicorn "Uvicorn"
[Hypercorn]:https://github.com/pgjones/hypercorn "Hypercorn"
[Fastapi-Utils]:https://github.com/dmontagu/fastapi-utils/ "Fastapi-Utils"
[Fastapi-Restful]:https://github.com/yuval9313/fastapi-restful/ "Fastapi-Restful"
[Flask]:https://github.com/pallets/flask "Flask"
[connexion]:https://github.com/spec-first/connexion "connexion"
[flasgger]:https://github.com/flasgger/flasgger "flasgger"
[flask-openapi3]:https://github.com/luolingchun/flask-openapi3 "flask-openapi3"
[awesome-flask]:https://github.com/humiaozuzu/awesome-flask
[flask-restful]:https://github.com/flask-restful/flask-restful
[flask-api]:https://github.com/flask-api/flask-api
[1]:https://editor.leonh.space/2022/openapi/ "OpenAPI 打通前後端任督二脈"
[2]:https://editor.leonh.space/2022/openapi-ts-codegen/ "真・用 OpenAPI 打通前後端任督二脈"
[3]:https://sean22492249.medium.com/fastapi-vs-flask-%E7%9A%84%E5%8A%9F%E8%83%BD%E6%AF%94%E8%BC%83-cd8e180a47ad "FastAPI vs Flask 的功能比較"
[4]:https://www.readfog.com/a/1635729038798589952 "Django,Flask ,FastAPI 怎麼選?"
[5]:https://stackoverflow.com/a/70563827 "How to create routes with FastAPI within a class"
[6]:https://fastapi.tiangolo.com/advanced/wsgi/ "FastAPI Including WSGI - Flask, Django, others"
[7]:https://fastapi.tiangolo.com/tutorial/bigger-applications/ "FastAPI bigger-applications"
[github star圖示]:https://badgen.net/github/
[markdown reference圖示]:https://github.com/Naereen/badges
[Open API UI Framework 介紹:Swagger 與 ReDoc]:https://greddyblogs.gitlab.io/2019/02/22/redoc/#gsc.tab=0 "Open API UI Framework 介紹:Swagger 與 ReDoc"
[GraphQL]:https://github.com/graphql
[gRPC]:https://grpc.io/
[Restful API]:https://zh.wikipedia.org/zh-tw/%E8%A1%A8%E7%8E%B0%E5%B1%82%E7%8A%B6%E6%80%81%E8%BD%AC%E6%8D%A2
[understanding-grpc-openapi-and-rest-and-when-to-use-them]:https://cloud.google.com/blog/products/api-management/understanding-grpc-openapi-and-rest-and-when-to-use-them
[understanding-rest-grpc-graphql-and-openapi-to-build-your-apis]:https://www.koyeb.com/blog/understanding-rest-grpc-graphql-and-openapi-to-build-your-apis
[graphql-vs-grpc-vs-rest-choosing-right-api]:https://blog.logrocket.com/graphql-vs-grpc-vs-rest-choosing-right-api/
[PostMan]:https://www.postman.com/
[WSGI & ASGI]:https://quietbo.com/2022/05/08/wsgi-asgi/
[OpenAPI in Java with spring boot]:https://www.ruyut.com/2022/05/spring-boot-openapi-3-swagger-ui.html
[OpenAPI Generator]:https://github.com/OpenAPITools/openapi-generator