Logging. CORS(*). Version in response and error type for JSON response

This commit is contained in:
Martin Berg Alstad 2024-06-13 18:58:50 +02:00
parent c1b9273e0c
commit 2a826be8ea
7 changed files with 203 additions and 12 deletions

135
Cargo.lock generated
View File

@ -98,6 +98,12 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.6.0" version = "1.6.0"
@ -262,6 +268,12 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.155" version = "0.2.155"
@ -328,6 +340,16 @@ dependencies = [
"minimal-lexical", "minimal-lexical",
] ]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.16.0" version = "1.16.0"
@ -353,6 +375,12 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -480,14 +508,26 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "simplify_truths" name = "simplify_truths"
version = "0.1.0" version = "2.0.0"
dependencies = [ dependencies = [
"axum", "axum",
"nom", "nom",
"serde", "serde",
"tokio", "tokio",
"tower-http",
"tracing",
"tracing-subscriber",
] ]
[[package]] [[package]]
@ -529,6 +569,16 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.38.0" version = "1.38.0"
@ -572,6 +622,23 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "tower-http"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
dependencies = [
"bitflags",
"bytes",
"http",
"http-body",
"http-body-util",
"pin-project-lite",
"tower-layer",
"tower-service",
"tracing",
]
[[package]] [[package]]
name = "tower-layer" name = "tower-layer"
version = "0.3.2" version = "0.3.2"
@ -592,9 +659,21 @@ checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [ dependencies = [
"log", "log",
"pin-project-lite", "pin-project-lite",
"tracing-attributes",
"tracing-core", "tracing-core",
] ]
[[package]]
name = "tracing-attributes"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "tracing-core" name = "tracing-core"
version = "0.1.32" version = "0.1.32"
@ -602,6 +681,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [
"nu-ansi-term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
] ]
[[package]] [[package]]
@ -610,12 +715,40 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"

View File

@ -1,11 +1,19 @@
[package] [package]
name = "simplify_truths" name = "simplify_truths"
version = "0.1.0" version = "2.0.0"
edition = "2021" edition = "2021"
authors = ["Martin Berg Alstad"] authors = ["Martin Berg Alstad"]
[dependencies] [dependencies]
# Parsing
nom = "7.1.3" nom = "7.1.3"
axum = "0.7.5" # Async
tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] }
# Serialization / Deserialization
serde = { version = "1.0.203", features = ["derive"] } serde = { version = "1.0.203", features = ["derive"] }
# API
axum = "0.7.5"
tower-http = { version = "0.5.2", features = ["cors", "trace"] }
# Logging
tracing = "0.1.40"
tracing-subscriber = "0.3.18"

View File

@ -5,6 +5,6 @@
}, },
"prod": { "prod": {
"expression": "", "expression": "",
"url": "https://api.martials.no/simplify-truths" "url": "https://api.martials.no/simplify-truths/v2"
} }
} }

View File

@ -1,6 +1,18 @@
### GET Atomic Expression ### GET Atomic Expression
GET {{url}}/simplify/A GET {{url}}/simplify/A
### GET Invalid Expression should return 400 Bad Request
GET {{url}}/simplify/A B
> {%
client.test("Status code is 400", () => {
client.assert(response.status === 400, "Response status is not 400");
});
client.test("Content-type is application/json", () => {
client.assert(response.headers.valueOf("content-type") === "application/json", "Content-Type is not application/json")
});
%}
### GET And Expression ### GET And Expression
< {% < {%
import {expression} from './common.js'; import {expression} from './common.js';

View File

@ -1,6 +1,10 @@
use std::net::SocketAddr; use std::net::SocketAddr;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tower_http::cors::{Any, CorsLayer};
use tower_http::trace;
use tower_http::trace::TraceLayer;
use tracing::Level;
use crate::routing::{index, simplify, table}; use crate::routing::{index, simplify, table};
@ -18,11 +22,25 @@ async fn main() {
.await .await
.unwrap(); .unwrap();
println!("Listening on: {}", listener.local_addr().unwrap()); tracing_subscriber::fmt()
.with_target(false)
.compact()
.init();
let routes = simplify::router() let routes = simplify::router()
.merge(table::router()) .merge(table::router())
.merge(index::router()); .merge(index::router());
axum::serve(listener, routes).await.unwrap(); let app = routes
.layer(CorsLayer::new().allow_origin(Any))
.layer(TraceLayer::new_for_http()
.make_span_with(trace::DefaultMakeSpan::new()
.level(Level::INFO))
.on_response(trace::DefaultOnResponse::new()
.level(Level::INFO))
);
tracing::info!("Starting server on: {addr}");
axum::serve(listener, app.into_make_service()).await.unwrap();
} }

View File

@ -33,16 +33,34 @@ struct QueryOptions {
} }
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] enum Law {
struct SimplifyResponse { // TODO
}
#[derive(Serialize)]
struct OrderOfOperation {
before: String, before: String,
after: String, after: String,
order_of_operations: Vec<String>, law: Law, // TODO
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct SimplifyResponse {
version: String, // TODO better versioning
before: String,
after: String,
order_of_operations: Vec<OrderOfOperation>,
expression: Expression, expression: Expression,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
truth_table: Option<TruthTable>, truth_table: Option<TruthTable>,
} }
#[derive(Serialize)]
struct Error {
message: String,
}
// TODO // TODO
async fn simplify(Path(path): Path<String>, query: Query<QueryOptions>, accept_language: Option<AcceptLanguage>) -> Response { async fn simplify(Path(path): Path<String>, query: Query<QueryOptions>, accept_language: Option<AcceptLanguage>) -> Response {
if let Ok(mut expression) = Expression::try_from(path.as_str()) { if let Ok(mut expression) = Expression::try_from(path.as_str()) {
@ -51,6 +69,7 @@ async fn simplify(Path(path): Path<String>, query: Query<QueryOptions>, accept_l
expression = expression.simplify(); expression = expression.simplify();
} }
Json(SimplifyResponse { Json(SimplifyResponse {
version: "2.0.0".to_string(),
before, before,
after: expression.to_string(), after: expression.to_string(),
order_of_operations: vec![], // TODO order_of_operations: vec![], // TODO
@ -58,7 +77,7 @@ async fn simplify(Path(path): Path<String>, query: Query<QueryOptions>, accept_l
truth_table: None, truth_table: None,
}).into_response() }).into_response()
} else { } else {
(StatusCode::BAD_REQUEST, "Invalid expression").into_response() (StatusCode::BAD_REQUEST, Json(Error { message: "Invalid expression".into() })).into_response()
} }
} }
@ -71,6 +90,7 @@ async fn simplify_and_table(Path(path): Path<String>, query: Query<QueryOptions>
// TODO options // TODO options
let truth_table = TruthTable::new(&expression, TruthTableOptions::default()); let truth_table = TruthTable::new(&expression, TruthTableOptions::default());
Json(SimplifyResponse { Json(SimplifyResponse {
version: "2.0.0".to_string(),
before, before,
after: expression.to_string(), after: expression.to_string(),
order_of_operations: vec![], // TODO order_of_operations: vec![], // TODO
@ -78,6 +98,6 @@ async fn simplify_and_table(Path(path): Path<String>, query: Query<QueryOptions>
truth_table: Some(truth_table), truth_table: Some(truth_table),
}).into_response() }).into_response()
} else { } else {
(StatusCode::BAD_REQUEST, "Invalid expression").into_response() (StatusCode::BAD_REQUEST, Json(Error { message: "Invalid expression".into() })).into_response()
} }
} }

View File

@ -9,5 +9,5 @@ pub fn router() -> Router<()> {
} }
async fn table() { async fn table() {
unimplemented!("Not yet implemented") unimplemented!()
} }