Add fallback page option (#91)
feat: fallback page option via `--page-fallback` argument
Diff
docs/content/features/error-pages.md | 15 ++++++++++++++-
src/config.rs | 8 ++++++--
src/fallback_page.rs | 19 +++++++++++++++++++
src/handler.rs | 25 ++++++++++++++++++-------
src/lib.rs | 1 +
src/server.rs | 4 ++++
6 files changed, 62 insertions(+), 10 deletions(-)
@@ -5,7 +5,7 @@
This feature is enabled by default and can be controlled either by the string `--page404` ([SERVER_ERROR_PAGE_404](./../configuration/environment-variables.md#server_error_page_404)) or the `--page50x` ([SERVER_ERROR_PAGE_50X](./../configuration/environment-variables.md#server_error_page_50x)) arguments.
!!! info "Tip"
Either `--page404` and `--page50x` have defaults (optional values) so they can be specified or omitted as required.
Either `--page404` and `--page50x` have defaults (optional values) so they can be specified or omitted as required.
Below an example of how to customize those HTML pages.
@@ -16,3 +16,16 @@ static-web-server \
--page404 ./my-page-404.html \
--page50x ./my-page-50x.html
```
## Fallback Page for use with Client Routers
HTML file path that is used for GET requests when the requested path doesn't exist. The fallback page is served with a 200 status code, useful when using client routers like `React Router` or similar. If the path is not specified or simply doesn't exist then this feature will not be active.
It can be set with the `SERVER_FALLBACK_PAGE` environment variable or with the cli argument `--page-fallback`.
```sh
static-web-server \
--port 8787 \
--root ./my-public-dir \
--page-fallback ./my-public-dir/index.html
```
@@ -47,7 +47,7 @@ pub struct Config {
default_value = "./public/50x.html",
env = "SERVER_ERROR_PAGE_50X"
)]
pub page50x: String,
#[structopt(
@@ -55,9 +55,13 @@ pub struct Config {
default_value = "./public/404.html",
env = "SERVER_ERROR_PAGE_404"
)]
pub page404: String,
#[structopt(long, default_value = "", env = "SERVER_FALLBACK_PAGE")]
pub page_fallback: String,
#[structopt(long, short = "g", default_value = "error", env = "SERVER_LOG_LEVEL")]
pub log_level: String,
@@ -0,0 +1,19 @@
use headers::{AcceptRanges, ContentLength, ContentType, HeaderMapExt};
use hyper::{Body, Response, StatusCode};
use mime_guess::mime;
pub fn fallback_response(page_fallback: &str) -> Response<Body> {
let body = Body::from(page_fallback.to_owned());
let len = page_fallback.len() as u64;
let mut resp = Response::new(body);
*resp.status_mut() = StatusCode::OK;
resp.headers_mut().typed_insert(ContentLength(len));
resp.headers_mut()
.typed_insert(ContentType::from(mime::TEXT_HTML_UTF_8));
resp.headers_mut().typed_insert(AcceptRanges::bytes());
resp
}
@@ -2,7 +2,8 @@ use hyper::{header::WWW_AUTHENTICATE, Body, Method, Request, Response, StatusCod
use std::{future::Future, path::PathBuf, sync::Arc};
use crate::{
basic_auth, compression, control_headers, cors, error_page, security_headers, static_files,
basic_auth, compression, control_headers, cors, error_page, fallback_page, security_headers,
static_files,
};
use crate::{Error, Result};
@@ -17,6 +18,7 @@ pub struct RequestHandlerOpts {
pub cache_control_headers: bool,
pub page404: String,
pub page50x: String,
pub page_fallback: String,
pub basic_auth: String,
}
@@ -154,12 +156,21 @@ impl RequestHandler {
Ok(resp)
}
Err(status) => error_page::error_response(
method,
&status,
&self.opts.page404,
&self.opts.page50x,
),
Err(status) => {
if !self.opts.page_fallback.is_empty()
&& (status == StatusCode::NOT_FOUND)
&& (method == Method::GET)
{
Ok(fallback_page::fallback_response(&self.opts.page_fallback))
} else {
error_page::error_response(
method,
&status,
&self.opts.page404,
&self.opts.page50x,
)
}
}
}
}
}
@@ -12,6 +12,7 @@ pub mod config;
pub mod control_headers;
pub mod cors;
pub mod error_page;
pub mod fallback_page;
pub mod handler;
pub mod helpers;
pub mod logger;
@@ -95,6 +95,9 @@ impl Server {
let page404 = helpers::read_file_content(&opts.page404);
let page50x = helpers::read_file_content(&opts.page50x);
let page_fallback = helpers::read_file_content(&opts.page_fallback);
let threads = self.threads;
tracing::info!("runtime worker threads: {}", self.threads);
@@ -148,6 +151,7 @@ impl Server {
cache_control_headers,
page404,
page50x,
page_fallback,
basic_auth,
}),
});