-
Notifications
You must be signed in to change notification settings - Fork 196
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
[Server] Unreachable routes in operation_registry when only httpLabels are different #1009
Comments
Ok I think I understand the problem - the fold() call in request_spec.rs works correctly for anything that has at least one segment, but the ListBuckets operation has no segments at all which makes the result be an empty string instead of a So I tested this fix and it seems to work ok for my cases:
|
I think you caught another bug here. I am not fond of our implementation using regexes and we did it like this because it was simple enough in the beginning. I think we can do two things here:
Regarding 2) it is unlikely I will find someone able to approve any code until January, so I am not sure it will be quicker. |
Hey @crisidev Thanks for the reply, and no worries about timelines I am unblocking myself with hacky fixes on a fork - |
Just adding a note that my suggested fix is not really enough for other cases, because S3 has more "semi overlapping" routes such as CreateBucket ( |
Yep, i was pretty sure this would happen.. it's going to be a lot of fun to catch and fix all the corner cases found in this model. My understanding is that this is a quite old model, hence it will require a bit of customization to adapt against the strictness of the smithy specs.. |
…iguation This commit implements basic URI pattern conflict disambiguation when routing incoming requests to service operations. It does this by introducing a measure of how "important" a `RequestSpec` is. The more specific a `RequestSpec` is, the higher it ranks in importance. Specificity is measured by the number of segments plus the number of query string literals in its URI pattern, so `/{Bucket}/{Key}?query` is more specific than `/{Bucket}/{Key}`, which is more specific than `/{Bucket}`, which is more specific than `/`. Why do we need this? Note that: 1. the Smithy spec does not define how servers should route incoming requests in the case of pattern conflicts; and 2. the Smithy spec even outright rejects conflicting patterns that can be easily disambiguated e.g. `/{a}` and `/{label}/b` cannot coexist. We can't to anything about (2) since the Smithy CLI will refuse to build a model with those kind of conflicts. However, the Smithy CLI does allow _other_ conflicting patterns to coexist, e.g. `/` and `/{label}`. We therefore have to take a stance on (1), since if we route arbitrarily we render basic usage impossible (see issue #1009). So this ranking of routes implements some basic pattern conflict disambiguation with some common sense. It's also the same behavior that the TypeScript sSDK is implementing [0]. This commit also: * makes the `future` module private, * hides documentation for the `request_spec` module; and * makes some fields from some structs in the `request_spec` module private and adds constructors. Closes #1009. [1]: https://github.com/awslabs/smithy-typescript/blob/d263078b81485a6a2013d243639c0c680343ff47/smithy-typescript-ssdk-libs/server-common/src/httpbinding/mux.ts#L59.
…iguation This commit implements basic URI pattern conflict disambiguation when routing incoming requests to service operations. It does this by introducing a measure of how "important" a `RequestSpec` is. The more specific a `RequestSpec` is, the higher it ranks in importance. Specificity is measured by the number of segments plus the number of query string literals in its URI pattern, so `/{Bucket}/{Key}?query` is more specific than `/{Bucket}/{Key}`, which is more specific than `/{Bucket}`, which is more specific than `/`. Why do we need this? Note that: 1. the Smithy spec does not define how servers should route incoming requests in the case of pattern conflicts; and 2. the Smithy spec even outright rejects conflicting patterns that can be easily disambiguated e.g. `/{a}` and `/{label}/b` cannot coexist. We can't to anything about (2) since the Smithy CLI will refuse to build a model with those kind of conflicts. However, the Smithy CLI does allow _other_ conflicting patterns to coexist, e.g. `/` and `/{label}`. We therefore have to take a stance on (1), since if we route arbitrarily we render basic usage impossible (see issue #1009). So this ranking of routes implements some basic pattern conflict disambiguation with some common sense. It's also the same behavior that the TypeScript sSDK is implementing [0]. This commit also: * makes the `future` module private, * hides documentation for the `request_spec` module; and * makes some fields from some structs in the `request_spec` module private and adds constructors. Closes #1009. [1]: https://github.com/awslabs/smithy-typescript/blob/d263078b81485a6a2013d243639c0c680343ff47/smithy-typescript-ssdk-libs/server-common/src/httpbinding/mux.ts#L59.
…iguation This commit implements basic URI pattern conflict disambiguation when routing incoming requests to service operations. It does this by introducing a measure of how "important" a `RequestSpec` is. The more specific a `RequestSpec` is, the higher it ranks in importance. Specificity is measured by the number of segments plus the number of query string literals in its URI pattern, so `/{Bucket}/{Key}?query` is more specific than `/{Bucket}/{Key}`, which is more specific than `/{Bucket}`, which is more specific than `/`. Why do we need this? Note that: 1. the Smithy spec does not define how servers should route incoming requests in the case of pattern conflicts; and 2. the Smithy spec even outright rejects conflicting patterns that can be easily disambiguated e.g. `/{a}` and `/{label}/b` cannot coexist. We can't to anything about (2) since the Smithy CLI will refuse to build a model with those kind of conflicts. However, the Smithy CLI does allow _other_ conflicting patterns to coexist, e.g. `/` and `/{label}`. We therefore have to take a stance on (1), since if we route arbitrarily we render basic usage impossible (see issue #1009). So this ranking of routes implements some basic pattern conflict disambiguation with some common sense. It's also the same behavior that the TypeScript sSDK is implementing [0]. This commit also: * makes the `future` module private, * hides documentation for the `request_spec` module; and * makes some fields from some structs in the `request_spec` module private and adds constructors. Closes #1009. [1]: https://github.com/awslabs/smithy-typescript/blob/d263078b81485a6a2013d243639c0c680343ff47/smithy-typescript-ssdk-libs/server-common/src/httpbinding/mux.ts#L59.
…iguation (#1036) This commit implements basic URI pattern conflict disambiguation when routing incoming requests to service operations. It does this by introducing a measure of how "important" a `RequestSpec` is. The more specific a `RequestSpec` is, the higher it ranks in importance. Specificity is measured by the number of segments plus the number of query string literals in its URI pattern, so `/{Bucket}/{Key}?query` is more specific than `/{Bucket}/{Key}`, which is more specific than `/{Bucket}`, which is more specific than `/`. Why do we need this? Note that: 1. the Smithy spec does not define how servers should route incoming requests in the case of pattern conflicts; and 2. the Smithy spec even outright rejects conflicting patterns that can be easily disambiguated e.g. `/{a}` and `/{label}/b` cannot coexist. We can't to anything about (2) since the Smithy CLI will refuse to build a model with those kind of conflicts. However, the Smithy CLI does allow _other_ conflicting patterns to coexist, e.g. `/` and `/{label}`. We therefore have to take a stance on (1), since if we route arbitrarily we render basic usage impossible (see issue #1009). So this ranking of routes implements some basic pattern conflict disambiguation with some common sense. It's also the same behavior that the TypeScript sSDK is implementing [0]. This commit also: * makes the `future` module private, * hides documentation for the `request_spec` module; and * makes some fields from some structs in the `request_spec` module private and adds constructors. Closes #1009. [1]: https://github.com/awslabs/smithy-typescript/blob/d263078b81485a6a2013d243639c0c680343ff47/smithy-typescript-ssdk-libs/server-common/src/httpbinding/mux.ts#L59.
Reopening, this is not fixed yet. I had to revert the test that was explicitly added for the route conflict in this issue in #1070. It seems like allowing both empty URI segments and the simple pattern conflict disambiguation using weighted segments that I implemented are at odds with each other. We're tracking this issue in the Smithy repo smithy-lang/smithy#1024. Ideas for how to have both empty URI segments and simple pattern conflict disambiguation are welcome. We should ensure a stance is taken on this issue in the new pattern conflict disambiguation proposal smithy-lang/smithy#1029 (comment). |
Hi @david-perez I had a similar attempt to fix routing issues for S3 in #1097, and I still carry those as a patch on my fork to support S3 routing, so at least one of those patches is now in the upstream! I wonder what do you think about the fix to set routes rank to have a higher weight to paths over queries - this is needed because if paths and queries have the same weight then it is not possible to match the route Thanks! |
I'm not sure I understand. Given:
Then, if a request has URI |
Ok, you're right off course, sorry for the mixup. I went back to review my patch, and I see that in my patches I tried to hack out the need for |
When generating codegen-server for S3, operation_registry has list_buckets and list_objects operations and the only difference in their routing is that list_objects specifies an http label to capture the bucket name from the uri path, whereas list_buckets specifies no labels. However the generated order (alphabetical) puts the list_buckets route first, which hides the second route altogether. It seems like any subsequent route is unreachable because the route of list_buckets matches any uri path, while it should match just for root path
/
.This might require a fix in request_spec.rs where it builds the path regex:
https://github.com/awslabs/smithy-rs/blob/cbd61ab1fff94775e112f78181653fe040d08e24/rust-runtime/aws-smithy-http-server/src/routing/request_spec.rs#L78-L91
I tried to restrict it to match the entire path by changing the last line to the following code, which seems to help in some cases but I'm not sure this is correct -
Regex::new(&format!("^/*{}$", re)).unwrap()
(I had to use/*
instead of/+
because it didn't work otherwise but I'm quite puzzled as to why).This issue might be related to existing PR #996 Implement httpLabel with nom - so worth noting this issue when working on it.
For reference here are the router specs for list_buckets and list_objects which is only different in having a path label -
CC @crisidev
The text was updated successfully, but these errors were encountered: