-
Notifications
You must be signed in to change notification settings - Fork 84
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
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
/// impl RequestInitialiser for AuthInit { | ||
/// fn init(&self, req: RequestBuilder) -> RequestBuilder { | ||
/// req.bearer_auth("my_auth_token") | ||
/// } | ||
/// } |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
/// 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(); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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>
There was a problem hiding this 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?
A key difference is that |
As suggested in #54 (comment)
Adds a set of
Extensions
toRequestBuilder
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 toRequestBuilder
.Adds a
Extension
RequestInitialiser which callsinsert
during the init chain