use crate::{Error, Response, Result};
use bytes::{Bytes, BytesMut};
use http_body_util::Full;
use hyper::header;
use std::borrow::Cow;
static CONTENT_TYPE_TEXT: header::HeaderValue =
header::HeaderValue::from_static("text/plain; charset=utf-8");
static CONTENT_TYPE_OCTET: header::HeaderValue =
header::HeaderValue::from_static("application/octet-stream");
pub trait IntoResponse {
fn into_response(self) -> Result;
}
impl IntoResponse for Full<Bytes> {
fn into_response(self) -> Result {
let response = hyper::http::Response::builder().body(self)?.into();
Ok(response)
}
}
impl IntoResponse for &'static str {
fn into_response(self) -> Result {
Cow::Borrowed(self).into_response()
}
}
impl IntoResponse for String {
fn into_response(self) -> Result {
Cow::<'static, str>::Owned(self).into_response()
}
}
impl IntoResponse for Cow<'static, str> {
fn into_response(self) -> Result {
let mut res = Full::from(self).into_response()?;
res
.inner
.headers_mut()
.insert(header::CONTENT_TYPE, CONTENT_TYPE_TEXT.clone());
Ok(res)
}
}
impl<T, E> IntoResponse for std::result::Result<T, E>
where
T: IntoResponse,
E: IntoResponse,
{
fn into_response(self) -> Result {
match self {
Ok(response) => response.into_response(),
Err(err) => err.into_response(),
}
}
}
impl IntoResponse for Error {
fn into_response(self) -> Result {
let val = self.to_string();
Response::with_status(500, val)
}
}
impl IntoResponse for () {
fn into_response(self) -> Result {
let response = hyper::http::Response::builder()
.body(Full::new(Bytes::default()))?
.into();
Ok(response)
}
}
impl IntoResponse for (hyper::StatusCode, String) {
fn into_response(self) -> Result {
let response = hyper::http::Response::builder()
.header(header::CONTENT_TYPE, CONTENT_TYPE_TEXT.clone())
.status(self.0)
.body(Full::new(Bytes::from(self.1)))?
.into();
Ok(response)
}
}
impl IntoResponse for (hyper::StatusCode, &'static str) {
fn into_response(self) -> Result {
let response = hyper::http::Response::builder()
.header(header::CONTENT_TYPE, CONTENT_TYPE_TEXT.clone())
.status(self.0)
.body(Full::new(Bytes::from(self.1)))?
.into();
Ok(response)
}
}
impl IntoResponse for (u16, String) {
fn into_response(self) -> Result {
let response = hyper::http::Response::builder()
.header(header::CONTENT_TYPE, CONTENT_TYPE_TEXT.clone())
.status(hyper::StatusCode::from_u16(self.0)?)
.body(Full::new(Bytes::from(self.1)))?
.into();
Ok(response)
}
}
impl IntoResponse for (u16, &'static str) {
fn into_response(self) -> Result {
let response = hyper::http::Response::builder()
.header(header::CONTENT_TYPE, CONTENT_TYPE_TEXT.clone())
.status(hyper::StatusCode::from_u16(self.0)?)
.body(Full::new(Bytes::from(self.1)))?
.into();
Ok(response)
}
}
impl IntoResponse for Bytes {
fn into_response(self) -> Result {
let mut res = Full::from(self).into_response()?;
res
.inner
.headers_mut()
.insert(header::CONTENT_TYPE, CONTENT_TYPE_OCTET.clone());
Ok(res)
}
}
impl IntoResponse for BytesMut {
fn into_response(self) -> Result {
self.freeze().into_response()
}
}
impl IntoResponse for crate::Response {
fn into_response(self) -> Result {
Ok(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_into_response_static_str() {
let response: Result = "hello".into_response();
assert!(response.is_ok());
assert_eq!(response.unwrap().status(), hyper::StatusCode::OK);
}
#[test]
fn test_into_response_string() {
let response: Result = String::from("hello").into_response();
assert!(response.is_ok());
}
#[test]
fn test_into_response_unit() {
let response: Result = ().into_response();
assert!(response.is_ok());
}
#[test]
fn test_into_response_status_code_and_str() {
let response: Result = (hyper::StatusCode::NOT_FOUND, "Not Found").into_response();
assert!(response.is_ok());
assert_eq!(response.unwrap().status(), hyper::StatusCode::NOT_FOUND);
}
#[test]
fn test_into_response_u16_and_str() {
let response: Result = (404, "Not Found").into_response();
assert!(response.is_ok());
assert_eq!(response.unwrap().status(), hyper::StatusCode::NOT_FOUND);
}
#[test]
fn test_into_response_result_ok() {
let response: Result = Ok::<&str, &str>("ok").into_response();
assert!(response.is_ok());
}
#[test]
fn test_into_response_result_err() {
let response: Result = Err::<(), &str>("error").into_response();
assert!(response.is_ok());
}
#[test]
fn test_into_response_bytes() {
let bytes: Bytes = Bytes::from(vec![1, 2, 3]);
let response: Result = bytes.into_response();
assert!(response.is_ok());
}
}