question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

AWS::Serverless::HttpApi CorsConfiguration not working

See original GitHub issue

Description:

I have an AWS::Serverless::HttpApi resource with the CorsConfiguration property. The template deploys ok and I can get a successful response from the endpoint sending a GET request using Postman but, an OPTION request returns error 404.

Steps to reproduce:

Here is my template

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Parameters:
  EnvironmentName:
    Description: An environment name
    Type: String
    Default: production
    AllowedValues:
      - sandbox
      - production
      - staging

  StageName:
    Type: String
    Description: Api Stage Name
    Default: 'v0'

  UiUserPoolId:
    Type: String
    Description: Ui User Pool Id.

  UiUserPoolClientId:
    Type: String
    Description: Ui User Pool Client Id.

Globals:
  Function:
    Runtime: nodejs12.x
    MemorySize: 128
    Timeout: 60
    Handler: index.handler
    Environment:
      Variables:
        AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1

Resources:
  MyApi:
    Type: 'AWS::Serverless::HttpApi'
    Properties:
      StageName: !Ref 'StageName'
      CorsConfiguration:
        AllowCredentials: true
        AllowMethods: "'GET,POST,OPTIONS'"
        AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
        AllowOrigins: "'http://localhost:9000'"
      Auth:
        Authorizers:
          OAuth2Authorizer:
            JwtConfiguration:
              issuer: !Sub 'https://cognito-idp.${AWS::Region}.amazonaws.com/${UiUserPoolId}'
              audience:
                - !Ref UiUserPoolClientId
            IdentitySource: '$request.header.Authorization'
      Tags:
        Environment: !Sub '${EnvironmentName}'

  FantazGlobalNotificationFunction:
    Type: AWS::Serverless::Function
    Properties:
      Description: global notification for FantaZ UI
      FunctionName: !Sub '${EnvironmentName}-client-global-notification-lambda'
      CodeUri: ./global-notification/
      MemorySize: 128
      Environment:
        Variables:
          GLOBAL_NOTIFICATION_TABLE: !Sub '${EnvironmentName}-cf-GlobalNotification'
          ORIGIN: 'http://localhost:9000'
      Policies:
        - DynamoDBReadPolicy:
            TableName: !Sub '${EnvironmentName}-cf-GlobalNotification'
      Events:
        Get:
          Type: HttpApi
          Properties:
            Path: /globalNotification
            ApiId: !Ref MyApi
            Method: GET
      Tags:
        Environment: !Sub '${EnvironmentName}'

Outputs:
  MyApiUrl:
    Value: !Sub 'https://${MyApi}.execute-api.${AWS::Region}.amazonaws.com/${StageName}'
    Description: Client API URL

Observed result:

After deploying the template, if I go to the API Gateway console and open the CORS page this is what I see image

As you can see, there is no value set. If I send a GET to /v0/globalNotification it works ok, but sending an OPTIONS to the same endpoint fails with a 404 error. image

Am I missing something? Is my template wrong?

Expected result:

Send an OPTIONS request works as expected.

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

  1. OS: Linux
  2. sam --version: 1.18.1
  3. AWS region: us-east-1

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:1
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

5reactions
iongioncommented, Jun 4, 2021

Is the new HttpApi ready for production ? Is not only this that is not working, following all proper docs available online, I can’t get anything working

  • The CORS configuration is not respected
  • The JWT mechanism ends up with Internal Server Error and no further details
  • No calls are ever made to the JWT Authorizer lambda function, I see no log group created
  • If I disable the custom authorizer, the sample service gets called, log group gets created, as long as you don’t pass the X-Api-Key header, which ends up with the Internal Server Error above
  • Still, even in the case above, the CORS configuration is not respected

Don’t know what else I can do

{
    "stage": "dev",
    "requestTime": "03/Jun/2021:09:56:21 +0000",
    "sourceIp": "85.201.8.224",
    "protocol": "HTTP/1.1",
    "status": "500",
    "httpMethod": "GET",
    "requestId": "AV8S6j-SDoEEP9A=",
    "routeKey": "GET /api/sequences/{sequence_id}",
    "path": "/dev/api/sequences/sdsd",
    "responseLength": "35",
    "integration.status": "-",
    "integration.error": "-",
    "authorizer.error": "-",
    "authorizer.integrationStatus": "-",
    "authorizer.status": "-",
    "integrationErrorMessage": "-",
    "error.message": "Internal Server Error"
}
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: DataSet HTTP API and helper utilities

Parameters:
  StageName:
    Type: String
    Default: dev
    Description: (Required) Enter dev, test, stag, prod. Default is dev.
    AllowedValues:
      - dev
      - test
      - stag
      - prod

Globals:
  Function:
    Timeout: 600
    MemorySize: 512
    Runtime: nodejs12.x
    Environment:
      Variables:
        RUNTIME: online
        STAGE: !Ref StageName
    CodeUri: DataSet/
  Api:
    OpenApiVersion: '3.0.1'
    # See https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi
    BinaryMediaTypes:
      - "*~1*"

Resources:

  DataSetApi:
    Type: AWS::Serverless::HttpApi
    Properties:
      StageName: !Ref StageName
      # FailOnWarnings: True
      DefaultRouteSettings:
        DetailedMetricsEnabled: true
      AccessLogSettings:
        DestinationArn: !GetAtt DataSetApiAccessLogs.Arn
        # See https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-logging-variables.html
        Format: '{"stage":"$context.stage","requestTime":"$context.requestTime","sourceIp":"$context.identity.sourceIp","protocol":"$context.protocol","status":"$context.status","httpMethod":"$context.httpMethod","requestId":"$context.requestId","routeKey":"$context.routeKey","path":"$context.path","responseLength":"$context.responseLength","integration.status":"$context.integration.status","integration.error":"$context.integration.error","authorizer.error":"$context.authorizer.error","authorizer.integrationStatus":"$context.authorizer.integrationStatus","authorizer.status":"$context.authorizer.status","integrationErrorMessage":"$context.integrationErrorMessage","error.message":"$context.error.message"}'
      Auth:
        DefaultAuthorizer: JWTCustomAuthorizer
        Authorizers:
          JWTCustomAuthorizer:
            FunctionPayloadType: REQUEST
            FunctionArn: !GetAtt DataSetJWTAuthorize.Arn
            FunctionInvokeRole: !GetAtt DataSetJWTAuthorizeRole.Arn
            Identity:
              Headers:
                - X-Api-Key
            AuthorizerPayloadFormatVersion: 2.0
            EnableSimpleResponses: true

    CorsConfiguration:
      AllowOrigins:
        - '*'
      AllowHeaders:
        - X-Api-Key
      AllowMethods:
        - OPTIONS
        - HEAD
        - GET
        - POST
        - PUT
        - DELETE
        - PATCH
      MaxAge: 600
      AllowCredentials: true

  DataSetApiAccessLogs:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Join ["-", ["DataSetApiLogGroup", !Ref StageName]]
      RetentionInDays: 30

  # See https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction

  DataSetSequencesGetAllFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: services/DataSetSequencesGetAll.lambdaHandler
      Events:
        DataSetSequencesGetAll:
          Type: HttpApi
          Properties:
            ApiId: !Ref DataSetApi
            Path: /api/sequences
            Method: get
            PayloadFormatVersion: "2.0"

  DataSetJWTCreateFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: services/DataSetJWTCreate.lambdaHandler
      Events:
        DataSetJWTCreate:
          Type: HttpApi
          Properties:
            ApiId: !Ref DataSetApi
            Path: /api/jwt
            Method: post
            PayloadFormatVersion: "2.0"
            Auth:
              Authorizer: "NONE"

  DataSetJWTAuthorize:
    Type: AWS::Serverless::Function
    Properties:
      Handler: services/DataSetJWTAuthorize.lambdaHandler
      Runtime: nodejs12.x

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  DataSetApiUrl:
    Description: "API Gateway endpoint URL for the DataSet API"
    Value: !Sub "https://${DataSetApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${StageName}/"
  DataSetApiId:
    Description: Api id of DataSetApi
    Value:
      Ref: DataSetApi

If of any help, the authorizer lambda code for my test is also as documented here https://aws.amazon.com/blogs/compute/introducing-iam-and-lambda-authorizers-for-amazon-api-gateway-http-apis/

const createResponse = async (input) => {
  console.debug('Create response from input started');
  return Promise.resolve({
    isAuthorized: true,
    context: {},
  });
};

const executor = async (event, context) => {
  console.debug('Event processing started', { event, context });
  const response = await createResponse({ event, context });
  console.debug('Event processing completed, responding', response);
  return response;
};

exports.lambdaHandler = executor;
5reactions
kstro21commented, Feb 22, 2021

Thanks, @sriram-mv for your response but, no, that does not help at all. I saw that doc already and I have to say it doesn’t help either. It only mentions CORS works only if the DefinitionBody property is specified but, what is the min required inside DefinitionBody to make it work? Where can I find an example? There is no one blogging about it 😃

I’ve tried this

Resources:
  MyApi:
    Type: 'AWS::Serverless::HttpApi'
    Properties:
      StageName: !Ref 'StageName'
      DefinitionBody:
        openapi: 3.0.1
        info:
          title: !Ref 'AWS::StackName'
        paths: {}
      CorsConfiguration:
        AllowCredentials: true
        AllowMethods: "'GET,POST,OPTIONS'"
        AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
        AllowOrigins: "'http://localhost:9000'"
      Auth:
        Authorizers:
          OAuth2Authorizer:
            JwtConfiguration:
              issuer: !Sub 'https://cognito-idp.${AWS::Region}.amazonaws.com/${UiUserPoolId}'
              audience:
                - !Ref UiUserPoolClientId
            IdentitySource: '$request.header.Authorization'
      Tags:
        Environment: !Sub '${EnvironmentName}'

As you can see, I’m specifying the DefinitionBody property but it doesn’t work either.

And if I have to configure the x-amazon-apigateway-cors property inside DefinitionBody, what is the point of having the CorsConfiguration property? Am I missing something here or there is something not working as it should or, probably, the documentation is not enough?

Read more comments on GitHub >

github_iconTop Results From Across the Web

HTTPApi + Serverless Framework + API Gateway CORS not ...
I have an HTTPApi API Gateway created with the Serverless Framework. But for some routes, the CORS is not working. provider: name: aws...
Read more >
Troubleshoot CORS errors from API Gateway - AWS
I get the error "No 'Access-Control-Allow-Origin' header is present on the requested resource" when I try to invoke my Amazon API Gateway ...
Read more >
CORS not working - Serverless Forums
Cors should work by default. You likely do not need all those headers for both request and response. I suggest you try one...
Read more >
API Gateway HTTP + Lambda integration not enabling CORS
I have an API Gateway with an HTTP API + route that utilizes a Lambda function integration. From the AWS documentation, I see...
Read more >
Configuring CORS for an HTTP API - Amazon API Gateway
Learn how to configure CORS for an HTTP API. ... a response to preflight OPTIONS requests, even if there isn't an OPTIONS route...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found