Problems with CORS when creating Creating API's from CloudFormation / SAM

0

I have a lambda that looks up a DynamoDB table and returns a lists based on a value that is posted it. It is quite simple but i've run into a problem with CORS and im not sure how to fix it. I'd ideally like to be able to configure in the CF / SAM templates and just deploy it.. But i'm not sure what is stopping this from working.

The lambda is looks like this

import json
import boto3
from boto3.dynamodb.conditions import Key, Attr
from botocore.exceptions import ClientError

def lambda_handler(event, context):

    dynamodb = boto3.resource("dynamodb")
    table = dynamodb.Table('learning-values')

    _class = "widgets"  
    body = json.loads(event['body'])
    _subclass = body['widget']

    try:
        response = table.get_item(
            Key={
                'class': _class,
                'subclass': _subclass
                }
        )
    except ClientError as e:
        print(e.response['Error']['Message'])
    else:
        item = response['Item']['data']['options']

    
    return {
            "statusCode": 200,
            "headers": 
                    {
                        "Access-Control-Allow-Origin": "*",
                        "Access-Control-Allow-Headers": "Content-Type",
                        "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
                    },
            "body": json.dumps(
                        {
                        "message": item

I used Cloudformation to deploy the API. it creates it, and i'm able to post a value to it and get the expected list back. I have tested it using this small piece of python.

import requests, json, sys, base64
url = 'https://0r746huw6b.execute-api.ap-southeast-2.amazonaws.com/prod/widget' # learn11
widget = sys.argv[1]
payload = {"widget": widget}
header = {"Content-type": "application/json"}
r = requests.post(url, data=json.dumps(payload))#, headers=header)
items = r.json()['message']
print(items)

The response I get is like this

Z:\sam\learning\sandbox\widget>py testmessage.py shape
['round', 'square', 'triangle', 'diamond']

Z:\sam\learning\sandbox\widget>py testmessage.py smell
['fowl', 'stinky', 'nothing', 'fresh-linen', 'vanilla', 'tropical', 'cut-grass']

Z:\sam\learning\sandbox\widget>py testmessage.py colours
['red', 'green', 'blue', 'yellow', 'grey', 'black', 'white']

When i attempt to get that same data from javascript using this html. ( either hosted on S3, or locally) I get CORS errors in the browser.

widget.html:1 Access to XMLHttpRequest at 'https://0r746huw6b.execute-api.ap-southeast-2.amazonaws.com/prod/widget' from origin 'null' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<p>Get Colours</p>
<div ng-app="myLearn" ng-controller="myLearnCtrl"> 
<h4>{{message}}</h4>
</div>

<script>
var app = angular.module('myLearn', []);
app.controller('myLearnCtrl', function($scope, $http) {
  $http.post("https://0r746huw6b.execute-api.ap-southeast-2.amazonaws.com/prod/widget",{"widget":"colours"})
  .then(function(response) {
      $scope.message = response.data["message"];
  });
});
</script>
</body>
</html>

The template i am using to deploy from is relatively simple.

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

  Sample SAM Template for learning

  '
Globals:
  Function:
    Timeout: 3
  Api:
    EndpointConfiguration: REGIONAL
    Cors: '''*'''
Resources:
  LearningAPI:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
  LearningFunction3:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://XXXXXXX-lambda-packages/0ab6dbfb0a46f18f11e43af73ee5d578
      Handler: app.lambda_handler
      Runtime: python3.7
      Events:
        Learning:
          Type: Api
          Properties:
            Path: /widget
            Method: post
            RestApiId:
              Ref: LearningAPI
asked 5 years ago715 views
1 Answer
1

My Cors configuration was incomplete. now resolved.

Globals:
Function:
Timeout: 3
Api:
EndpointConfiguration: REGIONAL
Cors:
AllowMethods: "''"
AllowHeaders: "'Content-Type'"
AllowOrigin: "'
'"

answered 5 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions