--- 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] [![GitHub stars](https://img.shields.io/github/stars/swagger-api/swagger-ui.svg?style=social&label=Star&maxAge=2592000)][Swagger-UI] [![GitHub latest commit](https://badgen.net/github/last-commit/swagger-api/swagger-ui)][Swagger-UI] 2. [Redoc] [![GitHub stars](https://img.shields.io/github/stars/Redocly/redoc.svg?style=social&label=Star&maxAge=2592000)][Redoc] [![GitHub latest commit](https://badgen.net/github/last-commit/Redocly/redoc/main)][Redoc] 3. [RapiDoc] [![GitHub stars](https://img.shields.io/github/stars/rapi-doc/RapiDoc.svg?style=social&label=Star&maxAge=2592000)][RapiDoc] [![GitHub latest commit](https://badgen.net/github/last-commit/rapi-doc/RapiDoc)][RapiDoc] 4. [StopLight] [![GitHub stars](https://img.shields.io/github/stars/stoplightio/elements.svg?style=social&label=Star&maxAge=2592000)][StopLight] [![GitHub latest commit](https://badgen.net/github/last-commit/stoplightio/elements/main)][StopLight] OpenAPI搭配[Swagger-UI]等相關的自動建立API Viewer可以自動建立docs網頁 且可以在web上面直接測試,不用再自己使用如[PostMan] 若覺得[Swagger-UI]沒那麼喜歡,可以參考Reference的其他幾個 --- ## 比較 [FastAPI] 與 [Flask] Reference: [[1]], [[2]], [[3]], [[4]] ### [FastAPI] [![GitHub stars](https://img.shields.io/github/stars/tiangolo/fastapi.svg?style=social&label=Star&maxAge=2592000)][FastAPI] [![GitHub latest commit](https://badgen.net/github/last-commit/tiangolo/fastapi)][FastAPI] 最大特點為快、新、不用自己寫OpenAPI的文件、原生支援async 缺點為不像[Flask]一樣直接附帶一個web server,需要使用到其他web server。如官方推薦使用[Uvicorn]或[Hypercorn] 或是也可以配合[Flask], [WSGI][WSGI & ASGI]來撰寫,該部分請參閱[[6]] 但不用自己寫文件的實際情況,就是沒有summary、description等等OpenAPI的文件內容,都是使用預設的 但也可以自己寫,但就直接寫在API code裡 #### 配合的其他lib ##### [uvicorn] [![GitHub stars](https://img.shields.io/github/stars/encode/uvicorn.svg?style=social&label=Star&maxAge=2592000)][uvicorn] [![GitHub latest commit](https://badgen.net/github/last-commit/encode/uvicorn)][uvicorn] 推薦使用這個當作web server,主要原因為使用人數較多、較為成熟 ##### [hypercorn] [![GitHub stars](https://img.shields.io/github/stars/pgjones/hypercorn.svg?style=social&label=Star&maxAge=2592000)][Hypercorn] [![GitHub latest commit](https://badgen.net/github/last-commit/pgjones/hypercorn/main)][Hypercorn] 是個選擇,但使用人數較少,社群不夠強大,所以若遇到使用上的問題可能不是那麼好解決 ##### [fastapi-utils] [![GitHub stars](https://img.shields.io/github/stars/dmontagu/fastapi-utils.svg?style=social&label=Star&maxAge=2592000)][Fastapi-Utils] [![GitHub latest commit](https://badgen.net/github/last-commit/dmontagu/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] [![GitHub stars](https://img.shields.io/github/stars/yuval9313/fastapi-restful.svg?style=social&label=Star&maxAge=2592000)][Fastapi-Restful] [![GitHub latest commit](https://badgen.net/github/last-commit/yuval9313/fastapi-restful)][Fastapi-Restful] 雖然該 repo 的 star 很少,但有確定使用後不會像 [fastapi-utils] 一樣會有 prefix 重複的問題 --- ### [Flask] [![GitHub stars](https://img.shields.io/github/stars/pallets/flask.svg?style=social&label=Star&maxAge=2592000)][Flask] [![GitHub latest commit](https://badgen.net/github/last-commit/pallets/flask/main)][Flask] 在python裡的老牌API框架 其優點為成熟到不能再成熟、踩過雷的人多、所以社群廣、且文件多 缺點如[[3]]與[[4]]所提: 1. 使用到很多第三方的工具開發 2. sync的開發 3. 與[FastAPI]相比跟OpenAPI的整合需要依賴第三方工具 #### 有整合OpenAPI的框架 ##### [connexion] [![GitHub stars](https://img.shields.io/github/stars/spec-first/connexion.svg?style=social&label=Star&maxAge=2592000)][connexion] [![GitHub latest commit](https://badgen.net/github/last-commit/spec-first/connexion)][connexion] > 實際上是要自己寫OpenAPI的文件的 > 如果沒有寫文件那等於無法提供給OpenAPI-UI自動有文件說明網頁 > 只提供swagger,沒有redoc ##### [flasgger] [![GitHub stars](https://img.shields.io/github/stars/flasgger/flasgger.svg?style=social&label=Star&maxAge=2592000)][flasgger] [![GitHub latest commit](https://badgen.net/github/last-commit/flasgger/flasgger)][flasgger] > flasgger: > TODO: 未測試 ##### [flask-openapi3] [![GitHub stars](https://img.shields.io/github/stars/luolingchun/flask-openapi3.svg?style=social&label=Star&maxAge=2592000)][flask-openapi3] [![GitHub latest commit](https://badgen.net/github/last-commit/luolingchun/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使用參考圖: ![Swagger-UI-use](https://i.imgur.com/6PJgTnf.png) Redoc使用參考圖: ![Redoc-use](https://i.imgur.com/UAEm6ZI.png) ### [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使用參考圖: ![RapiDoc-use](https://i.imgur.com/FaRirWV.png) ### [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使用參考圖: ![StopLight-use](https://i.imgur.com/5a3n0DR.png) --- ## 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] [![GitHub stars](https://img.shields.io/github/stars/humiaozuzu/awesome-flask.svg?style=social&label=Star&maxAge=2592000)][awesome-flask] [![GitHub latest commit](https://badgen.net/github/last-commit/humiaozuzu/awesome-flask)][awesome-flask] [flask-restful] [![GitHub stars](https://img.shields.io/github/stars/flask-restful/flask-restful.svg?style=social&label=Star&maxAge=2592000)][flask-restful] [![GitHub latest commit](https://badgen.net/github/last-commit/flask-restful/flask-restful)][flask-restful] [flask-api] [![GitHub stars](https://img.shields.io/github/stars/flask-api/flask-api.svg?style=social&label=Star&maxAge=2592000)][flask-api] [![GitHub latest commit](https://badgen.net/github/last-commit/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