Zabir Al Nazi Nabil
Zabir Al Nazi Nabil

Reputation: 11198

uvicorn [fastapi] python run both HTTP and HTTPS

I'm trying to run a fastapi app with SSL.

I am running the app with uvicorn.

I can run the server on port 80 with HTTP,

if __name__ == '__main__':
    uvicorn.run("main:app", port=80, host='0.0.0.0', reload = True, reload_dirs = ["html_files"])

To run the port with HTTPS, I do the following,

if __name__ == '__main__':
    uvicorn.run("main:app", port=443, host='0.0.0.0', reload = True, reload_dirs = ["html_files"], ssl_keyfile="/etc/letsencrypt/live/my_domain/privkey.pem", ssl_certfile="/etc/letsencrypt/live/my_domain/fullchain.pem")

How can I run both or simply integrate https redirect?

N.B: This is a setup on a server where I don't want to use nginx, I know how to use nginx to implement https redirect.

Upvotes: 18

Views: 52814

Answers (3)

Chris
Chris

Reputation: 34045

You could use HTTPSRedirectMiddleware. This would enforce "that all incoming requests must either be https or wss. Any incoming requests to http or ws will be redirected to the secure scheme instead`.

from fastapi import FastAPI
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware

app = FastAPI()
app.add_middleware(HTTPSRedirectMiddleware)


@app.get("/")
async def main():
    return {"message": "Hello World"}

Upvotes: 13

aaron
aaron

Reputation: 43073

Run a subprocess to return a redirect response from one port to another.

main.py:

if __name__ == '__main__':
    Popen(['python', '-m', 'https_redirect'])  # Add this
    uvicorn.run(
        'main:app', port=443, host='0.0.0.0',
        reload=True, reload_dirs=['html_files'],
        ssl_keyfile='/path/to/certificate-key.pem',
        ssl_certfile='/path/to/certificate.pem')

https_redirect.py:

import uvicorn
from fastapi import FastAPI
from starlette.requests import Request
from starlette.responses import RedirectResponse

app = FastAPI()


@app.route('/{_:path}')
async def https_redirect(request: Request):
    return RedirectResponse(request.url.replace(scheme='https'))

if __name__ == '__main__':
    uvicorn.run('https_redirect:app', port=80, host='0.0.0.0')

Upvotes: 14

Tamir Ciprut
Tamir Ciprut

Reputation: 67

I think you can redirect all traffic from port 80 to port 443 on the OS level using. For example, on Ubuntu, by run in the terminal:

sudo iptables -t nat -L
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 443 # 80 -> 443

Upvotes: -1

Related Questions