diff --git a/README.md b/README.md index 9cfaaf5..e95f315 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,6 @@ A test dataset of questions. Generated by [ChatGPT](https://chat.openai.com/) ### Looking ahead These are a few things still to be added #### Higher priority -* Support POST /answers * Add some simple API curl examples to this README * API documentation tooling (`utoipa`) * API testing tooling (`swagger`) @@ -74,7 +73,6 @@ These are a few things still to be added * Optimize flush/file writing: Write out the JSON in a pretty structure and avoid re-writing the whole file in cases when it can be avoid (like adding 1 item) * Use a database alltogether instead of a json file for persistance * Serve basic web page(s) to utilize all APIs -* Re-structure the application to serve API endpoint from an `api` directory, and generically serve web content from a `web` directory * Optimize the put/update handler to support path or body identification, and to update only individual fields passed. * Host application on my raspberry pi on the internet diff --git a/src/api.rs b/src/api.rs index 9a53dcf..164afdd 100644 --- a/src/api.rs +++ b/src/api.rs @@ -93,6 +93,7 @@ pub async fn delete_question( Err(e) => (StatusCode::NOT_FOUND, e).into_response(), } } + /// Create an Answer /// # Parameters /// `answer_dto` Form URL encoded answer DTO @@ -100,7 +101,6 @@ pub async fn delete_question( /// Status Created 201 and the created answer upon success /// Status Conflict 409 and message if answer with ID already exists /// Status Unprocessable Entity 422 is returned (implicitlly) for a malformed body - pub async fn create_answer( State(store): State>>, Form(answer_dto): Form, diff --git a/src/main.rs b/src/main.rs index c055b5d..da32147 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ mod question; mod store; use axum::{ extract::{Path, Query, State}, - http::StatusCode, + http::{StatusCode, Uri}, response::{IntoResponse, Response}, routing::{delete, get, post, put}, Form, Json, Router, @@ -13,22 +13,40 @@ use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, fs::File, - io::{ErrorKind, Seek, Write}, + io::{ErrorKind, Read, Seek, Write}, net::SocketAddr, + path::PathBuf, sync::Arc, }; use store::Store; use tokio::sync::RwLock; -async fn handle() -> Response { - (StatusCode::OK, "Visiting the root").into_response() -} - -//generic handler for any not supported route/method combination +// generic handler for any not supported route/method combination async fn handler_404() -> Response { (StatusCode::NOT_FOUND, "404 Not Found").into_response() } +// generic handler to serve static for non-api routes +async fn serve_file(uri: Uri) -> impl IntoResponse { + let mut path_buf: PathBuf = PathBuf::from("./src/static/").join(uri.path().trim_start_matches('/')); + if path_buf.is_dir() { + path_buf.push("index.html") + } + match File::open(path_buf) { + Ok(mut file) => { + let mut contents = Vec::new(); + match file.read_to_end(&mut contents) { + Ok(_) => axum::response::Response::builder() + .status(StatusCode::OK) + .body(axum::body::Body::from(contents)) + .unwrap(), + Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Server Error").into_response(), + } + } + Err(_) => (StatusCode::NOT_FOUND, "404 Not Found").into_response(), + } +} + #[tokio::main] async fn main() { let store: Arc> = Arc::new(RwLock::new(store::Store::new())); @@ -41,9 +59,11 @@ async fn main() { .route("/question", put(api::update_question)) .route("/question/:id", delete(api::delete_question)) .route("/answer", post(api::create_answer)) - .with_state(store) + .with_state(store); + let app = Router::new() + .nest("/api/v1", apis) + .route("/", get(serve_file)) + .route("/*path", get(serve_file)) .fallback(handler_404); - - let app = Router::new().route("/", get(handle)).merge(apis); axum::serve(listener, app).await.unwrap(); } diff --git a/src/static/cats/index.html b/src/static/cats/index.html new file mode 100644 index 0000000..4055790 --- /dev/null +++ b/src/static/cats/index.html @@ -0,0 +1,8 @@ + + + Welcome again + + + Hello cats! + + diff --git a/src/static/cats/warhol.jpg b/src/static/cats/warhol.jpg new file mode 100755 index 0000000..9799144 Binary files /dev/null and b/src/static/cats/warhol.jpg differ diff --git a/src/static/index.html b/src/static/index.html new file mode 100644 index 0000000..20d1359 --- /dev/null +++ b/src/static/index.html @@ -0,0 +1,8 @@ + + + Welcome + + + Hello world! + +