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

feat(middleware): allow dynamic validation of CORS origins #2052

Closed
wants to merge 1 commit into from

Conversation

willnewton
Copy link

  • feat(middleware): support callable filter for CORSMiddleware

  • tests(cors_middleware): add tests for dynamic origins

Summary of Changes

Allow passing a function to the CORSMiddleware for origin validation. This allows arbitrary validation like applying regexes etc.

Related Issues

I opened an issue regarding this feature request: #2050

Pull Request Checklist

This is just a reminder about the most common mistakes. Please make sure that you tick all appropriate boxes. But please read our contribution guide at least once; it will save you a few review cycles!

If an item doesn't apply to your pull request, check it anyway to make it apparent that there's nothing to do.

  • [X ] Applied changes to both WSGI and ASGI code paths and interfaces (where applicable).
  • [X ] Added tests for changed code.
  • [X ] Prefixed code comments with GitHub nick and an appropriate prefix.
  • [X ] Coding style is consistent with the rest of the framework.
  • [X ] Updated documentation for changed code.
    • [X ] Added docstrings for any new classes, functions, or modules.
    • [X ] Updated docstrings for any modifications to existing code.
    • [X ] Updated both WSGI and ASGI docs (where applicable).
    • [X ] Added references to new classes, functions, or modules to the relevant RST file under docs/.
    • [X ] Updated all relevant supporting documentation files under docs/.
    • [X ] A copyright notice is included at the top of any new modules (using your own name or the name of your organization).
    • [X ] Changed/added classes/methods/functions have appropriate versionadded, versionchanged, or deprecated directives.
  • [X ] Changes (and possible deprecations) have towncrier news fragments under docs/_newsfragments/, with the file name format {issue_number}.{fragment_type}.rst. (Run towncrier --draft to ensure it renders correctly.)

If you have any questions to any of the points above, just submit and ask! This checklist is here to help you, not to deter you from contributing!

PR template inspired by the attrs project.

* feat(middleware): support callable filter for CORSMiddleware

* tests(cors_middleware): add tests for dynamic origins
Copy link
Member

@vytas7 vytas7 left a comment

Choose a reason for hiding this comment

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

Thanks for this prototype @willnewton!

I'm admittedly a bit divided here though... 🤔 On the one hand, it would be a shame to say no a neat improvement like this, OTOH, we haven't made a decision on whether we want this feature in the framework itself or not. It's always better to discuss before building issues marked with the decision-needed label.

@CaselIT @kgriffs thoughts on including this feature?

@codecov
Copy link

codecov bot commented Apr 5, 2022

Codecov Report

Merging #2052 (394758c) into master (130572d) will not change coverage.
The diff coverage is 100.00%.

@@            Coverage Diff            @@
##            master     #2052   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           63        63           
  Lines         6707      6721   +14     
  Branches      1238      1241    +3     
=========================================
+ Hits          6707      6721   +14     
Impacted Files Coverage Δ
falcon/middleware.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 130572d...394758c. Read the comment docs.

@CaselIT
Copy link
Member

CaselIT commented Apr 5, 2022

I'm not against it, I would need to look at the implementation a bit more though.

@kgriffs
Copy link
Member

kgriffs commented Aug 22, 2022

IMO it would be fine to move forward with this. It affords additional use cases without the framework needing to implement and maintain explicit support for them.

@@ -19,7 +22,7 @@ class CORSMiddleware(object):

Keyword Arguments:
allow_origins (Union[str, Iterable[str]]): List of origins to allow (case
sensitive). The string ``'*'`` acts as a wildcard, matching every origin.
sensitive) or callable. The string ``'*'`` acts as a wildcard, matching every origin.
Copy link
Member

Choose a reason for hiding this comment

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

I think we'll need an update to docs/api/cors.rst as well to better explain how to use the callable option, provide an example.

allow_credentials (Optional[Union[str, Iterable[str]]]): List of origins
(case sensitive) for which to allow credentials via the
allow_credentials (Optional[Union[str, Iterable[str], OriginFilter]]): List of origins
(case sensitive) or callable for which to allow credentials via the
Copy link
Member

Choose a reason for hiding this comment

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

See above.

)
self.allow_credentials_filter = self.create_origin_filter(allow_credentials)

def create_origin_filter(self, allow_list):
Copy link
Member

Choose a reason for hiding this comment

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

Should this be part of the public interface? It seems like it should be private (prefixed w/ an undescore), at least in the first release until we discover otherwise.

):
if allow_origins == '*':
self.allow_origins = allow_origins
self.allow_origins_wildcard = False
Copy link
Member

Choose a reason for hiding this comment

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

Style: prefix allow_origins_wildcard name with an underscore; I don't think there is any need to make this part of the public interface.

self.allow_origins = allow_origins
self.allow_origins_wildcard = False
if isinstance(allow_origins, Callable):
self.allow_origins_filter = allow_origins
Copy link
Member

Choose a reason for hiding this comment

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

Style: prefix allow_origins_filter name with an underscore; I don't think there is any need to make this part of the public interface.

@vytas7
Copy link
Member

vytas7 commented Aug 23, 2022

IMO it would be fine to move forward with this. It affords additional use cases without the framework needing to implement and maintain explicit support for them.

Hm, not sure about this one @kgriffs. Maybe a better course of action could be breaking out that validation part to a public method of CORSMiddleware, and document an example how to subclass and override that? This is how some other parts of Falcon like media handlers are implemented too.

The async flavour could by default call the synchronous version directly, but it should be possible to do perform origin validation asynchronously too. Passing in a callable makes this somewhat trickier, or should we detect a coroutine function and act accordingly? Or just document it must be a sync function like in field converters?

@kgriffs
Copy link
Member

kgriffs commented Oct 7, 2022

@vytas7 I see your point. We should iterate on this design to make it more consistent with other parts of the framework.

@vytas7
Copy link
Member

vytas7 commented Jan 15, 2023

@willnewton I'm going to close this pull request for now, but we'll leave your issue (#2050) open for discussion on how to best implement this (or at least make it easy to customize).

@vytas7 vytas7 closed this Jan 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants