Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #389 +/- ##
========================================
Coverage 100.0% 100.0%
========================================
Files 224 226 +2
Lines 16187 16325 +138
========================================
+ Hits 16187 16325 +138 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a new http_extensions::routing module to resolve and inject a templated_uri::BaseUri into outgoing request targets, with configurable conflict behavior when a target URI already includes a base.
Changes:
- Add
http_extensions::routingwithRouting,RoutingContext, andBaseUriConflict, plus tests. - Add
templated_uri::Uri::into_parts()to split aUriinto(base_uri, path_and_query)for recomposition. - Add a new
uri_conflicterror label and anAsRef<Clock>impl forHttpBodyBuilder, plus changelog entries.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/templated_uri/src/uri.rs | Adds Uri::into_parts() for extracting base + path/query components. |
| crates/templated_uri/CHANGELOG.md | Adds an Unreleased entry for the templated_uri change (currently mismatched to the actual API). |
| crates/http_extensions/src/routing/routing_context.rs | Introduces RoutingContext passed to routing resolvers. |
| crates/http_extensions/src/routing/routing.rs | Implements routing strategies, conflict policy handling, request URI update helper, and tests. |
| crates/http_extensions/src/routing/mod.rs | Adds routing module docs and re-exports. |
| crates/http_extensions/src/lib.rs | Exposes the new routing module publicly. |
| crates/http_extensions/src/error_labels.rs | Adds LABEL_URI_CONFLICT for routing conflict validation errors. |
| crates/http_extensions/src/body/builder.rs | Adds impl AsRef<Clock> for HttpBodyBuilder and updates trait assertions in tests. |
| crates/http_extensions/CHANGELOG.md | Adds an Unreleased entry for the new routing module. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| self.try_into() | ||
| } | ||
|
|
||
| /// Returns the [`BaseUri`] and path and query of the URI as a tuple. |
There was a problem hiding this comment.
The doc comment says this returns the BaseUri and path/query, but the signature returns optional values and the second element is a TargetPathAndQuery (not necessarily a concrete PathAndQuery). Consider rewording to reflect what is actually returned.
| /// Returns the [`BaseUri`] and path and query of the URI as a tuple. | |
| /// Returns the optional [`BaseUri`] and optional [`TargetPathAndQuery`] components of the URI as a tuple. |
| /// Creates a new [`RoutingContext`] for the first (and only) attempt. | ||
| #[must_use] | ||
| pub fn new() -> Self { | ||
| Self::default() |
There was a problem hiding this comment.
RoutingContext::new() is documented as "first (and only) attempt", but it currently uses Default which sets is_last_attempt to false. Either set is_last_attempt to true in new()/Default or adjust the docs so callers don’t get misleading attempt metadata by default.
| Self::default() | |
| Self { | |
| is_last_attempt: true, | |
| ..Self::default() | |
| } |
| //! - [`Routing::default`] - returns no [`BaseUri`] (the target [`Uri`] is used as-is). | ||
| //! - [`Routing::base_uri`] - always returns the same [`BaseUri`]. | ||
| //! - [`Routing::custom`] - delegates the decision to a user supplied closure that | ||
| //! receives a [`RoutingContext`]. |
There was a problem hiding this comment.
Module docs list default, base_uri, and custom constructors, but the module also exposes Routing::fallback. Please include fallback in the construction section (or remove the exhaustive-looking list) so the docs match the public API.
| //! receives a [`RoutingContext`]. | |
| //! receives a [`RoutingContext`]. | |
| //! - [`Routing::fallback`] - uses a fallback [`BaseUri`] when the target [`Uri`] | |
| //! does not already provide one. |
| fn assert_routing_size() { | ||
| static_assertions::assert_eq_size!(Routing, [u8; 16]); | ||
| } |
There was a problem hiding this comment.
This size assertion is likely to be brittle across architectures/compilers (e.g., 32-bit vs 64-bit pointer width, enum layout, future changes to Arc). Unless there’s a strong ABI requirement, consider removing it or gating it behind #[cfg(target_pointer_width = "64")] / using a less strict invariant.
|
|
||
| - ✨ Features | ||
|
|
||
| - add `routing` module with `Routing`, `RoutingContext`, and `BaseUriConflict` for resolving the target `BaseUri` of outgoing requests |
There was a problem hiding this comment.
This PR also adds a new public trait impl (impl AsRef<Clock> for HttpBodyBuilder). Since the changelog entry is under user-visible features, consider documenting this addition here as well so consumers can discover it.
| - add `routing` module with `Routing`, `RoutingContext`, and `BaseUriConflict` for resolving the target `BaseUri` of outgoing requests | |
| - add `routing` module with `Routing`, `RoutingContext`, and `BaseUriConflict` for resolving the target `BaseUri` of outgoing requests | |
| - implement `AsRef<Clock>` for `HttpBodyBuilder` |
| #[must_use] | ||
| pub fn custom<F>(resolver: F) -> Self | ||
| where | ||
| F: Fn(&RoutingContext) -> Option<BaseUri> + Send + Sync + 'static, |
There was a problem hiding this comment.
RoutingContext is declared as RoutingContext<'a>, but this file uses it without a lifetime parameter (e.g., Fn(&RoutingContext), fn resolve(&self, ctx: &RoutingContext)). This won’t compile and also doesn’t express the intended “any request lifetime” semantics. Consider using an HRTB like for<'a> Fn(&RoutingContext<'a>) -> Option<BaseUri> (and similarly for RoutingFn/resolve).
| F: Fn(&RoutingContext) -> Option<BaseUri> + Send + Sync + 'static, | |
| F: for<'a> Fn(&RoutingContext<'a>) -> Option<BaseUri> + Send + Sync + 'static, |
|
|
||
| - ✨ Features | ||
|
|
||
| - add `Uri::target_base_uri` getter to access the optional `BaseUri` |
There was a problem hiding this comment.
The Unreleased entry mentions adding a Uri::target_base_uri getter, but this PR actually introduces Uri::into_parts (and there’s no target_base_uri in the crate). Please update the changelog entry to match the API that was added.
| - add `Uri::target_base_uri` getter to access the optional `BaseUri` | |
| - add `Uri::into_parts` |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| - ✨ Features | ||
|
|
||
| - add `Uri::target_base_uri` getter to access the optional `BaseUri` |
There was a problem hiding this comment.
The Unreleased changelog entry doesn’t match the code changes in this PR: it mentions adding a Uri::target_base_uri getter, but uri.rs adds Uri::into_parts() instead (and there is no target_base_uri in the crate). Please update the entry to describe the actual new API (or implement the documented getter and reference it here).
| - add `Uri::target_base_uri` getter to access the optional `BaseUri` | |
| - add `Uri::into_parts()` to access the URI components, including the optional `BaseUri` |
| /// Creates a new [`RoutingContext`] for the first (and only) attempt. | ||
| #[must_use] | ||
| pub fn new() -> Self { | ||
| Self::default() | ||
| } |
There was a problem hiding this comment.
RoutingContext::new() is documented as creating a context for the "first (and only) attempt", but the default is_last_attempt value is false (and the tests assert that). Either update the docs to say "first attempt" or change the default so that new() sets is_last_attempt to true when that’s the intended meaning.
| /// Always route to a single base URI: | ||
| /// | ||
| /// ``` | ||
| /// use http_extensions::routing::{Routing, RoutingContext}; | ||
| /// use templated_uri::{BaseUri, Uri}; | ||
| /// | ||
| /// let routing = Routing::base_uri(BaseUri::from_uri_static("https://api.example.com")); | ||
| /// let target: Uri = "/v1/items".parse().unwrap(); | ||
| /// | ||
| /// let resolved = routing.create_uri(RoutingContext::new(), target).unwrap(); | ||
| /// assert_eq!( | ||
| /// resolved.to_string().declassify_into(), | ||
| /// "https://api.example.com/v1/items" | ||
| /// ); | ||
| /// ``` |
There was a problem hiding this comment.
PR description example for "fixed base uri" appears to repeat Routing::fallback(...) (same as the previous example). Since Routing::base_uri(...) is the fixed-base option implemented here, please correct the PR description snippet to avoid confusing reviewers/users.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| //! Routing primitives for resolving the [`BaseUri`] of an outgoing request. | ||
| //! | ||
| //! A [`Routing`] decides which [`BaseUri`] should be attached to a target [`Uri`] | ||
| //! before it is sent. This is useful when a library or middleware needs to centralize | ||
| //! the resolution of the destination of HTTP requests while still allowing callers to | ||
| //! express the rest of the request (path, query, ...) independently. |
There was a problem hiding this comment.
The PR description’s usage examples don’t match the implemented API: the repo contains no with_routing method (searching the codebase finds no occurrences), and the “fixed base uri” example repeats Routing::fallback(...). Consider either adding the integration helper that the description advertises, or updating the description/module docs to demonstrate the supported usage (e.g., Routing::update_request_uri or Routing::create_uri during request construction).
This module exposes flexible way to inject
base_urito outgoing requests.Practical application: