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
已提問 5 年前檢視次數 727 次
1 個回答
1

My Cors configuration was incomplete. now resolved.

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

已回答 5 年前

您尚未登入。 登入 去張貼答案。

一個好的回答可以清楚地回答問題並提供建設性的意見回饋,同時有助於提問者的專業成長。

回答問題指南