1
0
mirror of https://github.com/actix/examples synced 2024-11-27 16:02:57 +01:00

Middleware example - Redirect http connections to https (#457)

This commit is contained in:
Rishad Baniya 2021-10-13 19:51:42 +05:45 committed by GitHub
parent 817c7e1150
commit 11cd3f2b58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 98 additions and 0 deletions

9
Cargo.lock generated
View File

@ -3768,6 +3768,15 @@ dependencies = [
"env_logger 0.9.0",
]
[[package]]
name = "middleware-http-to-https"
version = "0.1.0"
dependencies = [
"actix-web 3.3.2",
"futures",
"rustls 0.18.1",
]
[[package]]
name = "mime"
version = "0.3.16"

View File

@ -7,6 +7,7 @@ members = [
"basics/http-proxy",
"basics/json-validation",
"basics/middleware",
"basics/middleware-http-to-https",
"basics/middleware-ext-mut",
"basics/nested-routing",
"basics/run-in-thread",

View File

@ -0,0 +1,13 @@
[package]
name = "middleware-http-to-https"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = {version = "3", features = ["rustls"]}
rustls = "0.18"
futures = "0.3"

View File

@ -0,0 +1,12 @@
## Middleware eg - redirect any http connection to use https connection
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
**Note :** You will be required to use sudo while running the binary to access port 80 and 443

View File

@ -0,0 +1 @@
cert.pem

View File

@ -0,0 +1 @@
key.pem

View File

@ -0,0 +1,61 @@
use std::fs::File;
use std::io::BufReader;
use actix_web::dev::Service;
use futures::future::FutureExt;
use actix_web::{get, App, HttpServer};
use actix_web::{http, HttpResponse};
use futures::future;
use futures::future::Either;
use rustls::internal::pemfile::{certs, pkcs8_private_keys};
use rustls::{NoClientAuth, ServerConfig};
#[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<()> {
let mut config = ServerConfig::new(NoClientAuth::new());
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 = certs(cert_file).unwrap();
let mut keys = pkcs8_private_keys(key_file).unwrap();
config.set_single_cert(cert_chain, keys.remove(0)).unwrap();
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()
.header(http::header::LOCATION, url)
.finish(),
))));
}
})
.service(index)
})
.bind("0.0.0.0:80")? // Port 80 to listen for http request
.bind_rustls("0.0.0.0:443", config)? // Port 443 to listen for https request
.run()
.await
}