diff options
| author | Arnaud Bailly <arnaud@pankzsoft.com> | 2025-10-09 12:47:18 +0200 |
|---|---|---|
| committer | Arnaud Bailly <arnaud@pankzsoft.com> | 2025-10-09 12:49:27 +0200 |
| commit | bf7f549e309a4da97def326b3fdf19a4d8833450 (patch) | |
| tree | b9a0777ab20a1b41b16b3fd9087af465879ab05d | |
| parent | 3050ae41c4e74b8bfa12aca31ab3af4c83ac5379 (diff) | |
| download | lambda-nantes-bf7f549e309a4da97def326b3fdf19a4d8833450.tar.gz | |
feat: can serve and receive Json or Sexp
depending on Registration by client
| -rw-r--r-- | lambda-calcul/rust/Cargo.toml | 2 | ||||
| -rw-r--r-- | lambda-calcul/rust/README.md | 8 | ||||
| -rw-r--r-- | lambda-calcul/rust/src/web.rs | 64 |
3 files changed, 50 insertions, 24 deletions
diff --git a/lambda-calcul/rust/Cargo.toml b/lambda-calcul/rust/Cargo.toml index 230e422..51185e5 100644 --- a/lambda-calcul/rust/Cargo.toml +++ b/lambda-calcul/rust/Cargo.toml @@ -14,7 +14,7 @@ env_logger = "0.8" log = "0.4" futures = "0.3.30" async-std = "1.13.0" -reqwest = "0.12.8" +reqwest = { version = "0.12.8", features = ["json"] } tokio = { version = "1.40.0", features = ["rt", "macros", "rt-multi-thread"]} clap = { version = "4.5.19", features = ["derive"] } proptest = "1.0.0" diff --git a/lambda-calcul/rust/README.md b/lambda-calcul/rust/README.md index 0b13e5c..08dfc3d 100644 --- a/lambda-calcul/rust/README.md +++ b/lambda-calcul/rust/README.md @@ -26,9 +26,14 @@ We use the following variables to represent, well, variable elements that should The client needs to send a `POST /register` request, passing in as payload a JSON object with a `url` and `name` string fields: ``` -curl -v -X POST -d '{"url":"${CLIENT_URL}", "name": "toto"}' -H 'Content-type: application/json' ${SERVER_BASE_URL}/register +curl -v -X POST -d '{"url":"${CLIENT_URL}", "name": "toto", "encoding": "Json"}' -H 'Content-type: application/json' ${SERVER_BASE_URL}/register ``` +The payload is expected to be a JSON object with the following fields: +* `url`: The client URL for the server to callback and send expressions to evaluate +* `name`: The name of this client +* _(Optional)_ `encoding`: Which encoding to use to receive expressions and send responses. One of `Json` or `Sexp`, defaulting to `Json`. + Notes: * Obviously, client needs to start a HTTP server able to respond to a `GET` request at the given URL. To check or troubleshoot connectivity, one can use the [netcat](https://linux.die.net/man/1/nc) program to fire up a local server with `nc -l 12345` and use the ip and port to register the client. This will echo in the terminal whatever the _server_ sends @@ -74,6 +79,7 @@ There are `--port` and `--host` arguments should one want to change the default * [ ] persist user state to avoid losing connections * [ ] deploy automatically server on punkachien.net with radicle CI * [ ] better JSON representation for AST than raw serde stuff +* [ ] Document JSON format... * [ ] ask people to implement something * [ ] prepare starter kit to overcome diff --git a/lambda-calcul/rust/src/web.rs b/lambda-calcul/rust/src/web.rs index ad6bc03..5bc8c3f 100644 --- a/lambda-calcul/rust/src/web.rs +++ b/lambda-calcul/rust/src/web.rs @@ -96,7 +96,7 @@ enum TestResult { } impl Client { - fn new(url: String, name: String, delay: Duration) -> Self { + fn new(url: String, name: String, delay: Duration, encoding: AstEncoding) -> Self { let id = Uuid::new_v4(); let runner = TestRunner::new_with_rng( Config::default(), @@ -110,7 +110,7 @@ impl Client { runner, results: Vec::new(), delay, - encoding: AstEncoding::Json, + encoding, } } @@ -213,6 +213,7 @@ impl AppState for State { registration.url.clone(), registration.name.clone(), self.base_duration, + registration.encoding.clone().unwrap_or(AstEncoding::Json), ); let id = client.id.to_string(); let client_ref = Arc::new(Mutex::new(client)); @@ -362,17 +363,7 @@ async fn send_one_test(client_m: &Arc<Mutex<Client>>, sleep: Duration) { let encoding = client_m.lock().unwrap().encoding.clone(); - let request = match encoding { - AstEncoding::Json => serde_json::to_string(&input).unwrap(), - _ => input - .iter() - .map(|v| format!("{}", v)) - .collect::<Vec<_>>() - .join("\n"), - }; - let response: Result<Vec<Value>, TestResult> = send_test(&request, &url, sleep) - .await - .and_then(|r| serde_json::from_str(&r).map_err(|e| TestResult::TestFailed(e.to_string()))); + let response: Result<Vec<Value>, TestResult> = send_test(&input, &url, encoding, sleep).await; apply_result(client_m, expected, response); } @@ -391,22 +382,50 @@ fn sleep_time(client_m: &Arc<Mutex<Client>>) -> Duration { client_m.lock().unwrap().time_to_next_test() } -async fn send_test(input: &String, url: &String, timeout: Duration) -> Result<String, TestResult> { - info!("Sending {} to {}", input, url); - let body = input.clone(); +async fn send_test( + input: &Vec<Value>, + url: &String, + encoding: AstEncoding, + timeout: Duration, +) -> Result<Vec<Value>, TestResult> { + info!("Sending {:?} to {}", input, url); + + let body = match encoding { + AstEncoding::Json => serde_json::to_string(&input).unwrap(), + AstEncoding::Sexp => input + .iter() + .map(|v| format!("{}", v)) + .collect::<Vec<_>>() + .join("\n"), + }; + let content_type = match encoding { + AstEncoding::Json => "application/json", + AstEncoding::Sexp => "text/plain", + }; + let response = reqwest::Client::new() .post(url) .timeout(timeout) - .header("content-type", "text/plain") + .header("content-type", content_type) .body(body) .send() .await; + match response { - Ok(response) => { - let body = response.text().await.unwrap(); - info!("Response from {}: {}", url, body); - Ok(body) - } + Ok(response) => match encoding { + AstEncoding::Json => { + let body = response.json().await.unwrap(); + info!("Response from {}: {:?}", url, body); + Ok(body) + } + AstEncoding::Sexp => { + let body = response.text().await.unwrap(); + info!("Response from {}: {}", url, body); + let exprs = + parse_total(&body).map_err(|e| TestResult::TestFailed(e.to_string()))?; + Ok(exprs) + } + }, Err(e) => { info!("Error sending test: {}", e); Err(TestResult::ErrorSendingTest(e.to_string())) @@ -625,6 +644,7 @@ mod app_tests { "http://1.2.3.4".to_string(), "foo".to_string(), Duration::from_secs(10), + AstEncoding::Json, ) } |
