From 5d0396e3654c19634947879c44bc9c291e8ede95 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Wed, 24 Jul 2024 10:48:29 +0200 Subject: [PATCH] set_first_user: try improving error reporting Problem: When there is an issue ("trying to use reserved username") it is reported as > Anyhow(Backend call failed with status 422 and text '["There is a conflict between the entered\nusername and an existing username.\nTry another one."]') (which is a wrapped `ServiceError::BackendError`) even though the CLI is ready to handle a `ServiceError::WrongUser` Solution: let BaseHTTPClient::put return a deserialized response but this commit still does not parse the JSON and does not convert the Err --- rust/agama-lib/src/base_http_client.rs | 23 ++++++++++++++++++----- rust/agama-lib/src/users/http_client.rs | 13 ++++++++++--- rust/agama-server/src/users/web.rs | 16 +++++++++------- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/rust/agama-lib/src/base_http_client.rs b/rust/agama-lib/src/base_http_client.rs index 1738fbc2ce..b835af15e5 100644 --- a/rust/agama-lib/src/base_http_client.rs +++ b/rust/agama-lib/src/base_http_client.rs @@ -129,15 +129,27 @@ impl BaseHTTPClient { /// /// * `path`: path relative to HTTP API like `/users/first` /// * `object`: Object that can be serialiazed to JSON as body of request. - pub async fn put(&self, path: &str, object: &impl Serialize) -> Result<(), ServiceError> { - let response = self.put_response(path, object).await?; + pub async fn put(&self, path: &str, object: &impl Serialize) -> Result + where + T: DeserializeOwned + std::fmt::Debug, + { + let response = self.request_response(reqwest::Method::PUT, path, object).await?; if response.status().is_success() { - Ok(()) + if let Some(clen) = response.content_length() { + if clen == 0 { + println!("empty body"); + } + } + + let ret = response.json::().await.map_err(|e| e.into()); + println!("PUT returns: {:#?}", ret); + ret } else { Err(self.build_backend_error(response).await) } } + /// FIXME redoc /// post object to given path and returns server response. Reports error only if failed to send /// request, but if server returns e.g. 500, it will be in Ok result. /// @@ -147,13 +159,14 @@ impl BaseHTTPClient { /// /// * `path`: path relative to HTTP API like `/questions` /// * `object`: Object that can be serialiazed to JSON as body of request. - pub async fn put_response( + pub async fn request_response( &self, + method: reqwest::Method, path: &str, object: &impl Serialize, ) -> Result { self.client - .put(self.url(path)) + .request(method, self.url(path)) .json(object) .send() .await diff --git a/rust/agama-lib/src/users/http_client.rs b/rust/agama-lib/src/users/http_client.rs index e400198dcc..b1ec789dfc 100644 --- a/rust/agama-lib/src/users/http_client.rs +++ b/rust/agama-lib/src/users/http_client.rs @@ -25,9 +25,16 @@ impl UsersHttpClient { &self, first_user: &FirstUser, ) -> Result<(bool, Vec), ServiceError> { - self.client.put("/users/first", first_user).await?; - // TODO: make BaseHTTPClient.put(_response) return the issues - Ok((true, vec!())) + let result: Result, ServiceError> = self.client.put("/users/first", first_user).await; + if let Err(ServiceError::BackendError(422, ref issues_s)) = result { + // way to go: + // deserialize json from string + // and use (void) put + println!("ISSUUUS {}", issues_s); + } + + let issues = result?; + Ok((issues.is_empty(), issues)) } async fn root_config(&self) -> Result { diff --git a/rust/agama-server/src/users/web.rs b/rust/agama-server/src/users/web.rs index 12be77bf59..5f3617b386 100644 --- a/rust/agama-server/src/users/web.rs +++ b/rust/agama-server/src/users/web.rs @@ -175,15 +175,17 @@ async fn set_first_user( // issues: for example, trying to use a system user id; empty password // success: simply !issues.is_empty() let (_success, issues) = state.users.set_first_user(&config).await?; - if issues.is_empty() { - Ok((StatusCode::NO_CONTENT, ().into_response())) + let status = if issues.is_empty() { + StatusCode::OK } else { - Ok(( - StatusCode::UNPROCESSABLE_ENTITY, - Json(issues).into_response(), - )) - } + StatusCode::UNPROCESSABLE_ENTITY + }; + + Ok(( + status, + Json(issues).into_response(), + )) } #[utoipa::path(get, path = "/users/first", responses(