refactor: `PathBuf` data type for cli and file options
options data types updated:
- root
- page50x
- page404
- page-fallback
- http2-tls-cert
- http2-tls-key
Diff
docs/content/configuration/config-file.md | 16 +++++-----
src/control_headers.rs | 2 +-
src/error_page.rs | 12 ++++----
src/fallback_page.rs | 7 ++--
src/handler.rs | 12 ++++----
src/helpers.rs | 15 ++++------
src/server.rs | 23 ++++++++++-----
src/settings/cli.rs | 28 +++++-------------
src/settings/file.rs | 14 ++++-----
src/settings/mod.rs | 50 ++++++++++++++++----------------
10 files changed, 89 insertions(+), 90 deletions(-)
@@ -13,11 +13,11 @@ Below just an example showing all features with its default values.
#### Address & Root dir
host = "::"
port = 8087
root = "docker/public"
port = 80
root = "./public"
#### Logging
log-level = "trace"
log-level = "error"
#### Cache Control headers
cache-control-headers = true
@@ -26,13 +26,13 @@ cache-control-headers = true
compression = true
#### Error pages
page404 = "docker/public/404.html"
page50x = "docker/public/50x.html"
page404 = "./public/404.html"
page50x = "./public/50x.html"
#### HTTP/2 + TLS
http2 = false
http2-tls-cert = ""
http2-tls-key = ""
# http2-tls-cert = "some.cert"
# http2-tls-key = "some.key"
#### Security headers
security-headers = true
@@ -58,7 +58,7 @@ threads-multiplier = 1
grace-period = 0
#### Page fallback for 404s
page-fallback = ""
# page-fallback = "some_page.html"
[advanced]
@@ -7,7 +7,7 @@ use hyper::{Body, Response};
const MAX_AGE_ONE_HOUR: u64 = 60 * 60;
const MAX_AGE_ONE_DAY: u64 = 60 * 60 * 24_u64;
const MAX_AGE_ONE_DAY: u64 = 60 * 60 * 24;
const MAX_AGE_ONE_YEAR: u64 = 60 * 60 * 24 * 365;
@@ -8,8 +8,8 @@ use crate::Result;
pub fn error_response(
method: &Method,
status_code: &StatusCode,
page404: &str,
page50x: &str,
page404: &[u8],
page50x: &[u8],
) -> Result<Response<Body>> {
tracing::warn!(method = ?method, status = status_code.as_u16(), error = ?status_code.to_owned());
@@ -36,8 +36,8 @@ pub fn error_response(
| &StatusCode::RANGE_NOT_SATISFIABLE
| &StatusCode::EXPECTATION_FAILED => {
if status_code == &StatusCode::NOT_FOUND {
error_page_content = page404.to_owned();
if status_code == &StatusCode::NOT_FOUND && !page404.is_empty() {
error_page_content = String::from_utf8_lossy(page404).to_string();
}
status_code
}
@@ -52,7 +52,9 @@ pub fn error_response(
| &StatusCode::INSUFFICIENT_STORAGE
| &StatusCode::LOOP_DETECTED => {
error_page_content = page50x.to_owned();
if !page50x.is_empty() {
error_page_content = String::from_utf8_lossy(page50x).to_string();
}
status_code
}
@@ -2,9 +2,10 @@ use headers::{AcceptRanges, ContentLength, ContentType, HeaderMapExt};
use hyper::{Body, Response, StatusCode};
use mime_guess::mime;
pub fn fallback_response(page_fallback: &str) -> Response<Body> {
pub fn fallback_response(page_fallback: &[u8]) -> Response<Body> {
let body = Body::from(page_fallback.to_owned());
let len = page_fallback.len() as u64;
@@ -16,9 +16,9 @@ pub struct RequestHandlerOpts {
pub cors: Option<cors::Configured>,
pub security_headers: bool,
pub cache_control_headers: bool,
pub page404: String,
pub page50x: String,
pub page_fallback: String,
pub page404: Vec<u8>,
pub page50x: Vec<u8>,
pub page_fallback: Vec<u8>,
pub basic_auth: String,
@@ -166,14 +166,14 @@ impl RequestHandler {
}
Err(status) => {
if !self.opts.page_fallback.is_empty()
if method == Method::GET
&& status == StatusCode::NOT_FOUND
&& method == Method::GET
&& !self.opts.page_fallback.is_empty()
{
return Ok(fallback_page::fallback_response(&self.opts.page_fallback));
}
error_page::error_response(
method,
&status,
@@ -30,17 +30,14 @@ where
}
}
pub fn read_file_content(p: &str) -> String {
if !p.is_empty() && Path::new(p).exists() {
return fs::read_to_string(p).unwrap_or_default();
}
String::new()
}
pub fn read_bytes(path: &Path) -> Result<Vec<u8>> {
fs::read(path).with_context(|| format!("failed to read `{}`", path.display()))
fs::read(path).with_context(|| format!("failed to read file `{}`", path.display()))
}
pub fn read_bytes_default(path: &Path) -> Vec<u8> {
fs::read(path).unwrap_or_default()
}
@@ -99,11 +99,11 @@ impl Server {
.with_context(|| "root directory was not found or inaccessible")?;
let page404 = helpers::read_file_content(&general.page404);
let page50x = helpers::read_file_content(&general.page50x);
let page404 = helpers::read_bytes_default(&general.page404);
let page50x = helpers::read_bytes_default(&general.page50x);
let page_fallback = helpers::read_file_content(&general.page_fallback);
let page_fallback = helpers::read_bytes_default(&general.page_fallback.unwrap_or_default());
let threads = self.threads;
@@ -171,7 +171,7 @@ impl Server {
tcp_listener
.set_nonblocking(true)
.expect("cannot set non-blocking");
.with_context(|| "failed to set TCP non-blocking mode")?;
let listener = tokio::net::TcpListener::from_std(tcp_listener)
.with_context(|| "failed to create tokio::net::TcpListener")?;
let mut incoming = AddrIncoming::from_listener(listener).with_context(|| {
@@ -179,12 +179,21 @@ impl Server {
})?;
incoming.set_nodelay(true);
let http2_tls_cert = match general.http2_tls_cert {
Some(v) => v,
_ => bail!("failed to initialize TLS because cert file missing"),
};
let http2_tls_key = match general.http2_tls_key {
Some(v) => v,
_ => bail!("failed to initialize TLS because key file missing"),
};
let tls = TlsConfigBuilder::new()
.cert_path(&general.http2_tls_cert)
.key_path(&general.http2_tls_key)
.cert_path(&http2_tls_cert)
.key_path(&http2_tls_key)
.build()
.with_context(|| {
"failed to initialize TLS, probably wrong cert/key or file missing"
"failed to initialize TLS probably because invalid cert or key file"
})?;
#[cfg(unix)]
@@ -44,7 +44,7 @@ pub struct General {
#[structopt(long, short = "d", default_value = "./public", env = "SERVER_ROOT")]
pub root: String,
pub root: PathBuf,
#[structopt(
long,
@@ -52,7 +52,7 @@ pub struct General {
env = "SERVER_ERROR_PAGE_50X"
)]
pub page50x: String,
pub page50x: PathBuf,
#[structopt(
long,
@@ -60,11 +60,11 @@ pub struct General {
env = "SERVER_ERROR_PAGE_404"
)]
pub page404: String,
pub page404: PathBuf,
#[structopt(long, default_value = "", env = "SERVER_FALLBACK_PAGE")]
#[structopt(long, env = "SERVER_FALLBACK_PAGE")]
pub page_fallback: String,
pub page_fallback: Option<PathBuf>,
#[structopt(long, short = "g", default_value = "error", env = "SERVER_LOG_LEVEL")]
@@ -98,23 +98,13 @@ pub struct General {
pub http2: bool,
#[structopt(
long,
required_if("http2", "true"),
default_value = "",
env = "SERVER_HTTP2_TLS_CERT"
)]
#[structopt(long, required_if("http2", "true"), env = "SERVER_HTTP2_TLS_CERT")]
pub http2_tls_cert: String,
pub http2_tls_cert: Option<PathBuf>,
#[structopt(
long,
required_if("http2", "true"),
default_value = "",
env = "SERVER_HTTP2_TLS_KEY"
)]
#[structopt(long, required_if("http2", "true"), env = "SERVER_HTTP2_TLS_KEY")]
pub http2_tls_key: String,
pub http2_tls_key: Option<PathBuf>,
#[structopt(
long,
@@ -2,8 +2,8 @@
use headers::HeaderMap;
use serde::Deserialize;
use std::collections::BTreeSet;
use std::path::Path;
use std::{collections::BTreeSet, path::PathBuf};
use crate::{helpers, Context, Result};
@@ -53,7 +53,7 @@ pub struct General {
pub host: Option<String>,
pub port: Option<u16>,
pub root: Option<String>,
pub root: Option<PathBuf>,
pub log_level: Option<LogLevel>,
@@ -65,13 +65,13 @@ pub struct General {
pub compression: Option<bool>,
pub page404: Option<String>,
pub page50x: Option<String>,
pub page404: Option<PathBuf>,
pub page50x: Option<PathBuf>,
pub http2: Option<bool>,
pub http2_tls_cert: Option<String>,
pub http2_tls_key: Option<String>,
pub http2_tls_cert: Option<PathBuf>,
pub http2_tls_key: Option<PathBuf>,
pub security_headers: Option<bool>,
@@ -95,7 +95,7 @@ pub struct General {
pub grace_period: Option<u8>,
pub page_fallback: Option<String>,
pub page_fallback: Option<PathBuf>,
}
@@ -36,28 +36,28 @@ impl Settings {
let opts = General::from_args();
let mut host = opts.host.to_owned();
let mut host = opts.host;
let mut port = opts.port;
let mut root = opts.root.to_owned();
let mut log_level = opts.log_level.to_owned();
let mut root = opts.root;
let mut log_level = opts.log_level;
let mut config_file = opts.config_file.clone();
let mut cache_control_headers = opts.cache_control_headers;
let mut compression = opts.compression;
let mut page404 = opts.page404.to_owned();
let mut page50x = opts.page50x.to_owned();
let mut page404 = opts.page404;
let mut page50x = opts.page50x;
let mut http2 = opts.http2;
let mut http2_tls_cert = opts.http2_tls_cert.to_owned();
let mut http2_tls_key = opts.http2_tls_key.to_owned();
let mut http2_tls_cert = opts.http2_tls_cert;
let mut http2_tls_key = opts.http2_tls_key;
let mut security_headers = opts.security_headers;
let mut cors_allow_origins = opts.cors_allow_origins.to_owned();
let mut cors_allow_headers = opts.cors_allow_headers.to_owned();
let mut cors_allow_origins = opts.cors_allow_origins;
let mut cors_allow_headers = opts.cors_allow_headers;
let mut directory_listing = opts.directory_listing;
let mut directory_listing_order = opts.directory_listing_order;
let mut basic_auth = opts.basic_auth.to_owned();
let mut basic_auth = opts.basic_auth;
let mut fd = opts.fd;
let mut threads_multiplier = opts.threads_multiplier;
let mut grace_period = opts.grace_period;
let mut page_fallback = opts.page_fallback.to_owned();
let mut page_fallback = opts.page_fallback;
let mut settings_advanced: Option<Advanced> = None;
@@ -79,14 +79,14 @@ impl Settings {
if let Some(general) = settings.general {
if let Some(ref v) = general.host {
host = v.to_owned()
if let Some(v) = general.host {
host = v
}
if let Some(v) = general.port {
port = v
}
if let Some(ref v) = general.root {
root = v.to_owned()
if let Some(v) = general.root {
root = v
}
if let Some(ref v) = general.log_level {
log_level = v.name().to_lowercase();
@@ -97,20 +97,20 @@ impl Settings {
if let Some(v) = general.compression {
compression = v
}
if let Some(ref v) = general.page404 {
page404 = v.to_owned()
if let Some(v) = general.page404 {
page404 = v
}
if let Some(ref v) = general.page50x {
page50x = v.to_owned()
if let Some(v) = general.page50x {
page50x = v
}
if let Some(v) = general.http2 {
http2 = v
}
if let Some(ref v) = general.http2_tls_cert {
http2_tls_cert = v.to_owned()
if let Some(v) = general.http2_tls_cert {
http2_tls_cert = Some(v)
}
if let Some(ref v) = general.http2_tls_key {
http2_tls_key = v.to_owned()
if let Some(v) = general.http2_tls_key {
http2_tls_key = Some(v)
}
if let Some(v) = general.security_headers {
security_headers = v
@@ -139,8 +139,8 @@ impl Settings {
if let Some(v) = general.grace_period {
grace_period = v
}
if let Some(ref v) = general.page_fallback {
page_fallback = v.to_owned()
if let Some(v) = general.page_fallback {
page_fallback = Some(v)
}
}