1
0
mirror of https://github.com/actix/examples synced 2025-06-26 17:17:42 +02:00

chore: rename middleware dirs

This commit is contained in:
Rob Ede
2023-10-29 23:51:05 +00:00
parent 5d36d72976
commit 0de1c02762
21 changed files with 43 additions and 38 deletions

View File

@ -0,0 +1,13 @@
[package]
name = "middleware-http-to-https"
version = "1.0.0"
publish.workspace = true
edition.workspace = true
[dependencies]
actix-web = { workspace = true, features = ["rustls-0_21"] }
env_logger.workspace = true
futures-util.workspace = true
log.workspace = true
rustls.workspace = true
rustls-pemfile = "1"

View File

@ -0,0 +1,20 @@
## Middleware: Redirect Any HTTP Connection To Use HTTPS Connection
## Alternatives
A pre-built solution is soon to be built-in. For now, see [`RedirectHttps`](https://docs.rs/actix-web-lab/0.18/actix_web_lab/middleware/struct.RedirectHttps.html) from [`actix-web-lab`](https://crates.io/crates/actix-web-lab).
## This Example
This example is the next step after implementing this example : [Setup TLS via rustls](https://github.com/actix/examples/tree/master/security/rustls).
You might have already implemented TLS (using one of the ways mentioned in the example of security section), and have setup your server to listen to port 443 (for HTTPS).
Now, the only problem left to solve is, to listen to **HTTP** connections as well and redirect them to use **HTTPS**
## Usage
```sh
cd middleware/http-to-https
cargo run
```

View File

@ -0,0 +1 @@
../../https-tls/rustls/cert.pem

View File

@ -0,0 +1 @@
../../https-tls/rustls/key.pem

View File

@ -0,0 +1,68 @@
use std::{fs::File, io::BufReader};
use actix_web::{dev::Service, get, http, App, HttpResponse, HttpServer};
use futures_util::future::{self, Either, FutureExt};
use rustls::{Certificate, PrivateKey, ServerConfig};
use rustls_pemfile::{certs, pkcs8_private_keys};
#[get("/")]
async fn index() -> String {
String::from("<html><head><title>FOO BAR</title></head><body><h1>FOO BAR</h1></body></html>")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
let cert_file = &mut BufReader::new(File::open("cert.pem").unwrap());
let key_file = &mut BufReader::new(File::open("key.pem").unwrap());
let cert_chain: Vec<Certificate> = certs(cert_file)
.unwrap()
.into_iter()
.map(Certificate)
.collect();
let mut keys: Vec<PrivateKey> = pkcs8_private_keys(key_file)
.unwrap()
.into_iter()
.map(PrivateKey)
.collect();
let config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(cert_chain, keys.remove(0))
.unwrap();
log::info!("starting HTTP server at http://localhost:8080");
HttpServer::new(|| {
App::new()
.wrap_fn(|sreq, srv| {
let host = sreq.connection_info().host().to_owned();
let uri = sreq.uri().to_owned();
let url = format!("https://{host}{uri}");
// If the scheme is "https" then it will let other services below this wrap_fn
// handle the request and if it's "http" then a response with redirect status code
// will be sent whose "location" header will be same as before, with just "http"
// changed to "https"
if sreq.connection_info().scheme() == "https" {
Either::Left(srv.call(sreq).map(|res| res))
} else {
println!("An http request has arrived here, i will redirect it to use https");
return Either::Right(future::ready(Ok(sreq.into_response(
HttpResponse::MovedPermanently()
.append_header((http::header::LOCATION, url))
.finish(),
))));
}
})
.service(index)
})
.bind(("127.0.0.1", 80))? // HTTP port
.bind_rustls_021(("127.0.0.1", 443), config)? // HTTPS port
.run()
.await
}