ServiceExt

Trait ServiceExt 

Source
pub trait ServiceExt<Request>: Service<Request> {
    // Provided methods
    fn map_first_graphql_response<Callback>(
        self,
        callback: Callback,
    ) -> MapFirstGraphqlResponseService<Self, Callback>
       where Self: Sized + Service<Request, Response = Response>,
             <Self as Service<Request>>::Future: Send + 'static,
             Callback: FnOnce(Context, Parts, Response) -> (Parts, Response) + Clone + Send + 'static { ... }
    fn map_future_with_request_data<RF, MF>(
        self,
        req_fn: RF,
        map_fn: MF,
    ) -> MapFutureWithRequestDataService<Self, RF, MF>
       where Self: Sized,
             RF: Clone,
             MF: Clone { ... }
}
Expand description

Extension trait for Service.

Importing both this trait and tower::ServiceExt could lead a name collision error. To work around that, use as _ syntax to make a trait’s methods available in a module without assigning it a name in that module’s namespace.

use apollo_router::layers::ServiceExt as _;
use tower::ServiceExt as _;

Provided Methods§

Source

fn map_first_graphql_response<Callback>( self, callback: Callback, ) -> MapFirstGraphqlResponseService<Self, Callback>
where Self: Sized + Service<Request, Response = Response>, <Self as Service<Request>>::Future: Send + 'static, Callback: FnOnce(Context, Parts, Response) -> (Parts, Response) + Clone + Send + 'static,

Maps HTTP parts, as well as the first GraphQL response, to different values.

In supergraph and execution services, the service response contains not just one GraphQL response but a stream of them, in order to support features such as @defer.

This method wraps a service and call callback when the first GraphQL response in the stream returned by the inner service becomes available. The callback can then modify the HTTP parts (headers, status code, etc) or the first GraphQL response before returning them.

Note that any subsequent GraphQL responses after the first will be forwarded unmodified. In order to inspect or modify all GraphQL responses, consider using map_response together with supergraph::Response::map_stream instead. (See the example in map_stream’s documentation.) In that case however HTTP parts cannot be modified because they may have already been sent.

§Example
use apollo_router::services::supergraph;
use apollo_router::layers::ServiceExt as _;
use tower::ServiceExt as _;

struct ExamplePlugin;

#[async_trait::async_trait]
impl apollo_router::plugin::Plugin for ExamplePlugin {
    // …
    fn supergraph_service(&self, inner: supergraph::BoxService) -> supergraph::BoxService {
        inner
            .map_first_graphql_response(|context, mut http_parts, mut graphql_response| {
                // Something interesting here
                (http_parts, graphql_response)
            })
            .boxed()
    }
}
Source

fn map_future_with_request_data<RF, MF>( self, req_fn: RF, map_fn: MF, ) -> MapFutureWithRequestDataService<Self, RF, MF>
where Self: Sized, RF: Clone, MF: Clone,

Similar to map_future but also providing an opportunity to extract information out of the request for use when constructing the response.

§Arguments
  • req_fn: The callback to extract data from the request.
  • map_fn: The callback to map the future.

returns: ServiceBuilder<Stack<MapFutureWithRequestDataLayer<RF, MF>, L>>

§Examples
let _ : supergraph::BoxService = service
    .map_future_with_request_data(
        |req: &supergraph::Request| req.context.clone(),
        |ctx : Context, fut| async { fut.await }
    )
    .boxed();

Implementors§

Source§

impl<T, Request> ServiceExt<Request> for T
where T: Service<Request> + ?Sized,