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

Bug: CORS Support in start-api #4991

Merged
merged 9 commits into from
May 18, 2023

Conversation

sleepwithcoffee
Copy link
Contributor

@sleepwithcoffee sleepwithcoffee commented Apr 10, 2023

Which issue(s) does this change fix?

#4161

Why is this change necessary?

To address a bug raised in ticket of local API gateway that does not properly return CORS headers. Currently, a workaround of using external plugin is required.

How does it address the issue?

Inject CORS response headers when returning to client. There are generated based on request Origin header.

What side effects does this change have?

I would expect none since this is a bug fix and an improvement. With this, user would not need to use external plugin to enable CORS for the local stack.

Mandatory Checklist

PRs will only be reviewed after checklist is complete

  • Add input/output type hints to new functions/methods
  • Write design document if needed (Do I need to write a design document?)
  • Write/update unit tests
  • Write/update integration tests
  • Write/update functional tests if needed
  • make pr passes
  • make update-reproducible-reqs if dependencies were changed
  • Write documentation (as below)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Current behavior:

  • Request header "Access-Control-Allow-Origin" is passed on as response header "Access-Control-Allow-Origin" without processing
    New behavior:
  • Get request header "Access-Control-Allow-Origin" and use it (either single domain or multiple domains or *) to match with Origin request header
    • If a match was found, only return that single matched domain as response "Access-Control-Allow-Origin"
    • If no match was found, reject the request by not returning according response header "Access-Control-Allow-Origin"
  • If there is no "Origin" header, straightout reject the request

Some consideration:

  • I didn't put the new logic under Cors class since this logic is supposed to be contextual of incoming requests
  • I named the new function _response_cors_headers since it is a private function, made it static for unit testing
  • The code prefers being restrictive over permissive due to the nature of this handling

@sleepwithcoffee sleepwithcoffee requested a review from a team as a code owner April 10, 2023 15:28
@github-actions github-actions bot added pr/external stage/needs-triage Automatically applied to new issues and PRs, indicating they haven't been looked at. area/local/invoke sam local invoke command area/local/start-api sam local start-api command area/local/start-invoke labels Apr 10, 2023
Copy link
Contributor

@jfuss jfuss left a comment

Choose a reason for hiding this comment

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

Is it possible to have integration tests that could help us validate the behavior?

return cors_headers

cors_origins = cors_headers["Access-Control-Allow-Origin"]
# unset this header due to restrictive manner
Copy link
Contributor

Choose a reason for hiding this comment

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

Why unset this? It looks like it should be removed in the case that response_allowed_origin is not set. If so, I would move this to be closer to line 437. I think it just make it a little easier to read since the mutation of the cors_headers is all in one spot.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @jfuss , thank you for taking your time to review this

we unset and set again if a match is found (restrictive manner)

if multiple domains are allowed, we only send back 1 allowed domain in our response header
if all domains are allowed, we also only send back 1 allowed domain in our response header

we do not return this header (implying a deny) if no matches is found

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hi @jfuss please also refer to my below comment:
#4991 (comment)

@@ -303,6 +303,7 @@ def _request_handler(self, **kwargs):

route = self._get_current_route(request)
cors_headers = Cors.cors_to_headers(self.api.cors)
cors_headers = self._response_cors_headers(request, cors_headers)
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for creating this PR! Did we need to restrict this behaviour to only run for HTTP APIs? From the docs and the linked issue, this seems to be something that the Lambda function deals with on for REST, but we would need to manage for HTTP.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hi @lucashuy

During the implementation, I referred to MDN web docs for reference:

image

I also referred to the implementation of middy cors middleware

below piece of code will basically parse and return a single origin if matched:
image

it is explained if looking deeper into the getOrigin() function:

image

Hope these help explain the reasoning behind my code.

Thanks,

@lucashuy lucashuy removed the stage/needs-triage Automatically applied to new issues and PRs, indicating they haven't been looked at. label Apr 20, 2023
Copy link
Contributor

@jfuss jfuss 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 the patch!

@sleepwithcoffee
Copy link
Contributor Author

merged and resolved conflicts

Copy link
Contributor

@hawflau hawflau left a comment

Choose a reason for hiding this comment

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

LGTM!

@hawflau hawflau added this pull request to the merge queue May 18, 2023
Merged via the queue into aws:develop with commit 3882c3d May 18, 2023
moelasmar added a commit to moelasmar/aws-sam-cli that referenced this pull request May 25, 2023
@moelasmar
Copy link
Contributor

moelasmar commented May 25, 2023

@sleepwithcoffee .. We had to revert this PR as it cause some regression, and some of the integration test cases are failing. Please check the revert PR to get more details. Could you please update this PR to fix the failing test cases, and add new integration test cases that cover the cases you are fixing here.

moelasmar added a commit that referenced this pull request May 25, 2023
@runk runk mentioned this pull request Jul 26, 2023
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants