Skip to main content

hive_router_plan_executor/plugins/hooks/
on_http_request.rs

1use ntex::{
2    http::Response,
3    web::{self, DefaultError, WebRequest},
4};
5
6use crate::{
7    plugin_context::PluginContext,
8    plugin_trait::{EndHookPayload, EndHookResult, StartHookPayload, StartHookResult},
9};
10
11pub struct OnHttpRequestHookPayload<'req> {
12    /// The raw incoming HTTP request to the router
13    /// It includes all the details of the request such as headers, body, etc.
14    ///
15    /// Example:
16    /// ```
17    /// use hive_router::{
18    ///    plugins::hooks::on_http_request::{OnHttpRequestHookPayload, OnHttpRequestHookResult},
19    /// };
20    ///
21    /// fn on_http_request<'req>(mut payload: OnHttpRequestHookPayload<'req>) -> OnHttpRequestHookResult<'req> {
22    ///     let my_header = payload.router_http_request.headers().get("my-header");
23    ///     // do something with the header...
24    ///     payload.proceed()
25    /// }
26    /// ```
27    pub router_http_request: WebRequest<DefaultError>,
28    /// The context object that can be used to share data across different plugin hooks for the same request.
29    /// It is unique per request and is dropped after the response is sent.
30    ///
31    /// [Learn more about the context data sharing in the docs](https://the-guild.dev/graphql/hive/docs/router/extensibility/plugin_system#context-data-sharing)
32    ///
33    /// Example:
34    /// ```
35    /// use hive_router::{
36    ///     plugins::hooks::{
37    ///         on_http_request::{OnHttpRequestHookPayload, OnHttpRequestHookResult},
38    ///         on_execute::{OnExecuteStartHookPayload, OnExecuteStartHookResult}    
39    ///     },
40    ///     plugin_context::PluginContext,
41    ///     async_trait::async_trait,
42    /// };
43    ///
44    /// struct ContextData {
45    ///     greetings: String
46    /// }
47    ///
48    /// #[async_trait]
49    /// impl RouterPlugin for MyPlugin {
50    ///     fn on_http_request<'req>(mut payload: OnHttpRequestHookPayload<'req>) -> OnHttpRequestHookResult<'req> {
51    ///         let context_data = ContextData {
52    ///            greetings: "Hello from context!".to_string()
53    ///         };
54    ///
55    ///        payload.context.insert(context_data);
56    ///
57    ///        payload.proceed()
58    ///     }
59    ///
60    ///     async fn on_execute<'exec>(&'exec self, payload: OnExecuteStartHookPayload<'exec>) -> OnExecuteStartHookResult<'exec> {
61    ///         let context_data = payload.context.get::<ContextData>().unwrap();
62    ///         println!("{}", context_data.greetings); // prints "Hello from context!"
63    ///         payload.proceed()
64    ///     }
65    /// }
66    /// ```
67    pub context: &'req PluginContext,
68}
69
70impl<'req> StartHookPayload<OnHttpResponseHookPayload<'req>, Response>
71    for OnHttpRequestHookPayload<'req>
72{
73}
74
75pub type OnHttpRequestHookResult<'req> = StartHookResult<
76    'req,
77    OnHttpRequestHookPayload<'req>,
78    OnHttpResponseHookPayload<'req>,
79    Response,
80>;
81
82pub struct OnHttpResponseHookPayload<'req> {
83    pub response: web::WebResponse,
84    pub context: &'req PluginContext,
85}
86
87impl<'req> OnHttpResponseHookPayload<'req> {
88    /// Manipulate the outgoing HTTP response before it's sent to the client.
89    /// This can be used to modify headers, change the body, etc.
90    ///
91    /// Example:
92    /// ```
93    /// fn on_http_request<'req>(
94    ///     &'req self,
95    ///     payload: OnHttpRequestHookPayload<'req>,
96    /// ) -> OnHttpRequestHookResult<'req> {
97    ///     payload.on_end(|payload| {
98    ///         payload.map_response(|mut response| {
99    ///             response.response_mut().headers_mut().insert(
100    ///                 "x-served-by",
101    ///                 "hive-router".parse().unwrap(),
102    ///             );
103    ///             response
104    ///         }).proceed()
105    ///     })
106    /// }
107    /// ```
108    pub fn map_response<F>(mut self, f: F) -> Self
109    where
110        F: FnOnce(web::WebResponse) -> web::WebResponse,
111    {
112        self.response = f(self.response);
113        self
114    }
115}
116
117impl<'req> EndHookPayload<Response> for OnHttpResponseHookPayload<'req> {}
118
119pub type OnHttpResponseHookResult<'req> = EndHookResult<OnHttpResponseHookPayload<'req>, Response>;