use std::sync::Mutex;
use http::uri::PathAndQuery;
use crate::Body;
pub(crate) const REWRITE_LIMIT: usize = 8;
#[must_use]
#[track_caller]
pub fn rewrite(path: impl AsRef<str>, body: impl Into<Body>) -> RewriteError {
RewriteError {
path_and_query: PathAndQuery::try_from(path.as_ref())
.expect("rewrite path is not a valid uri path and query"),
body: Mutex::new(body.into()),
}
}
#[derive(Debug)]
pub struct RewriteError {
path_and_query: PathAndQuery,
body: Mutex<Body>,
}
impl RewriteError {
pub(crate) fn into_parts(self) -> (PathAndQuery, Body) {
let body = match self.body.into_inner() {
Ok(body) => body,
Err(poisoned) => poisoned.into_inner(),
};
(self.path_and_query, body)
}
}
impl std::fmt::Display for RewriteError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "rewrite to {}", self.path_and_query)
}
}
impl std::error::Error for RewriteError {}
#[derive(Debug)]
pub(crate) struct RewriteLoopError {
message: String,
}
impl RewriteLoopError {
pub(crate) fn cycle(visited: &[String], target: &str) -> Self {
Self {
message: format!(
"the rewrite to {target} creates a cycle: {} -> {target}",
visited.join(" -> ")
),
}
}
pub(crate) fn limit(visited: &[String], target: &str) -> Self {
Self {
message: format!(
"the request was rewritten more than {REWRITE_LIMIT} times: {} -> {target}",
visited.join(" -> ")
),
}
}
}
impl std::fmt::Display for RewriteLoopError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.message)
}
}
impl std::error::Error for RewriteLoopError {}