Skip to content

Commit

Permalink
src: lib: web: Move and improve app router
Browse files Browse the repository at this point in the history
Improvements:
- Versionize API using default_api_version CLI arg
- 404 handling unified
- Add permissive cors
- Add tracing log for http requests
- Remove trailing slashes from URIs
  • Loading branch information
joaoantoniocardoso committed Nov 14, 2024
1 parent 02e4d2c commit f10482f
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 28 deletions.
34 changes: 11 additions & 23 deletions src/lib/web/mod.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
mod endpoints;
pub mod routes;

use std::net::SocketAddr;

use axum::{extract::ws::Message, http::StatusCode, routing::get, Router};
use tokio::{
signal,
sync::{broadcast, mpsc, RwLock},
};
use axum::{extract::Request, ServiceExt};
use tokio::signal;
use tower::Layer;
use tower_http::normalize_path::NormalizePathLayer;
use tracing::*;

fn default_router() -> Router {
Router::new()
.route("/", get(endpoints::root))
.route("/:path", get(endpoints::root))
.fallback(get(|| async { (StatusCode::NOT_FOUND, "Not found :(") }))
}

pub async fn run(address: std::net::SocketAddrV4) {
let router = default_router();

let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(1));
let mut first = true;
loop {
Expand All @@ -36,16 +26,14 @@ pub async fn run(address: std::net::SocketAddrV4) {
}
};

let app = NormalizePathLayer::trim_trailing_slash().layer(routes::router());
let service = ServiceExt::<Request>::into_make_service_with_connect_info::<SocketAddr>(app);

info!("Running web server on address {address:?}");

if let Err(error) = axum::serve(
listener,
router
.clone()
.into_make_service_with_connect_info::<SocketAddr>(),
)
.with_graceful_shutdown(shutdown_signal())
.await
if let Err(error) = axum::serve(listener, service)
.with_graceful_shutdown(shutdown_signal())
.await
{
error!("WebServer error: {error}");
continue;
Expand Down
36 changes: 31 additions & 5 deletions src/lib/web/endpoints.rs → src/lib/web/routes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
pub mod v1;

use axum::{
extract::Path,
http::{header, StatusCode},
response::IntoResponse,
routing::get,
Router,
};
use include_dir::{include_dir, Dir};
use mime_guess::from_path;
use tower_http::{cors::CorsLayer, trace::TraceLayer};
use tracing::*;

use crate::cli;

static HTML_DIST: Dir = include_dir!("src/webpage/dist");

pub async fn root(filename: Option<Path<String>>) -> impl IntoResponse {
#[instrument(level = "trace")]
pub fn router() -> Router {
let app = Router::new()
.route_service("/", get(root))
.route("/:path", get(root))
.nest("/v1", v1::router())
.fallback(handle_404())
.layer(CorsLayer::permissive())
.layer(TraceLayer::new_for_http());

match cli::default_api_version() {
1 => app.merge(v1::router()),
_ => unimplemented!(),
}
}

#[instrument(level = "trace")]
async fn root(filename: Option<Path<String>>) -> impl IntoResponse {
let filename = filename
.map(|Path(name)| {
if name.is_empty() {
Expand All @@ -20,10 +45,7 @@ pub async fn root(filename: Option<Path<String>>) -> impl IntoResponse {
.unwrap_or_else(|| "index.html".into());

HTML_DIST.get_file(&filename).map_or_else(
|| {
// Return 404 Not Found if the file doesn't exist
(StatusCode::NOT_FOUND, "404 Not Found").into_response()
},
|| handle_404().into_response(),
|file| {
// Determine the MIME type based on the file extension
let mime_type = from_path(&filename).first_or_octet_stream();
Expand All @@ -32,3 +54,7 @@ pub async fn root(filename: Option<Path<String>>) -> impl IntoResponse {
},
)
}

fn handle_404() -> (StatusCode, &'static str) {
(StatusCode::NOT_FOUND, "404 Not Found")
}

0 comments on commit f10482f

Please sign in to comment.