use std::sync::Mutex;
use http::{Method, uri::PathAndQuery};
use topcoat_core::context::Cx;
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()),
method: None,
cx: None,
}
}
#[derive(Debug)]
pub struct RewriteError {
path_and_query: PathAndQuery,
body: Mutex<Body>,
method: Option<Method>,
cx: Option<Cx>,
}
impl RewriteError {
#[must_use]
pub fn method(mut self, method: Method) -> Self {
self.method = Some(method);
self
}
#[must_use]
pub fn cx(mut self, cx: Cx) -> Self {
self.cx = Some(cx);
self
}
pub(crate) fn into_parts(self) -> RewriteParts {
let body = match self.body.into_inner() {
Ok(body) => body,
Err(poisoned) => poisoned.into_inner(),
};
RewriteParts {
path_and_query: self.path_and_query,
body,
method: self.method,
cx: self.cx,
}
}
}
pub(crate) struct RewriteParts {
pub(crate) path_and_query: PathAndQuery,
pub(crate) body: Body,
pub(crate) method: Option<Method>,
pub(crate) cx: Option<Cx>,
}
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 {}