Skip to content

⛅ 🗳

⚠, 👆 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 🎆, ⚫️ 🔜 👷. 👶