⛅ 🗳¶
⚠, 👆 5️⃣📆 💪 ⚙️ 🗳 💽 💖 Traefik ⚖️ 👌 ⏮️ 📳 👈 🚮 ➕ ➡ 🔡 👈 🚫 👀 👆 🈸.
👫 💼 👆 💪 ⚙️ root_path 🔗 👆 🈸.
root_path 🛠️ 🚚 🔫 🔧 (👈 FastAPI 🏗 🔛, 🔘 💃).
root_path ⚙️ 🍵 👫 🎯 💼.
& ⚫️ ⚙️ 🔘 🕐❔ 🗜 🎧-🈸.
🗳 ⏮️ 🎞 ➡ 🔡¶
✔️ 🗳 ⏮️ 🎞 ➡ 🔡, 👉 💼, ⛓ 👈 👆 💪 📣 ➡ /app 👆 📟, ✋️ ⤴️, 👆 🚮 🧽 🔛 🔝 (🗳) 👈 🔜 🚮 👆 FastAPI 🈸 🔽 ➡ 💖 /api/v1.
👉 💼, ⏮️ ➡ /app 🔜 🤙 🍦 /api/v1/app.
✋️ 🌐 👆 📟 ✍ 🤔 📤 /app.
& 🗳 🔜 "❎" ➡ 🔡 🔛 ✈ ⏭ 📶 📨 Uvicorn, 🚧 👆 🈸 🤔 👈 ⚫️ 🍦 /app, 👈 👆 🚫 ✔️ ℹ 🌐 👆 📟 🔌 🔡 /api/v1.
🆙 📥, 🌐 🔜 👷 🛎.
✋️ ⤴️, 🕐❔ 👆 📂 🛠️ 🩺 🎚 (🕸), ⚫️ 🔜 ⌛ 🤚 🗄 🔗 /openapi.json, ↩️ /api/v1/openapi.json.
, 🕸 (👈 🏃 🖥) 🔜 🔄 🏆 /openapi.json & 🚫🔜 💪 🤚 🗄 🔗.
↩️ 👥 ✔️ 🗳 ⏮️ ➡ 🔡 /api/v1 👆 📱, 🕸 💪 ☕ 🗄 🔗 /api/v1/openapi.json.
graph LR
browser("Browser")
proxy["Proxy on http://0.0.0.0:9999/api/v1/app"]
server["Server on http://127.0.0.1:8000/app"]
browser --> proxy
proxy --> server
Tip
📢 0.0.0.0 🛎 ⚙️ ⛓ 👈 📋 👂 🔛 🌐 📢 💪 👈 🎰/💽.
🩺 🎚 🔜 💪 🗄 🔗 📣 👈 👉 🛠️ server 🔎 /api/v1 (⛅ 🗳). 🖼:
{
"openapi": "3.0.2",
// More stuff here
"servers": [
{
"url": "/api/v1"
}
],
"paths": {
// More stuff here
}
}
👉 🖼, "🗳" 💪 🕳 💖 Traefik. & 💽 🔜 🕳 💖 Uvicorn, 🏃♂ 👆 FastAPI 🈸.
🚚 root_path¶
🏆 👉, 👆 💪 ⚙️ 📋 ⏸ 🎛 --root-path 💖:
$ uvicorn main:app --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
🚥 👆 ⚙️ Hypercorn, ⚫️ ✔️ 🎛 --root-path.
📡 ℹ
🔫 🔧 🔬 root_path 👉 ⚙️ 💼.
& --root-path 📋 ⏸ 🎛 🚚 👈 root_path.
✅ ⏮️ root_path¶
👆 💪 🤚 ⏮️ root_path ⚙️ 👆 🈸 🔠 📨, ⚫️ 🍕 scope 📖 (👈 🍕 🔫 🔌).
📥 👥 ✅ ⚫️ 📧 🎦 🎯.
from fastapi import FastAPI, Request
app = FastAPI()
@app.get("/app")
def read_main(request: Request):
return {"message": "Hello World", "root_path": request.scope.get("root_path")}
⤴️, 🚥 👆 ▶️ Uvicorn ⏮️:
$ uvicorn main:app --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
📨 🔜 🕳 💖:
{
"message": "Hello World",
"root_path": "/api/v1"
}
⚒ root_path FastAPI 📱¶
👐, 🚥 👆 🚫 ✔️ 🌌 🚚 📋 ⏸ 🎛 💖 --root-path ⚖️ 🌓, 👆 💪 ⚒ root_path 🔢 🕐❔ 🏗 👆 FastAPI 📱:
from fastapi import FastAPI, Request
app = FastAPI(root_path="/api/v1")
@app.get("/app")
def read_main(request: Request):
return {"message": "Hello World", "root_path": request.scope.get("root_path")}
🚶♀️ root_path FastAPI 🔜 🌓 🚶♀️ --root-path 📋 ⏸ 🎛 Uvicorn ⚖️ Hypercorn.
🔃 root_path¶
✔️ 🤯 👈 💽 (Uvicorn) 🏆 🚫 ⚙️ 👈 root_path 🕳 🙆 🌘 🚶♀️ ⚫️ 📱.
✋️ 🚥 👆 🚶 ⏮️ 👆 🖥 http://127.0.0.1:8000/app 👆 🔜 👀 😐 📨:
{
"message": "Hello World",
"root_path": "/api/v1"
}
, ⚫️ 🏆 🚫 ⌛ 🔐 http://127.0.0.1:8000/api/v1/app.
Uvicorn 🔜 ⌛ 🗳 🔐 Uvicorn http://127.0.0.1:8000/app, & ⤴️ ⚫️ 🔜 🗳 🎯 🚮 ➕ /api/v1 🔡 🔛 🔝.
🔃 🗳 ⏮️ 🎞 ➡ 🔡¶
✔️ 🤯 👈 🗳 ⏮️ 🎞 ➡ 🔡 🕴 1️⃣ 🌌 🔗 ⚫️.
🎲 📚 💼 🔢 🔜 👈 🗳 🚫 ✔️ 🏚 ➡ 🔡.
💼 💖 👈 (🍵 🎞 ➡ 🔡), 🗳 🔜 👂 🔛 🕳 💖 https://myawesomeapp.com, & ⤴️ 🚥 🖥 🚶 https://myawesomeapp.com/api/v1/app & 👆 💽 (✅ Uvicorn) 👂 🔛 http://127.0.0.1:8000 🗳 (🍵 🎞 ➡ 🔡) 🔜 🔐 Uvicorn 🎏 ➡: http://127.0.0.1:8000/api/v1/app.
🔬 🌐 ⏮️ Traefik¶
👆 💪 💪 🏃 🥼 🌐 ⏮️ 🎞 ➡ 🔡 ⚙️ Traefik.
⏬ Traefik, ⚫️ 👁 💱, 👆 💪 ⚗ 🗜 📁 & 🏃 ⚫️ 🔗 ⚪️➡️ 📶.
⤴️ ✍ 📁 traefik.toml ⏮️:
[entryPoints]
[entryPoints.http]
address = ":9999"
[providers]
[providers.file]
filename = "routes.toml"
👉 💬 Traefik 👂 🔛 ⛴ 9️⃣9️⃣9️⃣9️⃣ & ⚙️ ➕1️⃣ 📁 routes.toml.
Tip
👥 ⚙️ ⛴ 9️⃣9️⃣9️⃣9️⃣ ↩️ 🐩 🇺🇸🔍 ⛴ 8️⃣0️⃣ 👈 👆 🚫 ✔️ 🏃 ⚫️ ⏮️ 📡 (sudo) 😌.
🔜 ✍ 👈 🎏 📁 routes.toml:
[http]
[http.middlewares]
[http.middlewares.api-stripprefix.stripPrefix]
prefixes = ["/api/v1"]
[http.routers]
[http.routers.app-http]
entryPoints = ["http"]
service = "app"
rule = "PathPrefix(`/api/v1`)"
middlewares = ["api-stripprefix"]
[http.services]
[http.services.app]
[http.services.app.loadBalancer]
[[http.services.app.loadBalancer.servers]]
url = "http://127.0.0.1:8000"
👉 📁 🔗 Traefik ⚙️ ➡ 🔡 /api/v1.
& ⤴️ ⚫️ 🔜 ❎ 🚮 📨 👆 Uvicorn 🏃♂ 🔛 http://127.0.0.1:8000.
🔜 ▶️ Traefik:
$ ./traefik --configFile=traefik.toml
INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml
& 🔜 ▶️ 👆 📱 ⏮️ Uvicorn, ⚙️ --root-path 🎛:
$ uvicorn main:app --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
✅ 📨¶
🔜, 🚥 👆 🚶 📛 ⏮️ ⛴ Uvicorn: http://127.0.0.1:8000/app, 👆 🔜 👀 😐 📨:
{
"message": "Hello World",
"root_path": "/api/v1"
}
Tip
👀 👈 ✋️ 👆 🔐 ⚫️ http://127.0.0.1:8000/app ⚫️ 🎦 root_path /api/v1, ✊ ⚪️➡️ 🎛 --root-path.
& 🔜 📂 📛 ⏮️ ⛴ Traefik, ✅ ➡ 🔡: http://127.0.0.1:9999/api/v1/app.
👥 🤚 🎏 📨:
{
"message": "Hello World",
"root_path": "/api/v1"
}
✋️ 👉 🕰 📛 ⏮️ 🔡 ➡ 🚚 🗳: /api/v1.
↗️, 💭 📥 👈 👱 🔜 🔐 📱 🔘 🗳, ⏬ ⏮️ ➡ 🔡 /app/v1 "☑" 1️⃣.
& ⏬ 🍵 ➡ 🔡 (http://127.0.0.1:8000/app), 🚚 Uvicorn 🔗, 🔜 🎯 🗳 (Traefik) 🔐 ⚫️.
👈 🎦 ❔ 🗳 (Traefik) ⚙️ ➡ 🔡 & ❔ 💽 (Uvicorn) ⚙️ root_path ⚪️➡️ 🎛 --root-path.
✅ 🩺 🎚¶
✋️ 📥 🎊 🍕. 👶
"🛂" 🌌 🔐 📱 🔜 🔘 🗳 ⏮️ ➡ 🔡 👈 👥 🔬. , 👥 🔜 ⌛, 🚥 👆 🔄 🩺 🎚 🍦 Uvicorn 🔗, 🍵 ➡ 🔡 📛, ⚫️ 🏆 🚫 👷, ↩️ ⚫️ ⌛ 🔐 🔘 🗳.
👆 💪 ✅ ⚫️ http://127.0.0.1:8000/docs:

✋️ 🚥 👥 🔐 🩺 🎚 "🛂" 📛 ⚙️ 🗳 ⏮️ ⛴ 9999, /api/v1/docs, ⚫️ 👷 ☑ ❗ 👶
👆 💪 ✅ ⚫️ http://127.0.0.1:9999/api/v1/docs:

▶️️ 👥 💚 ⚫️. 👶 👶
👉 ↩️ FastAPI ⚙️ 👉 root_path ✍ 🔢 server 🗄 ⏮️ 📛 🚚 root_path.
🌖 💽¶
Warning
👉 🌅 🏧 ⚙️ 💼. 💭 🆓 🚶 ⚫️.
🔢, FastAPI 🔜 ✍ server 🗄 🔗 ⏮️ 📛 root_path.
✋️ 👆 💪 🚚 🎏 🎛 servers, 🖼 🚥 👆 💚 🎏 🩺 🎚 🔗 ⏮️ 🏗 & 🏭 🌐.
🚥 👆 🚶♀️ 🛃 📇 servers & 📤 root_path (↩️ 👆 🛠️ 👨❤👨 ⛅ 🗳), FastAPI 🔜 📩 "💽" ⏮️ 👉 root_path ▶️ 📇.
🖼:
from fastapi import FastAPI, Request
app = FastAPI(
servers=[
{"url": "https://stag.example.com", "description": "Staging environment"},
{"url": "https://prod.example.com", "description": "Production environment"},
],
root_path="/api/v1",
)
@app.get("/app")
def read_main(request: Request):
return {"message": "Hello World", "root_path": request.scope.get("root_path")}
🔜 🏗 🗄 🔗 💖:
{
"openapi": "3.0.2",
// More stuff here
"servers": [
{
"url": "/api/v1"
},
{
"url": "https://stag.example.com",
"description": "Staging environment"
},
{
"url": "https://prod.example.com",
"description": "Production environment"
}
],
"paths": {
// More stuff here
}
}
Tip
👀 🚘-🏗 💽 ⏮️ url 💲 /api/v1, ✊ ⚪️➡️ root_path.
🩺 🎚 http://127.0.0.1:9999/api/v1/docs ⚫️ 🔜 👀 💖:

Tip
🩺 🎚 🔜 🔗 ⏮️ 💽 👈 👆 🖊.
❎ 🏧 💽 ⚪️➡️ root_path¶
🚥 👆 🚫 💚 FastAPI 🔌 🏧 💽 ⚙️ root_path, 👆 💪 ⚙️ 🔢 root_path_in_servers=False:
from fastapi import FastAPI, Request
app = FastAPI(
servers=[
{"url": "https://stag.example.com", "description": "Staging environment"},
{"url": "https://prod.example.com", "description": "Production environment"},
],
root_path="/api/v1",
root_path_in_servers=False,
)
@app.get("/app")
def read_main(request: Request):
return {"message": "Hello World", "root_path": request.scope.get("root_path")}
& ⤴️ ⚫️ 🏆 🚫 🔌 ⚫️ 🗄 🔗.
🗜 🎧-🈸¶
🚥 👆 💪 🗻 🎧-🈸 (🔬 🎧 🈸 - 🗻) ⏪ ⚙️ 🗳 ⏮️ root_path, 👆 💪 ⚫️ 🛎, 👆 🔜 ⌛.
FastAPI 🔜 🔘 ⚙️ root_path 🎆, ⚫️ 🔜 👷. 👶