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
1개 답변
1

My Cors configuration was incomplete. now resolved.

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

답변함 5년 전

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인

관련 콘텐츠