diff --git a/acmed/src/acme_proto/http.rs b/acmed/src/acme_proto/http.rs index b069329..bee5aff 100644 --- a/acmed/src/acme_proto/http.rs +++ b/acmed/src/acme_proto/http.rs @@ -53,10 +53,8 @@ where let url = endpoint.dir.new_account.clone(); let response = http::post_jose(endpoint, root_certs, &url, data_builder)?; let acc_uri = response - .headers() - .get(http::HEADER_LOCATION) + .get_header(http::HEADER_LOCATION) .ok_or_else(|| Error::from("no account location found"))?; - let acc_uri = http::header_to_string(&acc_uri)?; let acc_resp = response.json::()?; Ok((acc_resp, acc_uri)) } @@ -72,10 +70,8 @@ where let url = endpoint.dir.new_order.clone(); let response = http::post_jose(endpoint, root_certs, &url, data_builder)?; let order_uri = response - .headers() - .get(http::HEADER_LOCATION) - .ok_or_else(|| Error::from("no order location found"))?; - let order_uri = http::header_to_string(&order_uri)?; + .get_header(http::HEADER_LOCATION) + .ok_or_else(|| Error::from("no account location found"))?; let order_resp = response.json::()?; Ok((order_resp, order_uri)) } @@ -169,6 +165,5 @@ where http::CONTENT_TYPE_JOSE, http::CONTENT_TYPE_PEM, )?; - let crt_pem = response.text()?; - Ok(crt_pem) + Ok(response.body) } diff --git a/acmed/src/http.rs b/acmed/src/http.rs index 2396bfe..4022cd2 100644 --- a/acmed/src/http.rs +++ b/acmed/src/http.rs @@ -13,6 +13,38 @@ pub const CONTENT_TYPE_PEM: &str = "application/pem-certificate-chain"; pub const HEADER_NONCE: &str = "Replay-Nonce"; pub const HEADER_LOCATION: &str = "Location"; +pub struct ValidHttpResponse { + headers: attohttpc::header::HeaderMap, + pub body: String, +} + +impl ValidHttpResponse { + pub fn get_header(&self, name: &str) -> Option { + match self.headers.get(name) { + Some(r) => match header_to_string(r) { + Ok(h) => Some(h), + Err(_) => None, + }, + None => None, + } + } + + pub fn json(&self) -> Result + where + T: serde::de::DeserializeOwned, + { + serde_json::from_str(&self.body).map_err(Error::from) + } + + fn from_response(response: Response) -> Result { + let (_status, headers, body) = response.split(); + let body = body.text()?; + log::trace!("HTTP response headers: {:?}", headers); + log::trace!("HTTP response body: {}", body); + Ok(ValidHttpResponse { headers, body }) + } +} + #[derive(Clone, Debug)] pub enum HttpError { ApiError(HttpApiError), @@ -97,10 +129,10 @@ fn rate_limit(endpoint: &mut Endpoint) { endpoint.rl.block_until_allowed(); } -pub fn header_to_string(header_value: &header::HeaderValue) -> Result { +fn header_to_string(header_value: &header::HeaderValue) -> Result { let s = header_value .to_str() - .map_err(|_| Error::from("invalid nonce format"))?; + .map_err(|_| Error::from("invalid header format"))?; Ok(s.to_string()) } @@ -130,14 +162,14 @@ pub fn get( endpoint: &mut Endpoint, root_certs: &[String], url: &str, -) -> Result { +) -> Result { let mut session = get_session(root_certs)?; session.try_header(header::ACCEPT, CONTENT_TYPE_JSON)?; rate_limit(endpoint); let response = session.get(url).send()?; update_nonce(endpoint, &response)?; check_status(&response)?; - Ok(response) + ValidHttpResponse::from_response(response).map_err(HttpError::from) } pub fn post( @@ -147,7 +179,7 @@ pub fn post( data_builder: &F, content_type: &str, accept: &str, -) -> Result +) -> Result where F: Fn(&str, &str) -> Result, { @@ -161,14 +193,16 @@ where let nonce = &endpoint.nonce.clone().unwrap_or_default(); let body = data_builder(&nonce, url)?; rate_limit(endpoint); + log::trace!("POST request body: {}", body); let response = session.post(url).text(&body).send()?; update_nonce(endpoint, &response)?; match check_status(&response) { Ok(_) => { - return Ok(response); + return ValidHttpResponse::from_response(response).map_err(HttpError::from); } Err(_) => { - let api_err = response.json::()?; + let resp = ValidHttpResponse::from_response(response)?; + let api_err = resp.json::()?; let acme_err = api_err.get_acme_type(); if !acme_err.is_recoverable() { return Err(api_err.into()); @@ -185,7 +219,7 @@ pub fn post_jose( root_certs: &[String], url: &str, data_builder: &F, -) -> Result +) -> Result where F: Fn(&str, &str) -> Result, {