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

Add features to allow users specify regular expression or Predicate for CORS allowed origins #4982

Merged
merged 8 commits into from
Apr 4, 2024

Conversation

seonWKim
Copy link
Contributor

@seonWKim seonWKim commented Jun 23, 2023

Motivation:

Allow users to specify CORS allowed origins by regular expression or Predicate<String>

Modifications:

Users can specify allowed origins by using regular expression or Predicate<String> like below.

CorsDecorator

@CorsDecorator(
        originRegex = "http://example.*",
        allowedRequestMethods = HttpMethod.GET
)

CorsService's builderForOriginRegex or builder(Predicate<String> originPredicate)

  sb.service("/cors15", myService.decorate(
          CorsService.builderForOriginRegex("http://example.*")
                     .allowRequestMethods(HttpMethod.GET)
                     .newDecorator()));

  sb.service("/cors17", myService.decorate(
          CorsService.builder(origin -> origin.contains("example") || origin.contains("line"))
                     .allowRequestMethods(HttpMethod.GET)
                     .newDecorator()));

or per route

sb.annotatedService("/cors18", new Object() {
                        @Get("/index1")
                        public void index1() {}

                        @Post("/index2")
                        public void index2() {}

                        @Delete("/index3")
                        public void index3() {}
                    }, CorsService.builder()
                                  .andForOriginRegex("http://example.*")
                                  .route("/cors18/index1")
                                  .allowRequestMethods(HttpMethod.GET)
                                  .and()
                                  .andForOriginRegex(Pattern.compile(".*line.*"))
                                  .route("/cors18/index2")
                                  .allowRequestMethods(HttpMethod.POST)
                                  .and()
                                  .andForOrigin((origin) -> origin.contains("armeria"))
                                  .route("/cors18/index3")
                                  .allowRequestMethods(HttpMethod.DELETE)
                                  .and()
                                  .newDecorator()

WebSocketServiceBuilder's allowedOrigins(Predicate<String> originPredicate>

 sb.route()
    .path("/chat")
    .build(WebSocketService.builder(new CustomWebSocketServiceHandler())
                           .allowedOrigins(origin -> origin.contains("armeria"))
                           .build());

Result:

@seonWKim seonWKim marked this pull request as draft June 23, 2023 18:05
@seonWKim seonWKim force-pushed the cors-regex branch 2 times, most recently from 79ec138 to 815cc51 Compare June 23, 2023 23:51
@seonWKim seonWKim marked this pull request as ready for review June 23, 2023 23:51
@seonWKim
Copy link
Contributor Author

seonWKim commented Jun 23, 2023

@minwoox What should happen when users specify WebSocket's allowed origins like below?

sb.route()
  .path("/chat")
  .build(WebSocketService.builder(new CustomWebSocketServiceHandler())
                         .allowedOrigins(origin -> origin.contains("armeria"))
                         .allowedOrigins("http://line.com")
                         .build());

Should we throw an exception which specifies it's not possible to set allowedOrigins using Prediate<String> and Strings at the same time OR just use one of Predicate<String> or Strings to verify which origins are allowed?

By the way, I've made a test code in WebSocketServiceCorsTest which is related to this topic.

@trustin
Copy link
Member

trustin commented Jul 5, 2023

I think we need to clear this question up before proceeding:

  • What should we use for the Access-Control-Allow-Origin header value when a user specified the allowed origins as a regular expression? Should it be * or is a user supposed to provide the header value?
    • If it's the former, is it OK to reject the request for non-matching origins even if we responded that we allow all (*) origins?
    • If it's the latter, is it OK not to list all allowed origins, given the regexes like http://[abc]{1000}.com can yield a very large list?

@seonWKim
Copy link
Contributor Author

seonWKim commented Jul 5, 2023

Oh, that's a great point. Let's clear below questions first.

  • If it's the former, is it OK to reject the request for non-matching origins even if we responded that we allow all (*) origins?

I think users might be confused in above situation because even though they received * for allowed origins, their requests are rejected.

  • If it's the latter, is it OK not to list all allowed origins, given the regexes like http://[abc]{1000}.com can yield a very large list?

Returning all or part of the allowed origins from regex matching might be too expensive. In this case(when using regex or predicate for allowed origins), what do you think of returning the origin from the request?

By the way, this PR's implementation will simply set Access-Control-Allow-Origin header with the Origin value from the request.

@jrhee17 jrhee17 added this to the 1.26.0 milestone Aug 15, 2023
@minwoox minwoox modified the milestones: 1.26.0, 1.27.0 Oct 11, 2023
@ikhoon ikhoon modified the milestones: 1.27.0, 1.28.0 Jan 16, 2024
Copy link

codecov bot commented Mar 27, 2024

Codecov Report

Attention: Patch coverage is 77.94118% with 15 lines in your changes are missing coverage. Please review.

Project coverage is 74.12%. Comparing base (db3973d) to head (3c56648).
Report is 15 commits behind head on main.

Files Patch % Lines
...inecorp/armeria/server/cors/CorsPolicyBuilder.java 20.00% 4 Missing ⚠️
...eria/server/websocket/WebSocketServiceBuilder.java 63.63% 2 Missing and 2 partials ⚠️
...a/com/linecorp/armeria/server/cors/CorsPolicy.java 40.00% 3 Missing ⚠️
...eria/server/cors/CorsDecoratorFactoryFunction.java 83.33% 1 Missing and 1 partial ⚠️
...necorp/armeria/server/cors/CorsServiceBuilder.java 80.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #4982      +/-   ##
============================================
+ Coverage     74.09%   74.12%   +0.03%     
- Complexity    20907    21002      +95     
============================================
  Files          1809     1819      +10     
  Lines         76940    77357     +417     
  Branches       9833     9880      +47     
============================================
+ Hits          57005    57341     +336     
- Misses        15291    15367      +76     
- Partials       4644     4649       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@minwoox
Copy link
Member

minwoox commented Mar 27, 2024

By the way, this PR's implementation will simply set Access-Control-Allow-Origin header with the Origin value from the request.

Oops, you are already doing it correctly. Let me continue to review the PR. 😉

Copy link
Member

@minwoox minwoox left a comment

Choose a reason for hiding this comment

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

Thanks! Looks pretty good. I left some suggestions. 😉

Copy link
Contributor

@jrhee17 jrhee17 left a comment

Choose a reason for hiding this comment

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

Looks good overall! Left a comment on the overall design

@CLAassistant
Copy link

CLAassistant commented Mar 30, 2024

CLA assistant check
All committers have signed the CLA.

@seonWKim
Copy link
Contributor Author

Thank you @minwoox and @jrhee17 for reviewing my old PR.

I've applied the comments which are mainly of

  • Add requireNonNull
  • Use OR logic if allowedOrigins and allowedPredicate is both configured

@minwoox
Copy link
Member

minwoox commented Apr 1, 2024

After discussing with the team, we've decided to deprecate the CorsPolicy.origins() method. I'll push a patch for that. 😉 The patch also includes some other miscellaneous changes, so please take a look.

minwoox and others added 2 commits April 1, 2024 19:26
- Allow `CorsDecorator` to accept list of regular expressions
- Add `@UnstableApi` annotation
- Cache `Collections.singletonList(*)`
Copy link
Contributor

@jrhee17 jrhee17 left a comment

Choose a reason for hiding this comment

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

👍 👍 👍

@jrhee17
Copy link
Contributor

jrhee17 commented Apr 2, 2024

Please sign the CLA if you haven't already @seonwoo960000 🙇

@seonWKim
Copy link
Contributor Author

seonWKim commented Apr 2, 2024

@jrhee17 thanks for the review. Seems like I've already signed up the CLA as follows
image

Copy link
Member

@minwoox minwoox left a comment

Choose a reason for hiding this comment

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

Thanks, @seonwoo960000! 👍 👍 👍 👍 👍

@jrhee17
Copy link
Contributor

jrhee17 commented Apr 2, 2024

@jrhee17 thanks for the review. Seems like I've already signed up the CLS as follows

#4982 (comment)

Can you try modifying the authoring email of your commits so that we can move forward with this PR?

스크린샷 2024-04-02 오후 4 28 53

@seonWKim
Copy link
Contributor Author

seonWKim commented Apr 2, 2024

@jrhee17, thank you for detailed explanation. I've fixed my authoring email address

Copy link
Contributor

@ikhoon ikhoon left a comment

Choose a reason for hiding this comment

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

It looks useful. Thanks, @seonwoo960000! 🙇‍♂️

@jrhee17 jrhee17 merged commit a36344d into line:main Apr 4, 2024
18 checks passed
@seonWKim seonWKim deleted the cors-regex branch April 5, 2024 00:09
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.

6 participants