Browse Source

Log HTTP responses and POST requests

pull/39/head
Rodolphe Breard 4 years ago
parent
commit
0c8b0d3e53
  1. 13
      acmed/src/acme_proto/http.rs
  2. 50
      acmed/src/http.rs

13
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::<AccountResponse>()?;
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::<Order>()?;
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)
}

50
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<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),
@ -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())
}
@ -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>(
@ -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>,
{
@ -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());
@ -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>,
{

Loading…
Cancel
Save