brefphp / bref

Serverless PHP on AWS Lambda
https://bref.sh
MIT License
3.1k stars 367 forks source link

Document dealing with CORS #252

Open mnapoli opened 5 years ago

mnapoli commented 5 years ago

I am opening this issue so that we document this information.

When building an API on Lambda (+ API Gateway) we often need to enable CORS so that it can be called from the browser (e.g. with a SPA).

There is a very simple option in SAM (in template.yaml) to do that:

Globals:
    Api:
        Cors: "'*'"

However it doesn't work with sam local yet! (it works when deployed though)

The issue to track that in the SAM repository: https://github.com/awslabs/aws-sam-cli/issues/323 There is a pull request as well: https://github.com/awslabs/aws-sam-cli/pull/1009

Workaround

A workaround is to deal with CORS in the PHP API.

Here is an example for a Slim application:

composer require eko3alpha/slim-cors-middleware
$app = new \Slim\App();
$app->add(new \Eko3alpha\Slim\Middleware\CorsMiddleware([
    '*' => ['GET', 'POST'],
]));

// ...
Luitame commented 5 years ago

UPDATE: That PR (awslabs/aws-sam-cli#1009) mentioned above was closed and the work in progress related to CORS is living here awslabs/aws-sam-cli#1242

mnapoli commented 5 years ago

With serverless.yml it seems even simpler: https://serverless.com/framework/docs/providers/aws/events/apigateway/#enabling-cors

functions:
  hello:
    handler: index.php
    layers:
        - ${bref:layer.php-73-fpm}
    events:
      - http:
          path: '/'
          method: ANY
          cors: true
FrancescoArcieri commented 3 years ago

Can you provide also an example of serverless.yml using httpAPI?

RTC1 commented 3 years ago

Can you provide also an example of serverless.yml using httpAPI?

https://www.serverless.com/framework/docs/providers/aws/events/http-api/#cors-setup

mnapoli commented 3 years ago

Short version:

provider:
    httpApi:
        cors: true

If anyone wants to add that to the Bref documentation that would be neat.

kwn commented 3 years ago

Hi @mnapoli

I'm using Api Gateway v2 (httpApi) created externally (via Terraform). When I try to add cors via provider section (like in the example above) I'm getting an error from the Serverless framework:

Cannot setup CORS rules for externally configured HTTP API

That's ok, I can configure CORS via Terraform too. That's the Terraform block I added:

resource "aws_apigatewayv2_api" "public" {
  name          = "${var.environment}-api"
  protocol_type = "HTTP"
  description   = "Public API Gateway"

  cors_configuration {
    allow_origins = [
      "*"
    ]
    allow_headers = [
      "Content-Type",
      "X-Amz-Date",
      "Authorization",
      "X-Api-Key",
      "X-Amz-Security-Token",
      "X-Amz-User-Agent"
    ]
    allow_methods = [
      "OPTIONS",
      "HEAD",
      "GET",
      "POST",
      "PUT",
      "PATCH",
      "DELETE"
    ]
  }
}

Now - for some reason requests from the browser to the API Gateway still don't work due to CORS issue. Question - do I need to add additional CORS headers manually/explicitly in the PHP code that returns PSR7 response object? I made the CURL request to the endpoint and it seems API Gateway doesn't add any CORS headers automatically.

mnapoli commented 3 years ago

I have no idea if that's the right configuration for Terraform. With the config in serverless.yml you don't need to add any header.

More generally, for support questions I'd say it's best to ask in GitHub discussions: https://github.com/brefphp/bref/discussions

kwn commented 3 years ago

Thanks, I solved the issue. So you can configure CORS headers via Terraform in the way I did. The issue is that HTTP API Gateway doesn't add CORS headers to the response automatically if you don't add specific headers to your request (very important if you're testing your API with e.g. curl). I started calling my API with extra headers like that:

curl -v https://xxxxxx.execute-api.eu-west-1.amazonaws.com/test/api/installation/XXXXX -H 'Origin:http://example.com' -H 'Access-Control-Request-Method: GET'

instead of just

curl -v https://xxxxxx.execute-api.eu-west-1.amazonaws.com/test/api/installation/XXXXX

and suddenly API GW started adding cors headers. Hope this will be useful for some people.