use super::{MapError, ResponseError};
use assert_impl::assert_impl;
use http::{
header::{AsHeaderName, HeaderMap, HeaderValue, IntoHeaderName},
response::{Parts as HttpResponseParts, Response as HttpResponse},
status::StatusCode,
Extensions, Version,
};
use std::{
default::Default,
fmt::Debug,
mem::take,
net::IpAddr,
num::NonZeroU16,
ops::{Deref, DerefMut},
result,
time::Duration,
};
#[cfg(feature = "async")]
use futures_lite::Future;
#[derive(Debug, Clone, Default)]
pub struct Metrics {
total_duration: Option<Duration>,
name_lookup_duration: Option<Duration>,
connect_duration: Option<Duration>,
secure_connect_duration: Option<Duration>,
redirect_duration: Option<Duration>,
transfer_duration: Option<Duration>,
}
impl Metrics {
#[inline]
pub fn builder() -> MetricsBuilder {
Default::default()
}
#[inline]
pub fn total_duration(&self) -> Option<Duration> {
self.total_duration
}
#[inline]
pub fn total_duration_mut(&mut self) -> &mut Option<Duration> {
&mut self.total_duration
}
#[inline]
pub fn name_lookup_duration(&self) -> Option<Duration> {
self.name_lookup_duration
}
#[inline]
pub fn name_lookup_duration_mut(&mut self) -> &mut Option<Duration> {
&mut self.name_lookup_duration
}
#[inline]
pub fn connect_duration(&self) -> Option<Duration> {
self.connect_duration
}
#[inline]
pub fn connect_duration_mut(&mut self) -> &mut Option<Duration> {
&mut self.connect_duration
}
#[inline]
pub fn secure_connect_duration(&self) -> Option<Duration> {
self.secure_connect_duration
}
#[inline]
pub fn secure_connect_duration_mut(&mut self) -> &mut Option<Duration> {
&mut self.secure_connect_duration
}
#[inline]
pub fn redirect_duration(&self) -> Option<Duration> {
self.redirect_duration
}
#[inline]
pub fn redirect_duration_mut(&mut self) -> &mut Option<Duration> {
&mut self.redirect_duration
}
#[inline]
pub fn transfer_duration(&self) -> Option<Duration> {
self.transfer_duration
}
#[inline]
pub fn transfer_duration_mut(&mut self) -> &mut Option<Duration> {
&mut self.transfer_duration
}
}
#[derive(Debug, Clone, Default)]
pub struct MetricsBuilder(Metrics);
impl MetricsBuilder {
#[inline]
pub fn total_duration(&mut self, duration: Duration) -> &mut Self {
self.0.total_duration = Some(duration);
self
}
#[inline]
pub fn name_lookup_duration(&mut self, duration: Duration) -> &mut Self {
self.0.name_lookup_duration = Some(duration);
self
}
#[inline]
pub fn connect_duration(&mut self, duration: Duration) -> &mut Self {
self.0.connect_duration = Some(duration);
self
}
#[inline]
pub fn secure_connect_duration(&mut self, duration: Duration) -> &mut Self {
self.0.secure_connect_duration = Some(duration);
self
}
#[inline]
pub fn redirect_duration(&mut self, duration: Duration) -> &mut Self {
self.0.redirect_duration = Some(duration);
self
}
#[inline]
pub fn transfer_duration(&mut self, duration: Duration) -> &mut Self {
self.0.transfer_duration = Some(duration);
self
}
#[inline]
pub fn build(&mut self) -> Metrics {
take(&mut self.0)
}
}
#[derive(Debug, Default, Clone)]
pub(super) struct ResponseInfo {
server_ip: Option<IpAddr>,
server_port: Option<NonZeroU16>,
metrics: Option<Metrics>,
}
impl ResponseInfo {
#[inline]
pub(super) fn server_ip(&self) -> Option<IpAddr> {
self.server_ip
}
#[inline]
pub(super) fn server_port(&self) -> Option<NonZeroU16> {
self.server_port
}
#[inline]
pub(super) fn metrics(&self) -> Option<&Metrics> {
self.metrics.as_ref()
}
pub(super) fn server_ip_mut(&mut self) -> &mut Option<IpAddr> {
&mut self.server_ip
}
pub(super) fn server_port_mut(&mut self) -> &mut Option<NonZeroU16> {
&mut self.server_port
}
pub(super) fn metrics_mut(&mut self) -> &mut Option<Metrics> {
&mut self.metrics
}
}
#[derive(Debug)]
pub struct ResponseParts {
inner: HttpResponseParts,
info: ResponseInfo,
}
impl ResponseParts {
#[inline]
pub fn status_code(&self) -> StatusCode {
self.inner.status
}
#[inline]
pub fn status_code_mut(&mut self) -> &mut StatusCode {
&mut self.inner.status
}
#[inline]
pub fn headers(&self) -> &HeaderMap {
&self.inner.headers
}
#[inline]
pub fn headers_mut(&mut self) -> &mut HeaderMap {
&mut self.inner.headers
}
#[inline]
pub fn version(&self) -> Version {
self.inner.version
}
#[inline]
pub fn version_mut(&mut self) -> &mut Version {
&mut self.inner.version
}
#[inline]
pub fn extensions(&self) -> &Extensions {
&self.inner.extensions
}
#[inline]
pub fn extensions_mut(&mut self) -> &mut Extensions {
&mut self.inner.extensions
}
#[inline]
pub fn header(&self, header_name: impl AsHeaderName) -> Option<&HeaderValue> {
self.headers().get(header_name)
}
pub(super) fn into_response_info(self) -> ResponseInfo {
self.info
}
#[inline]
pub fn server_ip(&self) -> Option<IpAddr> {
self.info.server_ip()
}
#[inline]
pub fn server_ip_mut(&mut self) -> &mut Option<IpAddr> {
self.info.server_ip_mut()
}
#[inline]
pub fn server_port(&self) -> Option<NonZeroU16> {
self.info.server_port()
}
#[inline]
pub fn server_port_mut(&mut self) -> &mut Option<NonZeroU16> {
self.info.server_port_mut()
}
#[inline]
pub fn metrics(&self) -> Option<&Metrics> {
self.info.metrics()
}
#[inline]
pub fn metrics_mut(&mut self) -> &mut Option<Metrics> {
self.info.metrics_mut()
}
}
impl Default for ResponseParts {
#[inline]
fn default() -> Self {
let (parts, _) = HttpResponse::new(()).into_parts();
Self {
inner: parts,
info: Default::default(),
}
}
}
#[derive(Debug, Default)]
pub struct Response<B> {
parts: ResponseParts,
body: B,
}
impl<B: Default> Response<B> {
#[inline]
pub fn builder() -> ResponseBuilder<B> {
ResponseBuilder::<B>::default()
}
}
impl<B> Response<B> {
#[inline]
pub fn body(&self) -> &B {
&self.body
}
#[inline]
pub fn body_mut(&mut self) -> &mut B {
&mut self.body
}
#[inline]
pub fn parts(&self) -> &ResponseParts {
&self.parts
}
#[inline]
pub fn parts_mut(&mut self) -> &mut ResponseParts {
&mut self.parts
}
#[inline]
pub fn into_body(self) -> B {
self.body
}
#[inline]
pub fn into_parts_and_body(self) -> (ResponseParts, B) {
let Self { parts, body } = self;
(parts, body)
}
#[inline]
pub fn from_parts_and_body(parts: ResponseParts, body: B) -> Self {
Response { parts, body }
}
#[inline]
pub fn map_body<B2>(self, f: impl FnOnce(B) -> B2) -> Response<B2> {
let (parts, body) = self.into_parts_and_body();
let body = f(body);
Response::from_parts_and_body(parts, body)
}
#[inline]
pub fn try_map_body<B2, E>(
self,
f: impl FnOnce(B) -> result::Result<B2, E>,
) -> result::Result<Response<B2>, MapError<E>> {
let (parts, body) = self.into_parts_and_body();
match f(body) {
Ok(body) => Ok(Response::from_parts_and_body(parts, body)),
Err(err) => Err(MapError::new(err, parts)),
}
}
#[inline]
#[cfg(feature = "async")]
pub async fn try_async_map_body<B2, E, F, Fut>(self, f: F) -> result::Result<Response<B2>, MapError<E>>
where
F: FnOnce(B) -> Fut,
Fut: Future<Output = result::Result<B2, E>>,
{
let (parts, body) = self.into_parts_and_body();
match f(body).await {
Ok(body) => Ok(Response::from_parts_and_body(parts, body)),
Err(err) => Err(MapError::new(err, parts)),
}
}
}
impl<B> Deref for Response<B> {
type Target = ResponseParts;
#[inline]
fn deref(&self) -> &Self::Target {
&self.parts
}
}
impl<B> DerefMut for Response<B> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.parts
}
}
impl<B: Send + Sync> Response<B> {
#[allow(dead_code)]
fn ignore() {
assert_impl!(Send: Self);
assert_impl!(Sync: Self);
}
}
#[derive(Debug, Default)]
pub struct ResponseBuilder<B> {
inner: Response<B>,
}
impl<B> ResponseBuilder<B> {
#[inline]
pub fn status_code(&mut self, status_code: StatusCode) -> &mut Self {
*self.inner.status_code_mut() = status_code;
self
}
#[inline]
pub fn headers(&mut self, headers: HeaderMap) -> &mut Self {
*self.inner.headers_mut() = headers;
self
}
#[inline]
pub fn version(&mut self, version: Version) -> &mut Self {
*self.inner.version_mut() = version;
self
}
#[inline]
pub fn server_ip(&mut self, server_ip: IpAddr) -> &mut Self {
*self.inner.info.server_ip_mut() = Some(server_ip);
self
}
#[inline]
pub fn server_port(&mut self, server_port: NonZeroU16) -> &mut Self {
*self.inner.info.server_port_mut() = Some(server_port);
self
}
#[inline]
pub fn extensions(&mut self, extensions: Extensions) -> &mut Self {
*self.inner.extensions_mut() = extensions;
self
}
#[inline]
pub fn header(&mut self, header_name: impl IntoHeaderName, header_value: impl Into<HeaderValue>) -> &mut Self {
self.inner.headers_mut().insert(header_name, header_value.into());
self
}
#[inline]
pub fn body(&mut self, body: B) -> &mut Self {
*self.inner.body_mut() = body;
self
}
#[inline]
pub fn metrics(&mut self, metrics: Metrics) -> &mut Self {
*self.inner.metrics_mut() = Some(metrics);
self
}
}
impl<B: Default> ResponseBuilder<B> {
#[inline]
pub fn build(&mut self) -> Response<B> {
take(&mut self.inner)
}
}
mod body {
use assert_impl::assert_impl;
use std::{
default::Default,
fmt::Debug,
io::{Cursor, Read, Result as IoResult},
};
trait ReadDebug: Read + Debug + Send {}
impl<T: Read + Debug + Send> ReadDebug for T {}
#[derive(Debug)]
pub struct ResponseBody(ResponseBodyInner);
#[derive(Debug)]
enum ResponseBodyInner {
Reader(Box<dyn ReadDebug>),
Bytes(Cursor<Vec<u8>>),
}
impl ResponseBody {
#[inline]
pub fn from_reader(reader: impl Read + Debug + Send + 'static) -> Self {
Self(ResponseBodyInner::Reader(Box::new(reader)))
}
#[inline]
pub fn from_bytes(bytes: Vec<u8>) -> Self {
Self(ResponseBodyInner::Bytes(Cursor::new(bytes)))
}
#[allow(dead_code)]
fn ignore() {
assert_impl!(Send: Self);
}
}
impl Default for ResponseBody {
#[inline]
fn default() -> Self {
Self::from_bytes(Default::default())
}
}
impl Read for ResponseBody {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
match &mut self.0 {
ResponseBodyInner::Reader(reader) => reader.read(buf),
ResponseBodyInner::Bytes(bytes) => bytes.read(buf),
}
}
}
#[cfg(feature = "async")]
mod async_body {
use assert_impl::assert_impl;
use futures_lite::{
io::{AsyncRead, Cursor, Result as IoResult},
pin,
};
use std::{
fmt::Debug,
pin::Pin,
task::{Context, Poll},
};
trait AsyncReadDebug: AsyncRead + Unpin + Debug + Send + Sync {}
impl<T: AsyncRead + Unpin + Debug + Send + Sync> AsyncReadDebug for T {}
#[derive(Debug)]
#[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
pub struct AsyncResponseBody(AsyncResponseBodyInner);
#[derive(Debug)]
enum AsyncResponseBodyInner {
Reader(Box<dyn AsyncReadDebug>),
Bytes(Cursor<Vec<u8>>),
}
impl AsyncResponseBody {
#[inline]
pub fn from_reader(reader: impl AsyncRead + Unpin + Debug + Send + Sync + 'static) -> Self {
Self(AsyncResponseBodyInner::Reader(Box::new(reader)))
}
#[inline]
pub fn from_bytes(bytes: Vec<u8>) -> Self {
Self(AsyncResponseBodyInner::Bytes(Cursor::new(bytes)))
}
#[allow(dead_code)]
fn ignore() {
assert_impl!(Send: Self);
assert_impl!(Sync: Self);
}
}
impl Default for AsyncResponseBody {
#[inline]
fn default() -> Self {
Self::from_bytes(Default::default())
}
}
impl AsyncRead for AsyncResponseBody {
fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context, buf: &mut [u8]) -> Poll<IoResult<usize>> {
match &mut self.as_mut().0 {
AsyncResponseBodyInner::Reader(reader) => {
pin!(reader);
reader.poll_read(cx, buf)
}
AsyncResponseBodyInner::Bytes(bytes) => {
pin!(bytes);
bytes.poll_read(cx, buf)
}
}
}
}
}
#[cfg(feature = "async")]
pub use async_body::*;
}
pub use body::ResponseBody;
#[cfg(feature = "async")]
pub use body::AsyncResponseBody;
pub type Result<B> = result::Result<Response<B>, ResponseError>;