Using HTTPS
This chapter explains how we can access our Humphrey application using HTTPS, improving the security of the application and allowing our client-side code access to more advanced browser features.
Note: While Humphrey's core features are dependency-free, using TLS requires the rustls
crate to ensure that the cryptography used is secure.
Enabling the TLS Feature
To use HTTPS with Humphrey, you must first enable the tls
feature in your Cargo.toml
file:
[dependencies]
humphrey = { version = "*", features = ["tls"] }
Setting up the TLS Certificate
TLS requires a certificate and a private key, which must be supplied to the Humphrey app. In production, these would be generated by a certificate authority like Let's Encrypt, but when developing an HTTPS application, it's often easier to use a self-signed certificate.
The mkcert
command-line tool can be used to generate a trusted certificate for local development.
Installing mkcert
mkcert
can be installed as follows (or downloaded from the aforementioned link):
Windows:
$ choco install mkcert
MacOS:
$ brew install mkcert
Linux:
$ sudo apt install libnss3-tools
$ brew install mkcert
Generating the Certificate
Once installed, the mkcert
certificate authority must be trusted by the operating system, which can be done by running the following command.
$ mkcert -install
Finally, to generate a certificate for local development, run this command, which will create two files, localhost.pem
and localhost-key.pem
.
$ mkcert localhost
Using the Certificate with Humphrey
When creating your Humphrey application, the certificate and key must be provided to the App
using the with_cert
method, which is only available when the tls
feature is enabled. A very simple example using TLS is shown below. Notice that we use run_tls
instead of run
to start the application.
use humphrey::http::{Request, Response, StatusCode};
use humphrey::App;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let app: App<()> = App::new()
.with_stateless_route("/", home)
.with_cert("path/to/localhost.pem", "path/to/localhost-key.pem");
app.run_tls("0.0.0.0:443")?;
Ok(())
}
fn home(_: Request) -> Response {
Response::new(
StatusCode::OK,
"<html><body><h1>This is served over HTTPS!</h1></body></html>",
)
}
Forcing HTTPS
By default, when you call app.run_tls("0.0.0.0:443")
, the application will only accept connections on the HTTPS port (443). Typically, web applications will automatically redirect requests the HTTP port 80 to the HTTPS endpoint. To enable this in Humphrey, you can use the with_forced_https
method on the App
struct, as follows:
// --snip--
let app: App<()> = App::new()
.with_stateless_route("/", home)
.with_cert("path/to/localhost.pem", "path/to/localhost-key.pem")
.with_forced_https(true);
// --snip--
This starts a background thread which simply redirects HTTP requests to the corresponding HTTPS URL.
Conclusion
In this section, we've covered how to use the TLS feature of Humphrey, and how to use it to serve HTTPS applications. Next, we'll learn how to monitor internal events in the application.