micro_web/date/
date_service_decorator.rs

1//! Module for handling HTTP response date headers.
2//!
3//! This module provides functionality for automatically adding RFC 7231 compliant
4//! date headers to HTTP responses. It implements a wrapper pattern that can be
5//! composed with other wrappers in the request handling pipeline.
6//!
7//! The main components are:
8//! - `DateWrapper`: A wrapper that adds date handling capability
9//! - `DateResponseHandler`: The actual handler that adds the Date header to responses
10//!
11//! The Date header is added according to RFC 7231 Section 7.1.1.2
12
13use crate::date::DateService;
14use crate::handler::RequestHandler;
15use crate::handler::handler_decorator::HandlerDecorator;
16use crate::handler::handler_decorator_factory::HandlerDecoratorFactory;
17use crate::{OptionReqBody, RequestContext, ResponseBody};
18use async_trait::async_trait;
19use http::Response;
20
21/// A wrapper that adds automatic date header handling to responses.
22///
23/// This wrapper creates a `DateResponseHandler` that will add an RFC 7231 compliant
24/// Date header to all HTTP responses.
25#[derive(Debug, Clone)]
26pub struct DateServiceDecorator;
27
28/// A request handler that adds the Date header to responses.
29///
30/// This handler wraps another handler and adds the Date header to its responses.
31/// The Date header is generated using a shared `DateService` instance to avoid
32/// unnecessary system calls.
33#[derive(Debug)]
34pub struct DateResponseHandler<H> {
35    handler: H,
36    // todo: we need to ensure data_service is singleton
37    date_service: &'static DateService,
38}
39
40impl<H: RequestHandler> HandlerDecorator<H> for DateServiceDecorator {
41    type Output = DateResponseHandler<H>;
42
43    fn decorate(&self, raw: H) -> Self::Output {
44        DateResponseHandler { handler: raw, date_service: DateService::get_global_instance() }
45    }
46}
47
48impl HandlerDecoratorFactory for DateServiceDecorator {
49    type Output<In>
50        = DateServiceDecorator
51    where
52        In: RequestHandler;
53
54    fn create_decorator<In>(&self) -> Self::Output<In>
55    where
56        In: RequestHandler,
57    {
58        DateServiceDecorator
59    }
60}
61
62#[async_trait]
63impl<H: RequestHandler> RequestHandler for DateResponseHandler<H> {
64    async fn invoke<'server, 'req>(&self, req: &mut RequestContext<'server, 'req>, req_body: OptionReqBody) -> Response<ResponseBody> {
65        let mut resp = self.handler.invoke(req, req_body).await;
66
67        self.date_service.with_http_date(|date_header_value| {
68            resp.headers_mut().insert(http::header::DATE, date_header_value);
69        });
70
71        resp
72    }
73}