Horizon

Share a FastAPI app

Share a FastAPI app with a Horizon tunnel, open the /docs Swagger UI on the public URL, and fix redirects that point at localhost.

Share your FastAPI app with a public HTTPS URL, including the interactive /docs page.

Before you begin

  • Node.js 18 or later
  • A Horizon account and the CLI (see Getting started)
  • A reserved subdomain for -s. Reserve one on the Subdomains page.
  • A FastAPI app in main.py and Uvicorn installed

Start the dev server

Uvicorn listens on port 8000 by default.

uvicorn main:app --reload

Start a tunnel

Use -s with a subdomain you reserved. Without it, the subdomain is random and changes every run. Reserved subdomains are a paid feature, see Pricing.

hrzn tunnel http://localhost:8000 -s my-app
Output
HORIZON: Tunnel connected
  URL          https://my-app.hrzn.run (reserved)
  Forwarding   http://localhost:8000
  Request log  https://hrzn.run/dashboard/tunnels/my-app

Your public URL is https://my-app.hrzn.run. Keep this terminal open.

Open the Swagger UI

Open https://my-app.hrzn.run/docs. The page loads /openapi.json from the same address, so Try it out sends requests to the public URL. You don't need root_path. It's for apps served under a path prefix such as /api/v1.

Check it works

Open https://my-app.hrzn.run/docs. On the first visit Horizon shows a Before you continue page. Select Continue to site. Swagger UI lists your routes. Expand one, select Try it out, then Execute.

The Horizon terminal prints one line per request:

Output
  GET     200  /docs
  GET     200  /openapi.json
  GET     200  /items/

Troubleshooting

A redirect goes to http://localhost:8000

FastAPI redirects /items to /items/ when you declare the route with a trailing slash. The redirect builds its address from the Host header, which the CLI sets to localhost:8000. The browser then follows a link to your own machine.

Request the exact path, /items/, or declare the route without the trailing slash. Check the Location header with curl -i https://my-app.hrzn.run/items.

Do I need --proxy-headers or --forwarded-allow-ips?

No. --proxy-headers is on by default, and Uvicorn trusts 127.0.0.1 and ::1, which is where the CLI connects from. Uvicorn only reads X-Forwarded-Proto and X-Forwarded-For. It ignores X-Forwarded-Host, and it skips an X-Forwarded-Proto value like https,http. So the flags don't change the host or scheme your app sees.

The URL changed after a restart

You started the tunnel without -s, so Horizon gave you a new random subdomain. Restart with -s my-app and the URL stays the same. -s needs a subdomain you reserved, see Pricing.

Nothing reaches your app

  • Check that the Horizon terminal is still running. If its last line is Connection lost. Reconnecting…, wait for Reconnected.
  • Check that Uvicorn listens on port 8000, the port in your hrzn tunnel command.

Next steps

On this page