use std::fmt::Debug;
use layered::{Layer, Service};
use crate::{HttpRequest, HttpResponse, RequestHandler, Result};
#[derive(Debug)]
pub struct Buffering<T> {
inner: T,
}
#[derive(Debug, Clone, Copy)]
pub struct BufferingLayer;
impl Buffering<()> {
#[must_use]
pub fn layer() -> BufferingLayer {
BufferingLayer
}
}
impl<S> Layer<S> for BufferingLayer {
type Service = Buffering<S>;
fn layer(&self, inner: S) -> Self::Service {
Buffering { inner }
}
}
impl<T: RequestHandler> Service<HttpRequest> for Buffering<T> {
type Out = Result<HttpResponse>;
async fn execute(&self, input: HttpRequest) -> Result<HttpResponse> {
let response = self.inner.execute(input).await?;
let (parts, body) = response.into_parts();
let body = body.into_buffered().await?;
Ok(HttpResponse::from_parts(parts, body))
}
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use http::{StatusCode, Uri};
use http_extensions::{FakeHandler, HttpBodyBuilder, HttpRequestBuilder};
use super::*;
use crate::error_labels::collect_error_labels;
use crate::handlers::Dispatch;
#[cfg_attr(miri, ignore)]
#[tokio::test]
async fn buffers_response_body() {
let inner = Dispatch::new_fake(FakeHandler::from(StatusCode::OK));
let handler = Buffering { inner };
let request = HttpRequestBuilder::new_fake().uri("https://example.com/path").build().unwrap();
let response = handler.execute(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
assert!(response.body().try_clone().is_some());
}
#[cfg_attr(miri, ignore)]
#[tokio::test]
async fn propagates_inner_handler_error() {
let inner = Dispatch::new_fake(FakeHandler::never_completes());
let handler = Buffering { inner };
let request = http::Request::get(Uri::from_static("/no-authority"))
.body(HttpBodyBuilder::new_fake().empty())
.unwrap();
let result: Result<HttpResponse> = handler.execute(request).await;
let error = result.unwrap_err();
assert_eq!(collect_error_labels(&error), "uri_origin_missing");
}
#[cfg_attr(miri, ignore)]
#[tokio::test]
async fn layer_constructs_handler() {
let layer = Buffering::layer();
let inner = Dispatch::new_fake(FakeHandler::from(StatusCode::NO_CONTENT));
let handler = layer.layer(inner);
let request = HttpRequestBuilder::new_fake().uri("https://example.com/test").build().unwrap();
let response = handler.execute(request).await.unwrap();
assert_eq!(response.status(), StatusCode::NO_CONTENT);
}
}