diff --git a/backend/src/net/static_server.rs b/backend/src/net/static_server.rs
index 23b9055bdf..3db1d5dce0 100644
--- a/backend/src/net/static_server.rs
+++ b/backend/src/net/static_server.rs
@@ -28,6 +28,7 @@ use crate::net::HttpHandler;
use crate::{diagnostic_api, install_api, main_api, setup_api, Error, ErrorKind, ResultExt};
static NOT_FOUND: &[u8] = b"Not Found";
+static METHOD_NOT_ALLOWED: &[u8] = b"Method Not Allowed";
static NOT_AUTHORIZED: &[u8] = b"Not Authorized";
pub const MAIN_UI_WWW_DIR: &str = "/var/www/html/main";
@@ -238,41 +239,26 @@ async fn alt_ui(req: Request
, ui_mode: UiMode) -> Result, E
.filter_map(|s| s.split(";").next())
.map(|s| s.trim())
.collect::>();
- match request_parts.uri.path() {
- "/" => {
- let full_path = PathBuf::from(selected_root_dir).join("index.html");
-
- file_send(full_path, &accept_encoding).await
- }
- _ => {
- match (
- request_parts.method,
- request_parts
- .uri
- .path()
- .strip_prefix('/')
- .unwrap_or(request_parts.uri.path())
- .split_once('/'),
- ) {
- (Method::GET, None) => {
- let uri_path = request_parts
- .uri
- .path()
- .strip_prefix('/')
- .unwrap_or(request_parts.uri.path());
-
- let full_path = PathBuf::from(selected_root_dir).join(uri_path);
- file_send(full_path, &accept_encoding).await
- }
-
- (Method::GET, Some((dir, file))) => {
- let full_path = PathBuf::from(selected_root_dir).join(dir).join(file);
- file_send(full_path, &accept_encoding).await
- }
-
- _ => Ok(not_found()),
- }
+ match &request_parts.method {
+ &Method::GET => {
+ let uri_path = request_parts
+ .uri
+ .path()
+ .strip_prefix('/')
+ .unwrap_or(request_parts.uri.path());
+
+ let full_path = Path::new(selected_root_dir).join(uri_path);
+ file_send(
+ if tokio::fs::metadata(&full_path).await.is_ok() {
+ full_path
+ } else {
+ Path::new(selected_root_dir).join("index.html")
+ },
+ &accept_encoding,
+ )
+ .await
}
+ _ => Ok(method_not_allowed()),
}
}
@@ -289,114 +275,72 @@ async fn main_embassy_ui(req: Request, ctx: RpcContext) -> Result>();
- match request_parts.uri.path() {
- "/" => {
- let full_path = PathBuf::from(selected_root_dir).join("index.html");
-
- file_send(full_path, &accept_encoding).await
- }
- _ => {
- let valid_session = HasValidSession::from_request_parts(&request_parts, &ctx).await;
-
- match valid_session {
- Ok(_valid) => {
- match (
- request_parts.method,
- request_parts
- .uri
- .path()
- .strip_prefix('/')
- .unwrap_or(request_parts.uri.path())
- .split_once('/'),
- ) {
- (Method::GET, Some(("public", path))) => {
- let sub_path = Path::new(path);
- if let Ok(rest) = sub_path.strip_prefix("package-data") {
- file_send(
- ctx.datadir.join(PKG_PUBLIC_DIR).join(rest),
- &accept_encoding,
- )
- .await
- } else if let Ok(rest) = sub_path.strip_prefix("eos") {
- match rest.to_str() {
- Some("local.crt") => {
- file_send(
- crate::net::ssl::ROOT_CA_STATIC_PATH,
- &accept_encoding,
- )
- .await
- }
- None => Ok(bad_request()),
- _ => Ok(not_found()),
- }
- } else {
- Ok(not_found())
+ match (
+ &request_parts.method,
+ request_parts
+ .uri
+ .path()
+ .strip_prefix('/')
+ .unwrap_or(request_parts.uri.path())
+ .split_once('/'),
+ ) {
+ (&Method::GET, Some(("public", path))) => {
+ match HasValidSession::from_request_parts(&request_parts, &ctx).await {
+ Ok(_) => {
+ let sub_path = Path::new(path);
+ if let Ok(rest) = sub_path.strip_prefix("package-data") {
+ file_send(
+ ctx.datadir.join(PKG_PUBLIC_DIR).join(rest),
+ &accept_encoding,
+ )
+ .await
+ } else if let Ok(rest) = sub_path.strip_prefix("eos") {
+ match rest.to_str() {
+ Some("local.crt") => {
+ file_send(crate::net::ssl::ROOT_CA_STATIC_PATH, &accept_encoding)
+ .await
}
+ None => Ok(bad_request()),
+ _ => Ok(not_found()),
}
- (Method::GET, Some(("eos", "local.crt"))) => {
- file_send(
- PathBuf::from(crate::net::ssl::ROOT_CA_STATIC_PATH),
- &accept_encoding,
- )
- .await
- }
-
- (Method::GET, None) => {
- let uri_path = request_parts
- .uri
- .path()
- .strip_prefix('/')
- .unwrap_or(request_parts.uri.path());
-
- let full_path = PathBuf::from(selected_root_dir).join(uri_path);
- file_send(full_path, &accept_encoding).await
- }
-
- (Method::GET, Some((dir, file))) => {
- let full_path = PathBuf::from(selected_root_dir).join(dir).join(file);
- file_send(full_path, &accept_encoding).await
- }
-
- _ => Ok(not_found()),
+ } else {
+ Ok(not_found())
}
}
- Err(err) => {
- match (
- request_parts.method,
- request_parts
- .uri
- .path()
- .strip_prefix('/')
- .unwrap_or(request_parts.uri.path())
- .split_once('/'),
- ) {
- (Method::GET, Some(("public", _path))) => {
- un_authorized(err, request_parts.uri.path())
- }
- (Method::GET, Some(("eos", "local.crt"))) => {
- un_authorized(err, request_parts.uri.path())
- }
- (Method::GET, None) => {
- let uri_path = request_parts
- .uri
- .path()
- .strip_prefix('/')
- .unwrap_or(request_parts.uri.path());
-
- let full_path = PathBuf::from(selected_root_dir).join(uri_path);
- file_send(full_path, &accept_encoding).await
- }
-
- (Method::GET, Some((dir, file))) => {
- let full_path = PathBuf::from(selected_root_dir).join(dir).join(file);
- file_send(full_path, &accept_encoding).await
- }
-
- _ => Ok(not_found()),
- }
+ Err(e) => un_authorized(e, &format!("public/{path}")),
+ }
+ }
+ (&Method::GET, Some(("eos", "local.crt"))) => {
+ match HasValidSession::from_request_parts(&request_parts, &ctx).await {
+ Ok(_) => {
+ file_send(
+ PathBuf::from(crate::net::ssl::ROOT_CA_STATIC_PATH),
+ &accept_encoding,
+ )
+ .await
}
+ Err(e) => un_authorized(e, "eos/local.crt"),
}
}
+ (&Method::GET, _) => {
+ let uri_path = request_parts
+ .uri
+ .path()
+ .strip_prefix('/')
+ .unwrap_or(request_parts.uri.path());
+
+ let full_path = Path::new(selected_root_dir).join(uri_path);
+ file_send(
+ if tokio::fs::metadata(&full_path).await.is_ok() {
+ full_path
+ } else {
+ Path::new(selected_root_dir).join("index.html")
+ },
+ &accept_encoding,
+ )
+ .await
+ }
+ _ => Ok(method_not_allowed()),
}
}
@@ -417,6 +361,14 @@ fn not_found() -> Response {
.unwrap()
}
+/// HTTP status code 405
+fn method_not_allowed() -> Response {
+ Response::builder()
+ .status(StatusCode::METHOD_NOT_ALLOWED)
+ .body(METHOD_NOT_ALLOWED.into())
+ .unwrap()
+}
+
fn server_error(err: Error) -> Response {
Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
@@ -439,30 +391,31 @@ async fn file_send(
let path = path.as_ref();
- if let Ok(file) = File::open(path).await {
- let metadata = file.metadata().await.with_kind(ErrorKind::Filesystem)?;
-
- match IsNonEmptyFile::new(&metadata, path) {
- Some(a) => a,
- None => return Ok(not_found()),
- };
-
- let mut builder = Response::builder().status(StatusCode::OK);
- builder = with_e_tag(path, &metadata, builder)?;
- builder = with_content_type(path, builder);
- builder = with_content_length(&metadata, builder);
- let body = if accept_encoding.contains(&"br") {
- Body::wrap_stream(ReaderStream::new(BrotliEncoder::new(BufReader::new(file))))
- } else if accept_encoding.contains(&"gzip") {
- Body::wrap_stream(ReaderStream::new(GzipEncoder::new(BufReader::new(file))))
- } else {
- Body::wrap_stream(ReaderStream::new(file))
- };
- return builder.body(body).with_kind(ErrorKind::Network);
- }
- tracing::debug!("File not found: {:?}", path);
+ let file = File::open(path)
+ .await
+ .with_ctx(|_| (ErrorKind::Filesystem, path.display().to_string()))?;
+ let metadata = file
+ .metadata()
+ .await
+ .with_ctx(|_| (ErrorKind::Filesystem, path.display().to_string()))?;
+
+ match IsNonEmptyFile::new(&metadata, path) {
+ Some(a) => a,
+ None => return Ok(not_found()),
+ };
- Ok(not_found())
+ let mut builder = Response::builder().status(StatusCode::OK);
+ builder = with_e_tag(path, &metadata, builder)?;
+ builder = with_content_type(path, builder);
+ builder = with_content_length(&metadata, builder);
+ let body = if accept_encoding.contains(&"br") {
+ Body::wrap_stream(ReaderStream::new(BrotliEncoder::new(BufReader::new(file))))
+ } else if accept_encoding.contains(&"gzip") {
+ Body::wrap_stream(ReaderStream::new(GzipEncoder::new(BufReader::new(file))))
+ } else {
+ Body::wrap_stream(ReaderStream::new(file))
+ };
+ builder.body(body).with_kind(ErrorKind::Network)
}
struct IsNonEmptyFile(());