use crate::{Body, StatusCode};
mod into_response;
pub use cot_macros::IntoResponse;
pub use into_response::{
IntoResponse, WithBody, WithContentType, WithExtension, WithHeader, WithStatus,
};
const RESPONSE_BUILD_FAILURE: &str = "Failed to build response";
pub type Response = http::Response<Body>;
pub type ResponseHead = http::response::Parts;
mod private {
pub trait Sealed {}
}
pub trait ResponseExt: Sized + private::Sealed {
#[must_use]
fn builder() -> http::response::Builder;
#[must_use]
#[deprecated(since = "0.5.0", note = "Use Redirect::new() instead")]
fn new_redirect<T: Into<String>>(location: T) -> Self;
}
impl private::Sealed for Response {}
impl ResponseExt for Response {
fn builder() -> http::response::Builder {
http::Response::builder()
}
fn new_redirect<T: Into<String>>(location: T) -> Self {
http::Response::builder()
.status(StatusCode::SEE_OTHER)
.header(http::header::LOCATION, location.into())
.body(Body::empty())
.expect(RESPONSE_BUILD_FAILURE)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Redirect(String);
impl Redirect {
#[must_use]
pub fn new<T: Into<String>>(location: T) -> Self {
Self(location.into())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::body::BodyInner;
use crate::headers::JSON_CONTENT_TYPE;
use crate::response::{Response, ResponseExt};
#[test]
#[cfg(feature = "json")]
fn response_new_json() {
#[derive(serde::Serialize)]
struct MyData {
hello: String,
}
let data = MyData {
hello: String::from("world"),
};
let response = crate::json::Json(data).into_response().unwrap();
assert_eq!(response.status(), StatusCode::OK);
assert_eq!(
response.headers().get(http::header::CONTENT_TYPE).unwrap(),
JSON_CONTENT_TYPE
);
match &response.body().inner {
BodyInner::Fixed(fixed) => {
assert_eq!(fixed, r#"{"hello":"world"}"#);
}
_ => {
panic!("Expected fixed body");
}
}
}
#[test]
#[expect(deprecated)]
fn response_new_redirect() {
let location = "http://example.com";
let response = Response::new_redirect(location);
assert_eq!(response.status(), StatusCode::SEE_OTHER);
assert_eq!(
response.headers().get(http::header::LOCATION).unwrap(),
location
);
}
#[test]
fn response_new_redirect_struct() {
let location = "http://example.com";
let response = Redirect::new(location).into_response().unwrap();
assert_eq!(response.status(), StatusCode::SEE_OTHER);
assert_eq!(
response.headers().get(http::header::LOCATION).unwrap(),
location
);
}
}