use http::StatusCode;
use serde::{Serialize, de::DeserializeOwned};
use url::Url;
use crate::auth::Credentials;
use crate::config::{ANTHROPIC_VERSION, USER_AGENT};
use crate::error::{Error, Result, api_error_from_response};
const REQUEST_ID_HEADER: &str = "request-id";
pub(crate) fn default_headers(creds: &Credentials) -> Result<http::HeaderMap> {
let mut headers = http::HeaderMap::new();
headers.insert(
http::header::ACCEPT,
http::HeaderValue::from_static("application/json"),
);
headers.insert(
http::header::CONTENT_TYPE,
http::HeaderValue::from_static("application/json"),
);
headers.insert(
http::HeaderName::from_static("anthropic-version"),
http::HeaderValue::from_static(ANTHROPIC_VERSION),
);
headers.insert(
http::header::USER_AGENT,
http::HeaderValue::from_static(USER_AGENT),
);
creds.write_into(&mut headers)?;
Ok(headers)
}
pub(crate) async fn post_json<B, R>(
http: &reqwest::Client,
url: Url,
headers: http::HeaderMap,
body: &B,
) -> Result<R>
where
B: Serialize + ?Sized,
R: DeserializeOwned,
{
let body_bytes = serde_json::to_vec(body)?;
let response = http
.post(url)
.headers(headers)
.body(body_bytes)
.send()
.await?;
let status = response.status();
let request_id = extract_request_id(response.headers());
let raw = response.text().await?;
if status.is_success() {
serde_json::from_str::<R>(&raw).map_err(Error::from)
} else {
Err(api_error_from_response(status, request_id, raw))
}
}
#[inline]
#[allow(dead_code)]
pub(crate) fn status_to_http(s: reqwest::StatusCode) -> StatusCode {
StatusCode::from_u16(s.as_u16()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR)
}
fn extract_request_id(headers: &http::HeaderMap) -> Option<String> {
headers
.get(REQUEST_ID_HEADER)
.and_then(|v| v.to_str().ok())
.map(|s| s.to_owned())
}