Author Topic: Problems with CORS when creating Creating API's from CloudFormation / SAM  (Read 57 times)

0 Members and 1 Guest are viewing this topic.

Online mrpackethead

  • Super Contributor
  • ***
  • Posts: 2668
  • Country: nz
Ok, lets see if the eevblog AWS knowledge is good.. :-)

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

Code: [Select]
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.

Code: [Select]
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

Code: [Select]
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.

Code: [Select]
<!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.

Code: [Select]
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






On a quest to find increasingly complicated ways to blink things
 

Online windsmurf

  • Frequent Contributor
  • **
  • Posts: 402
  • Country: us
I'm guessing it has to do with Boto3 configs alreadying passing credentials to aws, whereas HTML is not authenticated?

 

Online mrpackethead

  • Super Contributor
  • ***
  • Posts: 2668
  • Country: nz
Just needed to fix my template, so it deployed properly.
On a quest to find increasingly complicated ways to blink things
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf