use http::HeaderName;
use http::HeaderValue;
use http::StatusCode;
use http::header::CONTENT_LENGTH;
use http::header::RETRY_AFTER;
use tako_rs_core::body::TakoBody;
use tako_rs_core::types::Response;
use super::store::CachedResponse;
pub(crate) fn conflict() -> Response {
conflict_response(None)
}
pub(crate) fn conflict_inflight() -> Response {
conflict_response(Some(3))
}
fn conflict_response(retry_after_secs: Option<u32>) -> Response {
let mut resp = http::Response::builder()
.status(StatusCode::CONFLICT)
.body(TakoBody::empty())
.unwrap();
if let Some(secs) = retry_after_secs {
resp.headers_mut().insert(
RETRY_AFTER,
HeaderValue::from_str(&secs.to_string()).unwrap_or_else(|_| HeaderValue::from_static("3")),
);
}
resp
}
pub(crate) fn bad_gateway() -> Response {
http::Response::builder()
.status(StatusCode::BAD_GATEWAY)
.body(TakoBody::empty())
.unwrap()
}
pub(crate) fn build_response_from_cache(c: &CachedResponse) -> Response {
let mut b = http::Response::builder().status(c.status);
let Some(headers) = b.headers_mut() else {
return http::Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(TakoBody::empty())
.expect("static 500 builder");
};
for (k, v) in &c.headers {
let _ = headers.insert(k, v.clone());
}
headers.remove(CONTENT_LENGTH);
b.body(TakoBody::from(c.body.clone())).unwrap_or_else(|_| {
http::Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(TakoBody::empty())
.expect("static 500 builder")
})
}
pub(crate) fn filter_headers(src: &http::HeaderMap) -> Vec<(HeaderName, HeaderValue)> {
const DENY: &[&str] = &[
"connection",
"keep-alive",
"proxy-authenticate",
"proxy-authorization",
"te",
"trailer",
"transfer-encoding",
"upgrade",
"content-length",
"set-cookie",
];
let mut out = Vec::with_capacity(src.keys_len());
for (name, v) in src {
let name_lc = name.as_str().to_ascii_lowercase();
if DENY.contains(&name_lc.as_str()) {
continue;
}
out.push((name.clone(), v.clone()));
}
out
}