Redirect HTTP to HTTPS With Python
I was working on a
FastAPI project and I had to deploy it to a web server to
make it easily accessible.
certbot to generate a free
Let's Encrypt certificate and I served the
uvicorn is the default server included in
APIs are served using a full-fledged web server such as
nginx. The recommended way to deploy
FastAPI is their
My small project will only be used by a small number of persons, so I decided to
First, I will show you how to serve your
HTTPS. Then, I will show
you how to use
Python to redirect
We will use a tool called
certbot. It automatically generates
You need to point your
A record to the
IP address of the server that
will host your app. I used an
Amazon Lightsail VPS instance running
20.04 LTS for my project.
The instructions in my case are located at https://certbot.eff.org/lets-encrypt/ubuntufocal-other. Use the drop-down menu at the top of the page to choose your distribution.
A summary of the commands to run for
Ubuntu 20.04 is the following. Use the
link above for more details; or to choose a different distribution.
# Certbot installation sudo snap install core; sudo snap refresh core sudo snap install --classic certbot sudo ln -s /snap/bin/certbot /usr/bin/certbot
I didn’t have a running web server so I used the standalone method:
sudo certbot certonly --standalone --register-unsafely-without-email
If you are not deploying for production, then you can use the flag
--register-unsafely-without-email to avoid typing your email address. You can
read about the “implications” of this flag in this
At this stage, your
Let's Encrypt certificate should be ready to be used.
uvicorn provides two command-line options to serve your certificate.
--ssl-certfile— used to specify your
--ssl-keyfile— used to specify your
You can find both files in
You need administrative privileges to serve your app on port 443, which is the
HTTPS port. Make sure to prefix your
uvicorn command with
It’s time to serve the app. Below is an example to serve a
FastAPI app located
sudo uvicorn server:app \ --workers 10 \ --ssl-certfile /etc/letsencrypt/live/[yourdomain]/fullchain.pem \ --ssl-keyfile /etc/letsencrypt/live/[yourdomain]/privkey.pem \ --host 0.0.0.0 \ --port 443
If we visit
https://[yourdomain] using a web browser, the certificate should
be valid (no browser warning saying that someone is trying to steal your credit
We can now move on to the second part of this post, in which I will explain how
The main problem at this stage is that many people will manually visit
http://[yourdomain]. Their browsers will not force them to use the
For those of you who are familiar with
WordPress, you may be used to
.htaccess to redirect
In my case, I didn’t want to deal with server configuration. Instead, I decided to use a classic imperative approach. 1
I googled the available solutions to redirect
HTTPS with code, and I
Their solution was simple and easy, but I wanted a cleaner approach. Messing
HTTP headers didn’t seem like a clean solution for me. Plus, their
Python 2. I decided that
this solution is old and not clean enough.
Next, I found a solution in
FastAPI’s documentation. The solution described
uses a middleware to redirect all incoming requests to “the secure scheme”.
This last solution is clean, simple, and it just works.
I created a new file called
https.py with the following code:
from fastapi import FastAPI from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware app = FastAPI() app.add_middleware(HTTPSRedirectMiddleware)
We will now spawn a new
uvicorn process to serve the
middleware on port 80. Port 80 is the default
80 is a privileged port, same as port 443. Only the root user can run servers on
those ports. We need to prefix the following command with
sudo uvicorn https:app \ --host 0.0.0.0 \ --port 80
HTTP visitors will automatically be redirected to
Usually, 301 or 302 redirects are used when redirecting incoming requests from
HTTPS. By default,
HTTPSRedirectMiddleware uses a 307 redirect.
According to Yoast SEO, 307 is the right temporary redirect to use since
1.1. You can read more about the difference between 301, 302, and 307 redirects
in this post.
In this post, I showed you how to serve your
FastAPI app over
HTTPS and how
to redirect your incoming
HTTP traffic to
HTTPS without a full-fledged web
Python enthusiasts may find this post interesting because it is more
convenient to showcase your newly developed
FastAPI app with
Browsers and people are becoming more and more demanding regarding web security,
so sharing an insecure
HTTP link to your app may not be the best idea.
By following the few steps in this post, you were able to secure your demo environment without having to deal with server configuration.
This post is by no means suitable for production apps. Follow the best practices
FastAPI’s documentation to publish your app on a publicly
available server and/or domain.
In contrast with the more popular declarative approach of dealing with server configuration. ↩