Skip to content

Commit

Permalink
Log HTTP responses and POST requests
Browse files Browse the repository at this point in the history
  • Loading branch information
breard-r committed Sep 26, 2020
1 parent 8477d92 commit 0c8b0d3
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 17 deletions.
13 changes: 4 additions & 9 deletions acmed/src/acme_proto/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<AccountResponse>()?;
Ok((acc_resp, acc_uri))
}
Expand All @@ -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::<Order>()?;
Ok((order_resp, order_uri))
}
Expand Down Expand Up @@ -169,6 +165,5 @@ where
http::CONTENT_TYPE_JOSE,
http::CONTENT_TYPE_PEM,
)?;
let crt_pem = response.text()?;
Ok(crt_pem)
Ok(response.body)
}
50 changes: 42 additions & 8 deletions acmed/src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> {
match self.headers.get(name) {
Some(r) => match header_to_string(r) {
Ok(h) => Some(h),
Err(_) => None,
},
None => None,
}
}

pub fn json<T>(&self) -> Result<T, Error>
where
T: serde::de::DeserializeOwned,
{
serde_json::from_str(&self.body).map_err(Error::from)
}

fn from_response(response: Response) -> Result<Self, Error> {
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),
Expand Down Expand Up @@ -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<String, Error> {
fn header_to_string(header_value: &header::HeaderValue) -> Result<String, Error> {
let s = header_value
.to_str()
.map_err(|_| Error::from("invalid nonce format"))?;
.map_err(|_| Error::from("invalid header format"))?;
Ok(s.to_string())
}

Expand Down Expand Up @@ -130,14 +162,14 @@ pub fn get(
endpoint: &mut Endpoint,
root_certs: &[String],
url: &str,
) -> Result<Response, HttpError> {
) -> Result<ValidHttpResponse, HttpError> {
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<F>(
Expand All @@ -147,7 +179,7 @@ pub fn post<F>(
data_builder: &F,
content_type: &str,
accept: &str,
) -> Result<Response, HttpError>
) -> Result<ValidHttpResponse, HttpError>
where
F: Fn(&str, &str) -> Result<String, Error>,
{
Expand All @@ -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::<HttpApiError>()?;
let resp = ValidHttpResponse::from_response(response)?;
let api_err = resp.json::<HttpApiError>()?;
let acme_err = api_err.get_acme_type();
if !acme_err.is_recoverable() {
return Err(api_err.into());
Expand All @@ -185,7 +219,7 @@ pub fn post_jose<F>(
root_certs: &[String],
url: &str,
data_builder: &F,
) -> Result<Response, HttpError>
) -> Result<ValidHttpResponse, HttpError>
where
F: Fn(&str, &str) -> Result<String, Error>,
{
Expand Down

0 comments on commit 0c8b0d3

Please sign in to comment.