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
preguntada hace 5 años727 visualizaciones
1 Respuesta
1

My Cors configuration was incomplete. now resolved.

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

respondido hace 5 años

No has iniciado sesión. Iniciar sesión para publicar una respuesta.

Una buena respuesta responde claramente a la pregunta, proporciona comentarios constructivos y fomenta el crecimiento profesional en la persona que hace la pregunta.

Pautas para responder preguntas