Skip to content

Commit

Permalink
Add --spa-index option
Browse files Browse the repository at this point in the history
  • Loading branch information
Billy Bradley authored and sinking-point committed Oct 8, 2021
1 parent b92663c commit 6dfe4d1
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 11 deletions.
8 changes: 8 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ pub struct CliArgs {
#[clap(long, parse(from_os_str), name = "index_file", value_hint = ValueHint::FilePath)]
pub index: Option<PathBuf>,

/// The index file of a single page application
///
/// If this option is set, miniserve will serve the specified file instead of a 404 page when
/// a non-existent path is requested. This is intended for single-page applications where
/// routing takes place on the client side.
#[clap(long, parse(from_os_str), name = "spa_index_file", value_hint = ValueHint::FilePath)]
pub spa_index: Option<PathBuf>,

/// Port to use
#[clap(short = 'p', long = "port", default_value = "8080")]
pub port: u16,
Expand Down
13 changes: 12 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ pub struct MiniserveConfig {
/// However, if a directory contains this file, miniserve will serve that file instead.
pub index: Option<std::path::PathBuf>,

/// The index file of a single page application
///
/// If this option is set, miniserve will serve the specified file instead of a 404 page when
/// a non-existent path is requested. This is intended for single-page applications where
/// routing takes place on the client side.
pub spa_index: Option<std::path::PathBuf>,

/// Enable QR code display
pub show_qrcode: bool,

Expand Down Expand Up @@ -169,6 +176,9 @@ impl MiniserveConfig {
#[cfg(not(feature = "tls"))]
let tls_rustls_server_config = None;

// If spa_index is set but index is unset, copy the former into the latter
let index = args.index.or(args.spa_index.clone());

Ok(MiniserveConfig {
verbose: args.verbose,
path: args.path.unwrap_or_else(|| PathBuf::from(".")),
Expand All @@ -183,7 +193,8 @@ impl MiniserveConfig {
css_route,
default_color_scheme,
default_color_scheme_dark,
index: args.index,
index,
spa_index: args.spa_index,
overwrite_files: args.overwrite_files,
show_qrcode: args.qrcode,
file_upload: args.file_upload,
Expand Down
47 changes: 37 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::io;
use std::io::Write;
use std::net::{IpAddr, SocketAddr, TcpListener};
use std::path::PathBuf;
use std::thread;
use std::time::Duration;

Expand Down Expand Up @@ -105,15 +106,9 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), ContextualError> {
ContextualError::IoError("Failed to resolve path to be served".to_string(), e)
})?;

if let Some(index_path) = &miniserve_config.index {
let has_index: std::path::PathBuf = [&canon_path, index_path].iter().collect();
if !has_index.exists() {
error!(
"The file '{}' provided for option --index could not be found.",
index_path.to_string_lossy()
);
}
}
check_file_exists(&canon_path, &miniserve_config.index, "index");
check_file_exists(&canon_path, &miniserve_config.spa_index, "spa-index");

let path_string = canon_path.to_string_lossy();

println!(
Expand Down Expand Up @@ -279,6 +274,19 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), ContextualError> {
.map_err(|e| ContextualError::IoError("".to_owned(), e))
}

fn check_file_exists(canon_path: &PathBuf, file_option: &Option<PathBuf>, option_name: &str) {
if let Some(file_path) = file_option {
let has_file: std::path::PathBuf = [&canon_path, file_path].iter().collect();
if !has_file.exists() {
error!(
"The file '{}' provided for option --{} could not be found.",
file_path.to_string_lossy(),
option_name,
);
}
}
}

/// Allows us to set low-level socket options
///
/// This mainly used to set `set_only_v6` socket option
Expand Down Expand Up @@ -311,6 +319,26 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
Some(index_file) => files.index_file(index_file.to_string_lossy()),
None => files,
};
let files = match &conf.spa_index {
Some(spa_index_file) => {
let spa_index_full = &conf.path.join(spa_index_file);
let spa_index_string: String = spa_index_full.to_string_lossy().into();

files.default_handler(move |req: actix_web::dev::ServiceRequest| {
let (request, _payload) = req.into_parts();
let spa_index_string = spa_index_string.clone();

async move {
let response = actix_files::NamedFile::open(
&spa_index_string
)?
.into_response(&request);
Ok(actix_web::dev::ServiceResponse::new(request, response))
}
})
},
None => files.default_handler(web::to(error_404)),
};
let files = match conf.show_hidden {
true => files.use_hidden_files(),
false => files,
Expand All @@ -320,7 +348,6 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
.files_listing_renderer(listing::directory_listing)
.prefer_utf8(true)
.redirect_to_slash_directory()
.default_handler(web::to(error_404))
};

if !conf.path.is_file() {
Expand Down

0 comments on commit 6dfe4d1

Please sign in to comment.