Break out into using axum extractor.

Add support for JSON extraction.
This commit is contained in:
Dorian Pula 2024-02-07 10:12:40 -05:00
parent 2ed659e3ad
commit 6a7869a80c
3 changed files with 39 additions and 23 deletions

View File

@ -19,4 +19,5 @@ section = "web"
axum = "0.7" axum = "0.7"
clap = { version = "4.4", features = ["derive"] } clap = { version = "4.4", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.113"
tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] }

View File

@ -11,6 +11,7 @@ A simple server for mirroring HTTP requests for testing.
* Create a DEB package: * Create a DEB package:
* Install cargo-deb: `cargo install cargo-deb` * Install cargo-deb: `cargo install cargo-deb`
* Create the DEB package: `cargo deb` * Create the DEB package: `cargo deb`
* Faster builds using [cargo-watch](https://watchexec.github.io/#cargo-watch): `cargo watch -x run`
## Install ## Install
@ -25,7 +26,8 @@ sudo dpkg -i "mirror-server-${VERSION}_amd64.deb"
## TODO ## TODO
* [ ] Migrate actix to axum for easier maintainability. * [x] Migrate actix to axum for easier maintainability.
* [x] Add mirroring of JSON request.
* [ ] Add logging to server. * [ ] Add logging to server.
* [ ] Add convenience path to access logging for a certain date / records. * [ ] Add convenience path to access logging for a certain date / records.
* [ ] Dockerize mirror-server for easier distribution. * [ ] Dockerize mirror-server for easier distribution.

View File

@ -1,9 +1,11 @@
use axum::{ use axum::{
extract::{Json, Request}, extract::{Host, OriginalUri, Json},
http::{header::HeaderMap, Method},
Router, Router,
}; };
use clap::Parser; use clap::Parser;
use serde::Serialize; use serde::Serialize;
use serde_json::{json, Value};
use std::collections::BTreeMap; use std::collections::BTreeMap;
#[derive(Parser)] #[derive(Parser)]
@ -30,29 +32,40 @@ struct EchoResponse {
path: String, path: String,
host: String, host: String,
headers: BTreeMap<String, String>, headers: BTreeMap<String, String>,
body: Value,
} }
impl EchoResponse { async fn echo_request(
fn new(req: &Request) -> Self { method: Method,
let req_uri = req.uri(); original_uri: OriginalUri,
let mut headers = BTreeMap::new(); host: Host,
for (header_name, header_value) in req.headers().iter() { header_map: HeaderMap,
headers.insert( body: Option<Json<Value>>
header_name.to_string(), ) -> Json<EchoResponse> {
header_value.to_str().unwrap_or("ERROR").to_string(), let method = method.to_string();
); let host = host.0;
} let path = original_uri.path().to_string();
EchoResponse { let headers = header_map
method: req.method().to_string(), .iter()
path: req_uri.path().to_string(), .map(|(name, value)| (name.to_string(), value.to_str().unwrap_or("").to_string()))
host: req_uri.host().unwrap_or("").to_string(), .collect();
// TODO: Logging the method and path.
let json_body = match body {
None => {
// TODO: Adding logging.
json!({"error": "Non-JSON request sent."})
},
Some(Json(value)) => value,
};
let response = EchoResponse {
method,
host,
path,
headers, headers,
} body: json_body,
} };
} Json(response)
async fn echo_request(request: Request) -> Json<EchoResponse> {
Json(EchoResponse::new(&request))
} }
#[tokio::main] #[tokio::main]
@ -64,7 +77,7 @@ async fn main() {
let app = Router::new().fallback(echo_request); let app = Router::new().fallback(echo_request);
let listener = tokio::net::TcpListener::bind(&listen_on) let listener = tokio::net::TcpListener::bind(&listen_on)
.await .await
.expect(&format!("Attempted binding to {}", listen_on)); .unwrap_or_else(|_| panic!("Attempted binding to {}", listen_on));
axum::serve(listener, app) axum::serve(listener, app)
.await .await
.expect("Server should start"); .expect("Server should start");