Merge pull request #26 from HenningHolmDE/redirect_http_server
feat: http to https redirection support
Diff
README.md | 10 ++++++++++
src/config.rs | 6 ++++++
src/main.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++---------
3 files changed, 62 insertions(+), 9 deletions(-)
@@ -20,6 +20,7 @@
- First-class [Docker](https://docs.docker.com/get-started/overview/) support. [Scratch](https://hub.docker.com/_/scratch) and latest [Alpine Linux](https://hub.docker.com/_/alpine) Docker images available.
- Server configurable via environment variables or CLI arguments.
- MacOs binary support (`x86_64-apple-darwin`) thanks to [Rust Linux / Darwin Builder](https://github.com/joseluisq/rust-linux-darwin-builder).
- Additional HTTP redirect server for redirecting HTTP traffic to HTTPS site.
## Releases
@@ -47,6 +48,8 @@ Server can be configured either via environment variables or their equivalent co
### Command-line arguments
@@ -92,6 +95,13 @@ OPTIONS:
corresponding private key and chain of certificates to a trusted root [env: SERVER_TLS_PKCS12=] [default: ]
--tls-pkcs12-passwd <tls-pkcs12-passwd>
A specified password to decrypt the private key [env: SERVER_TLS_PKCS12_PASSWD=] [default: ]
--tls-redirect-from <tls-redirect-from>
Host port for redirecting HTTP requests to HTTPS. This option enables the HTTP redirect feature [env:
SERVER_TLS_REDIRECT_FROM=]
--tls-redirect-host <tls-redirect-host>
Host name of HTTPS site for redirecting HTTP requests to. Defaults to host address [env:
SERVER_TLS_REDIRECT_HOST=]
```
## TLS/SSL
@@ -41,6 +41,12 @@ pub struct Options {
#[structopt(long, default_value = "", env = "SERVER_TLS_PKCS12_PASSWD")]
pub tls_pkcs12_passwd: String,
#[structopt(long, env = "SERVER_TLS_REDIRECT_FROM")]
pub tls_redirect_from: Option<u16>,
#[structopt(long, env = "SERVER_TLS_REDIRECT_HOST")]
pub tls_redirect_host: Option<String>,
#[structopt(long, default_value = "error", env = "SERVER_LOG_LEVEL")]
pub log_level: String,
@@ -7,7 +7,8 @@ extern crate log;
use crate::config::Options;
use hyper_native_tls::NativeTlsServer;
use iron::prelude::*;
use iron::{prelude::*, Listening};
use iron_staticfile_middleware::HttpToHttpsRedirect;
use staticfiles::*;
use structopt::StructOpt;
@@ -19,12 +20,21 @@ mod logger;
mod signal_manager;
mod staticfiles;
fn on_server_running(server_name: &str, proto: &str, addr: &str) {
#[derive(Debug)]
struct RunningServer {
listening: Listening,
server_type: String,
}
fn on_server_running(server_name: &str, running_servers: &Vec<RunningServer>) {
logger::log_server(&format!(
"Static {} Server \"{}\" is listening on {}",
proto, server_name, addr
));
running_servers.iter().for_each(|server| {
logger::log_server(&format!(
"{} Server \"{}\" is listening on {}",
server.server_type, server_name, server.listening.socket
))
});
signal_manager::wait_for_signal(|sig: signal::Signal| {
@@ -42,7 +52,6 @@ fn main() {
logger::init(&opts.log_level);
let addr = &format!("{}{}{}", opts.host, ":", opts.port);
let proto = if opts.tls { "HTTPS" } else { "HTTP" };
@@ -54,19 +63,47 @@ fn main() {
cors_allow_origins: opts.cors_allow_origins,
});
let mut running_servers = Vec::new();
if opts.tls {
let ssl = NativeTlsServer::new(opts.tls_pkcs12, &opts.tls_pkcs12_passwd).unwrap();
match Iron::new(files.handle()).https(addr, ssl) {
Result::Ok(_) => on_server_running(&opts.name, &proto, addr),
Result::Ok(listening) => running_servers.push(RunningServer {
listening,
server_type: "Static HTTPS".to_string(),
}),
Result::Err(err) => panic!("{:?}", err),
}
if let Some(port_redirect) = opts.tls_redirect_from {
let addr_redirect = &format!("{}{}{}", opts.host, ":", port_redirect);
let host_redirect = match opts.tls_redirect_host.as_ref() {
Some(host) => host,
None => &opts.host,
};
let handler =
Chain::new(HttpToHttpsRedirect::new(&host_redirect, opts.port).permanent());
match Iron::new(handler).http(addr_redirect) {
Result::Ok(listening) => running_servers.push(RunningServer {
listening,
server_type: "Redirect HTTP".to_string(),
}),
Result::Err(err) => panic!("{:?}", err),
}
}
} else {
match Iron::new(files.handle()).http(addr) {
Result::Ok(_) => on_server_running(&opts.name, &proto, addr),
Result::Ok(listening) => running_servers.push(RunningServer {
listening,
server_type: "Static HTTP".to_string(),
}),
Result::Err(err) => panic!("{:?}", err),
}
}
on_server_running(&opts.name, &running_servers);
}
#[cfg(test)]