Compare commits
No commits in common. "e627581f6673fb8ceefc7c3318c1164e86d1efc8" and "99a68b9f89da3644e561194ceaaf95b03a3ddcdd" have entirely different histories.
e627581f66
...
99a68b9f89
|
@ -19,4 +19,3 @@ Cargo.lock
|
||||||
# Added by cargo
|
# Added by cargo
|
||||||
|
|
||||||
/target
|
/target
|
||||||
.idea
|
|
||||||
|
|
12
Cargo.toml
12
Cargo.toml
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "mirror-server"
|
name = "mirror-server"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Dorian Pula <dorian.pula@amber-penguin-software.ca>"]
|
authors = ["Dorian Pula <dorian.pula@amber-penguin-software.ca>"]
|
||||||
description = "A simple server for mirror HTTP requests for testing."
|
description = "A simple server for mirror HTTP requests for testing."
|
||||||
|
@ -16,12 +16,6 @@ section = "web"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = "0.7"
|
actix-web = "4"
|
||||||
clap = { version = "4.4", features = ["derive"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
|
||||||
tokio = { version = "1.36", features = ["macros", "rt-multi-thread"] }
|
|
||||||
tower = "0.4"
|
|
||||||
tower-http = { version = "0.5", features = ["trace"] }
|
|
||||||
tracing = "0.1"
|
|
||||||
tracing-subscriber = "0.3"
|
|
||||||
|
|
|
@ -11,14 +11,13 @@ 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
|
||||||
|
|
||||||
Download the DEB file, and install it:
|
Download the DEB file, and install it:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
VERSION=0.3.0
|
VERSION=0.2.0
|
||||||
REPO_URL=https://code.birch-tree.net/api/packages/dorian/generic/mirror-server/
|
REPO_URL=https://code.birch-tree.net/api/packages/dorian/generic/mirror-server/
|
||||||
curl "${REPO_URL}/${VERSION}/mirror-server_${VERSION}_amd64.deb"
|
curl "${REPO_URL}/${VERSION}/mirror-server_${VERSION}_amd64.deb"
|
||||||
sudo dpkg -i "mirror-server-${VERSION}_amd64.deb"
|
sudo dpkg -i "mirror-server-${VERSION}_amd64.deb"
|
||||||
|
@ -26,8 +25,6 @@ sudo dpkg -i "mirror-server-${VERSION}_amd64.deb"
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* [x] Migrate actix to axum for easier maintainability.
|
* [ ] Add logging to server.
|
||||||
* [x] Add mirroring of JSON request.
|
|
||||||
* [x] 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.
|
||||||
|
|
92
src/main.rs
92
src/main.rs
|
@ -1,14 +1,7 @@
|
||||||
use axum::{
|
use actix_web::{web::Json, App, HttpRequest, HttpServer, Responder};
|
||||||
extract::{Host, OriginalUri, Json},
|
|
||||||
http::{header::HeaderMap, Method},
|
|
||||||
Router,
|
|
||||||
};
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value;
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use tower_http::trace;
|
|
||||||
use tracing::{Level, info, warn};
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
|
@ -22,69 +15,50 @@ struct CliArgs {
|
||||||
ips: String,
|
ips: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct EchoHeader {
|
||||||
|
name: String,
|
||||||
|
value: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct EchoResponse {
|
struct EchoResponse {
|
||||||
method: String,
|
method: String,
|
||||||
path: String,
|
path: String,
|
||||||
host: String,
|
host: String,
|
||||||
headers: BTreeMap<String, String>,
|
headers: BTreeMap<String, String>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
body: Option<Value>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn echo_request(
|
impl EchoResponse {
|
||||||
method: Method,
|
fn new(req: &HttpRequest) -> Self {
|
||||||
original_uri: OriginalUri,
|
let req_uri = req.uri();
|
||||||
host: Host,
|
let mut headers = BTreeMap::new();
|
||||||
header_map: HeaderMap,
|
for (header_name, header_value) in req.headers().iter() {
|
||||||
body: Option<Json<Value>>
|
headers.insert(
|
||||||
) -> Json<EchoResponse> {
|
header_name.to_string(),
|
||||||
let method = method.to_string();
|
header_value.to_str().unwrap_or("ERROR").to_string(),
|
||||||
let host = host.0;
|
);
|
||||||
let path = original_uri.path().to_string();
|
}
|
||||||
let headers = header_map
|
EchoResponse {
|
||||||
.iter()
|
method: req.method().to_string(),
|
||||||
.map(|(name, value)| (name.to_string(), value.to_str().unwrap_or("").to_string()))
|
path: req_uri.path().to_string(),
|
||||||
.collect();
|
host: req_uri.host().unwrap_or("").to_string(),
|
||||||
|
|
||||||
let json_body = match body {
|
|
||||||
None => {
|
|
||||||
warn!("Received a non-JSON body.");
|
|
||||||
None
|
|
||||||
},
|
|
||||||
Some(Json(value)) => Some(value),
|
|
||||||
};
|
|
||||||
let response = EchoResponse {
|
|
||||||
method,
|
|
||||||
host,
|
|
||||||
path,
|
|
||||||
headers,
|
headers,
|
||||||
body: json_body,
|
}
|
||||||
};
|
}
|
||||||
Json(response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
async fn echo_request(request: HttpRequest) -> actix_web::Result<impl Responder> {
|
||||||
async fn main() {
|
let echo = EchoResponse::new(&request);
|
||||||
|
Ok(Json(echo))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() -> std::io::Result<()> {
|
||||||
let cli_args = CliArgs::parse();
|
let cli_args = CliArgs::parse();
|
||||||
let listen_on = (cli_args.ips, cli_args.port);
|
let listen_on = (cli_args.ips, cli_args.port);
|
||||||
let listen_on = format!("{ip}:{port}", ip = listen_on.0, port = listen_on.1);
|
HttpServer::new(|| App::new().default_service(actix_web::web::route().to(echo_request)))
|
||||||
|
.bind(listen_on)?
|
||||||
// From https://stackoverflow.com/questions/75009289/how-to-enable-logging-tracing-with-axum
|
.run()
|
||||||
tracing_subscriber::fmt()
|
|
||||||
.with_max_level(Level::INFO)
|
|
||||||
.init();
|
|
||||||
let app = Router::new().fallback(echo_request).layer(
|
|
||||||
trace::TraceLayer::new_for_http()
|
|
||||||
.make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
|
|
||||||
.on_response(trace::DefaultOnResponse::new().level(Level::INFO)),
|
|
||||||
);
|
|
||||||
|
|
||||||
info!("Starting the mirror-server to listen to {}", listen_on);
|
|
||||||
let listener = tokio::net::TcpListener::bind(&listen_on)
|
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|_| panic!("Failed to binding to {}", listen_on));
|
|
||||||
axum::serve(listener, app)
|
|
||||||
.await
|
|
||||||
.expect("Server should start");
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue