refactor: decrease allocations during 404/50x error page responses
Diff
Cargo.lock | 40 +++++++++++++++-------------------------
Cargo.toml | 1 -
src/error_page.rs | 47 ++++++++++++++++++++---------------------------
src/handler.rs | 18 ++++++++++++++++--
src/server.rs | 12 +++++-------
5 files changed, 56 insertions(+), 62 deletions(-)
@@ -34,9 +34,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.41"
version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
[[package]]
name = "async-compression"
@@ -114,15 +114,9 @@ checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
[[package]]
name = "cc"
version = "1.0.68"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
[[package]]
name = "cfg-if"
@@ -168,7 +162,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
@@ -202,7 +196,7 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"crc32fast",
"libc",
"miniz_oxide",
@@ -492,9 +486,9 @@ checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]]
name = "listenfd"
version = "0.3.3"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "492158e732f2e2de81c592f0a2427e57e12cd3d59877378fe7af624b6bbe0ca1"
checksum = "809e514e2cb8a9624701346ea3e694c1766d76778e343e537d873c1c366e79a7"
dependencies = [
"libc",
"uuid",
@@ -507,7 +501,7 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
@@ -581,7 +575,7 @@ checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a"
dependencies = [
"bitflags",
"cc",
"cfg-if 1.0.0",
"cfg-if",
"libc",
]
@@ -807,7 +801,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16"
dependencies = [
"block-buffer",
"cfg-if 1.0.0",
"cfg-if",
"cpufeatures",
"digest",
"opaque-debug",
@@ -867,7 +861,6 @@ dependencies = [
"listenfd",
"mime_guess",
"num_cpus",
"once_cell",
"percent-encoding",
"pin-project",
"structopt",
@@ -1008,7 +1001,7 @@ version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@@ -1124,12 +1117,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "uuid"
version = "0.6.5"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363"
dependencies = [
"cfg-if 0.1.10",
]
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
[[package]]
name = "version_check"
@@ -1159,7 +1149,7 @@ version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"wasm-bindgen-macro",
]
@@ -40,7 +40,6 @@ bytes = "1.0"
percent-encoding = "2.1"
structopt = { version = "0.3", default-features = false }
num_cpus = { version = "1.13" }
once_cell = "1.7"
pin-project = "1.0"
tokio-rustls = { version = "0.22" }
humansize = "1.1"
@@ -1,15 +1,16 @@
use headers::{AcceptRanges, ContentLength, ContentType, HeaderMapExt, HeaderValue};
use http::header::CONTENT_TYPE;
use hyper::{Body, Method, Response, StatusCode};
use once_cell::sync::OnceCell;
use crate::Result;
pub static PAGE_404: OnceCell<String> = OnceCell::new();
pub static PAGE_50X: OnceCell<String> = OnceCell::new();
pub fn error_response(method: &Method, status_code: &StatusCode) -> Result<Response<Body>> {
pub fn error_response(
method: &Method,
status_code: &StatusCode,
page404: &str,
page50x: &str,
) -> Result<Response<Body>> {
tracing::warn!(method = ?method, status = status_code.as_u16(), error = ?status_code.to_owned());
@@ -36,15 +37,7 @@ pub fn error_response(method: &Method, status_code: &StatusCode) -> Result<Respo
| &StatusCode::EXPECTATION_FAILED => {
if status_code == &StatusCode::NOT_FOUND {
error_page_content = match PAGE_404.get() {
Some(s) => s.to_owned(),
None => {
tracing::error!(
"404 error page content is not accessible or `PAGE_404` uninitialized"
);
String::new()
}
};
error_page_content = page404.to_owned();
}
status_code
}
@@ -59,15 +52,7 @@ pub fn error_response(method: &Method, status_code: &StatusCode) -> Result<Respo
| &StatusCode::INSUFFICIENT_STORAGE
| &StatusCode::LOOP_DETECTED => {
error_page_content = match PAGE_50X.get() {
Some(s) => s.to_owned(),
None => {
tracing::error!(
"50x error page content is not accessible or `PAGE_50X` uninitialized"
);
String::new()
}
};
error_page_content = page50x.to_owned();
status_code
}
@@ -75,10 +60,18 @@ pub fn error_response(method: &Method, status_code: &StatusCode) -> Result<Respo
};
if error_page_content.is_empty() {
error_page_content = format!(
"<html><head><title>{}</title></head><body><center><h1>{}</h1></center></body></html>",
status_code, status_code
);
error_page_content = [
"<html><head><title>",
status_code.as_str(),
" ",
status_code.canonical_reason().unwrap_or_default(),
"</title></head><body><center><h1>",
status_code.as_str(),
" ",
status_code.canonical_reason().unwrap_or_default(),
"</h1></center></body></html>",
]
.concat();
}
let mut body = Body::empty();
@@ -12,6 +12,8 @@ pub struct RequestHandlerOpts {
pub dir_listing: bool,
pub cors: Option<Arc<cors::Configured>>,
pub security_headers: bool,
pub page404: Arc<str>,
pub page50x: Arc<str>,
}
@@ -42,7 +44,12 @@ impl RequestHandler {
}
Err(e) => {
tracing::debug!("cors error kind: {:?}", e);
return error_page::error_response(method, &StatusCode::FORBIDDEN);
return error_page::error_response(
method,
&StatusCode::FORBIDDEN,
self.opts.page404.as_ref(),
self.opts.page50x.as_ref(),
);
}
};
}
@@ -59,6 +66,8 @@ impl RequestHandler {
return error_page::error_response(
method,
&StatusCode::INTERNAL_SERVER_ERROR,
self.opts.page404.as_ref(),
self.opts.page50x.as_ref(),
);
}
};
@@ -75,7 +84,12 @@ impl RequestHandler {
Ok(resp)
}
Err(status) => error_page::error_response(method, &status),
Err(status) => error_page::error_response(
method,
&status,
self.opts.page404.as_ref(),
self.opts.page50x.as_ref(),
),
}
}
}
@@ -8,7 +8,7 @@ use structopt::StructOpt;
use crate::handler::{RequestHandler, RequestHandlerOpts};
use crate::tls::{TlsAcceptor, TlsConfigBuilder};
use crate::{config::Config, service::RouterService, Result};
use crate::{cors, error_page, helpers, logger, signals};
use crate::{cors, helpers, logger, signals};
pub struct Server {
@@ -81,12 +81,8 @@ impl Server {
let root_dir = Arc::new(helpers::get_valid_dirpath(&opts.root)?);
error_page::PAGE_404
.set(helpers::read_file_content(opts.page404.as_ref()))
.expect("page 404 is not initialized");
error_page::PAGE_50X
.set(helpers::read_file_content(opts.page50x.as_ref()))
.expect("page 50x is not initialized");
let page404 = Arc::from(helpers::read_file_content(opts.page404.as_ref()).as_str());
let page50x = Arc::from(helpers::read_file_content(opts.page50x.as_ref()).as_str());
let threads = self.threads;
@@ -115,6 +111,8 @@ impl Server {
dir_listing,
cors,
security_headers,
page404,
page50x,
},
});