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

ensure_usable_cors_rules() isn't client friendly #272

Open
garypen opened this issue Jun 6, 2022 · 5 comments
Open

ensure_usable_cors_rules() isn't client friendly #272

garypen opened this issue Jun 6, 2022 · 5 comments
Labels
C-enhancement Category: A PR with an enhancement or a proposed on in an issue. E-help-wanted Call for participation: Help is requested to fix this issue. E-medium Call for participation: Experience needed to fix: Medium / intermediate

Comments

@garypen
Copy link

garypen commented Jun 6, 2022

Feature Request

Motivation

We are using tower-http in our project and we allow users to configure CORS. If there is a mistake which we can't detect in the composition of those rules, then this can result in a runtime panic in the ensure_usable_cors_rules() fn. This is not a good experience and we are working around this at the moment by validating our CORS rules before we pass them into tower-http.

Proposal

Could we modify ensure_usable_cors_rules() so that rather than asserting rules are usable, returns a result and expose this function so that we can validate before attempting to create a CorsLayer?:

    pub fn ensure_usable_cors_rules(&self) -> Result<(), &'static str>;

Alternatives

Perhaps have a try_layer() on Cors (or CorsLayer?) which is a fallible CorsLayer creator? If we had this, we could keep the original assert based ensure_usable_cors_rules() and add a new private fallible ensurer for consumption in try_layer. I feel like this would be the cleanest solution.

@jplatte
Copy link
Collaborator

jplatte commented Jun 6, 2022

I don't really understand what you mean with try_layer. I see two solutions here:

  • keep the existing API and implementation and add a function to check whether a CORS layer / service is valid (I'd just make it return bool instead of `Result<(), _>
  • deprecate (and later remove) the builder-style methods on the layer and service, provide a separate CorsBuilder that has fallible finishing functions like fn layer(self) -> Result<CorsLayer, _> and fn service(self) -> Result<Cors, _>

@davidpdrsn
Copy link
Member

Returning Result makes most sense when you expect users to handle the errors somehow. ensure_usable_cors_rules checks for invalid configurations which I'm not sure how you'd handle. Maybe you can elaborate on your use case and how you expect to handle the errors?

Something like try_layer wont work since tower::Layer trait doesn't have such a method. It also wouldn't be compatible with tower::ServiceBuilder unless we make fallible as well, which is a big change. If we do decide to support this I say we provide a separate builder.

@garypen
Copy link
Author

garypen commented Jun 7, 2022

I'll try to clarify why this is potentially useful:

@jplatte What I mean bytry_layer() is to avoid changing the existing layer() interface, to help maintain backwards compatibility for existing API consumers. There may be better ways to achieve this, but that's the motivation.
@davidpdrsn The nice thing about returning a Result here is that I like the existing error messages and so, I want to maintain those (hence, bool not as attractive) and in my use-case I can handle the errors. In our product, we maintain a configuration state machine. Before we transition to the new configuration, ensure that the incoming configuration is correct. If not, we reject the proposed configuration (with helpful error messages) and continue with the current configuration. Here's a link to a PR on our product which may be helpful if you want more detail: apollographql/router#1197

I could have a go at trying to implement something for a draft PR if this is something that you think would be useful in tower-http. If you think it's not generally applicable, then I can live with the solution I've put together in the PR above.

@jplatte
Copy link
Collaborator

jplatte commented Jun 7, 2022

Alright, I guess Result makes sense if you want to pass on the error message. I could totally see having .validate() on the layer and service, which returns Result<(), CorsConfigurationError>, with the existing ensure_usable_cors_rules calls being replaced by something like

if let Err(e) = self.validate() {
    panic!("{}", e);
}

@davidpdrsn
Copy link
Member

I think I'm gonna experiment with some sort of builder that doesn't panic.

@davidpdrsn davidpdrsn added E-help-wanted Call for participation: Help is requested to fix this issue. E-medium Call for participation: Experience needed to fix: Medium / intermediate labels Dec 2, 2022
@davidpdrsn davidpdrsn added this to the 0.4 milestone Dec 2, 2022
@davidpdrsn davidpdrsn added the C-enhancement Category: A PR with an enhancement or a proposed on in an issue. label Dec 2, 2022
@jplatte jplatte removed this from the 0.4 milestone Aug 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: A PR with an enhancement or a proposed on in an issue. E-help-wanted Call for participation: Help is requested to fix this issue. E-medium Call for participation: Experience needed to fix: Medium / intermediate
Projects
None yet
Development

No branches or pull requests

3 participants