Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extensions middleware and request extensions #56

Merged
merged 7 commits into from
Sep 30, 2022

Conversation

conradludgate
Copy link
Collaborator

@conradludgate conradludgate commented Aug 30, 2022

As suggested in #54 (comment)

Adds a set of Extensions to RequestBuilder so that requests can have some default extensions provided.

Adds a new way to configure requests: RequestInitialiser - it's a simple sync trait that just applies basic settings to RequestBuilder.

Adds a Extension RequestInitialiser which calls insert during the init chain

@conradludgate conradludgate requested a review from a team as a code owner August 30, 2022 15:50
@conradludgate conradludgate marked this pull request as draft August 30, 2022 16:21
@conradludgate

This comment was marked as resolved.

@conradludgate

This comment was marked as resolved.

@conradludgate conradludgate marked this pull request as ready for review August 30, 2022 18:14
@conradludgate conradludgate mentioned this pull request Aug 30, 2022
@conradludgate conradludgate added the reqwest-middleware Issues related to the core middleware lib label Aug 30, 2022
Comment on lines +13 to +17
/// impl RequestInitialiser for AuthInit {
/// fn init(&self, req: RequestBuilder) -> RequestBuilder {
/// req.bearer_auth("my_auth_token")
/// }
/// }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can already be done with existing middleware via Request::headers_mut, maybe we should use a more motivating example that's harder to do with the Request struct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can probably elaborate more - this is a client wide setting. Imagine you have a client that has many endpoints but all use the same auth settings, then those can be define in a RequestInitialiser on the top level connection

Comment on lines +49 to +73
/// impl Middleware for LoggingMiddleware {
/// async fn handle(
/// &self,
/// req: Request,
/// extensions: &mut Extensions,
/// next: Next<'_>,
/// ) -> Result<Response> {
/// // get the log name or default to "unknown"
/// let name = extensions
/// .get()
/// .map(|&LogName(name)| name)
/// .unwrap_or("unknown");
/// println!("[{name}] Request started {req:?}");
/// let res = next.run(req, extensions).await;
/// println!("[{name}] Result: {res:?}");
/// res
/// }
/// }
///
/// async fn run() {
/// let reqwest_client = Client::builder().build().unwrap();
/// let client = ClientBuilder::new(reqwest_client)
/// .with_init(Extension(LogName("my-client")))
/// .with(LoggingMiddleware)
/// .build();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this example couldn't the LogName have been baked into LoggingMiddleware. Or if the latter was a shared thing, a wrapper middleware used. I'm not seeing the motivating case for the new abstractions from this example very clearly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I thought I added the extra example. The case is where you might have a client wide extension, and then you can have a per-request configuration too.

let client = ClientBuilder::new(reqwest_client)
    .with_init(Extension(LogName("my-client")))
    .with(LoggingMiddleware)
    .build();
    
// uses "my-client" as the log name
client.get("https://truelayer.com").send().await

// uses "create-payment" as the log name
client.post("https://api.truelayer.com/payment")
    .with_extension(LogName("create-payment"))
    .send()
    .await

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this is something I want to supplement #54 because I'm not keen on breaking the current SpanBackend trait to add &self just yet, but it does have access to the extensions.

The desired configuration by the author was to have client wide configuration of the span name, but I think a request specific span name might be more desirable in some situations. So this is the best of both worlds for configuration

Co-authored-by: Alex Butler <alexheretic@gmail.com>
Copy link
Contributor

@tl-rodrigo-gryzinski tl-rodrigo-gryzinski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we considered a numerical priority for middlewares and sorting based on that? Seems more general than having two hardcoded levels under different traits, am I missing the point?

@conradludgate
Copy link
Collaborator Author

Have we considered a numerical priority for middlewares and sorting based on that? Seems more general than having two hardcoded levels under different traits, am I missing the point?

A key difference is that RequestInitialiser applies to the RequestBuilder, whereas Middleware applies to the Request

@conradludgate conradludgate merged commit 85e520f into main Sep 30, 2022
@conradludgate conradludgate deleted the extensions-middleware branch September 30, 2022 09:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
reqwest-middleware Issues related to the core middleware lib
Development

Successfully merging this pull request may close these issues.

3 participants