use crate::{
component::AnyExtension,
host_io::{event_queue::EventQueue, http::StatusCode},
types::{
AuthorizedOperationContext, Configuration, Error, ErrorResponse, GatewayHeaders, Headers, HttpRequestParts,
OnRequestOutput, RequestContext,
},
};
#[allow(unused_variables)]
pub trait HooksExtension: Sized + 'static {
fn new(config: Configuration) -> Result<Self, Error>;
fn on_request(
&mut self,
url: &str,
method: http::Method,
headers: &mut GatewayHeaders,
) -> Result<impl IntoOnRequestOutput, ErrorResponse> {
Ok(())
}
fn on_response(
&mut self,
ctx: &RequestContext,
status: &mut http::StatusCode,
headers: &mut Headers,
event_queue: EventQueue,
) -> Result<(), Error> {
Ok(())
}
fn on_graphql_subgraph_request(
&mut self,
ctx: &AuthorizedOperationContext,
subgraph_name: &str,
parts: &mut HttpRequestParts,
) -> Result<(), Error> {
Ok(())
}
fn on_virtual_subgraph_request(
&mut self,
ctx: &AuthorizedOperationContext,
subgraph_name: &str,
headers: &mut Headers,
) -> Result<(), Error> {
Ok(())
}
}
pub trait IntoOnRequestOutput {
fn into_on_request_output(self) -> OnRequestOutput;
}
impl IntoOnRequestOutput for OnRequestOutput {
fn into_on_request_output(self) -> OnRequestOutput {
self
}
}
impl IntoOnRequestOutput for () {
fn into_on_request_output(self) -> OnRequestOutput {
OnRequestOutput::default()
}
}
#[doc(hidden)]
pub fn register<T: HooksExtension>() {
pub(super) struct Proxy<T: HooksExtension>(T);
impl<T: HooksExtension> AnyExtension for Proxy<T> {
fn on_request(
&mut self,
url: &str,
method: http::Method,
headers: &mut Headers,
) -> Result<OnRequestOutput, ErrorResponse> {
self.0
.on_request(url, method, headers)
.map(|output| output.into_on_request_output())
}
fn on_response(
&mut self,
ctx: &RequestContext,
status: &mut StatusCode,
headers: &mut Headers,
event_queue: EventQueue,
) -> Result<(), Error> {
self.0.on_response(ctx, status, headers, event_queue)
}
fn on_graphql_subgraph_request(
&mut self,
ctx: &AuthorizedOperationContext,
subgraph_name: &str,
parts: &mut HttpRequestParts,
) -> Result<(), Error> {
self.0.on_graphql_subgraph_request(ctx, subgraph_name, parts)
}
fn on_virtual_subgraph_request(
&mut self,
ctx: &AuthorizedOperationContext,
subgraph_name: &str,
headers: &mut Headers,
) -> Result<(), Error> {
self.0.on_virtual_subgraph_request(ctx, subgraph_name, headers)
}
}
crate::component::register_extension(Box::new(|_, config| {
<T as HooksExtension>::new(config).map(|extension| Box::new(Proxy(extension)) as Box<dyn AnyExtension>)
}))
}