1
0
mirror of https://github.com/actix/examples synced 2025-06-28 09:50:36 +02:00

restructure folders

This commit is contained in:
Rob Ede
2022-02-18 02:01:48 +00:00
parent 4d8573c3fe
commit cc3d356209
201 changed files with 52 additions and 49 deletions

View File

@ -0,0 +1,10 @@
[package]
name = "middleware-http-to-https"
version = "1.0.0"
edition = "2021"
[dependencies]
actix-web = { version = "4.0.0-beta.21", features = ["rustls"] }
rustls = "0.20.2"
rustls-pemfile = "0.2.1"
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,72 @@
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::{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<()> {
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();
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("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
}