0

I'm slowly inching my way towards a rudimentary ability to use or understand AWS. I have a Gateway API set up to Post a string to a (Node 10.x)Lambda function that then gets sent to a Dynamo table. I've been having issues with CORS when trying to make API calls from webpage javascript, and found out it had something to do with the CORS in the handler in the Lambda function. Here is what I have right now:


const AWS = require('aws-sdk');
const db = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
exports.handler = async function(event, context) {

    var responseCode = 200;

    var response = {
        statusCode: responseCode,
        headers: {
            "Access-Control-Allow-Origin": "*"

        },
        body: JSON.stringify(event)
    };

    context.succeed(response);

    console.log("Made it past context succeed");
    var characterData = JSON.parse(event.body);

    return await db.put(characterData).promise();
    };

I run tests from the AWS API page just sending it strings to Post like

{
    "TableName" : "characterTable",
    "Item" : {
      "userID" : "123",
      "characterName" : "Alan",
      "race" : "human"
    }
  }

When I comment out

    context.succeed(response);

my function adds the data to the Dynamo table, but does not show the CORS headers in the Gateway log, meaning they weren't received, and if I try it on a webpage, the webpage will error telling me I'm missing the Access-Control-Allow-Origin header. If I leave that snippet in, the Gateway log shows the proper CORS header, and the webpage console moves past the Access-Control-Allow-Origin error onto a different error (missing token ‘content-type’ in CORS header but that's a problem for me in the future) but the data does not get passed onto the Dynamo table, even though the console.log statement right above it triggers properly.

I'm not sure how or why this is happening, so I would appreciate any insight into what might be wrong!

EDIT: Here is my webpage JS

//Default AWS sdk object
var lambda = new AWS.Lambda();

//api sdk stuff
var apigClient = apigClientFactory.newClient({
  apiKey: 'iHadMyAPIKeyHere ' //placeholder for my actual API Key
});

function makeJSON(){
  var userID = "";
  var name = document.forms["characterForm"]["characterName"].value;

  var race = document.forms["characterForm"]["race"].value;
  var playerClass = document.forms["characterForm"]["class"].value;
  var strength = document.forms["characterForm"]["strength"].value;
  var dexterity = document.forms["characterForm"]["dexterity"].value;
  var constitution = document.forms["characterForm"]["constitution"].value;
  var intelligence = document.forms["characterForm"]["intelligence"].value;
  var wisdom = document.forms["characterForm"]["wisdom"].value;
  var charisma = document.forms["characterForm"]["charisma"].value;



  characterSheetObj = {"userID": userID, "name": name, "race": race, "class": playerClass, "strength": strength, "dexterity": dexterity, "constitution": constitution, "intelligence": intelligence, "wisdom": wisdom, "charisma": charisma}
  characterSheetJSON = JSON.stringify(characterSheetObj);

  alert(characterSheetJSON);

  var params = {

  }
  var body = {
    "TableName" : "characterTable",
    "Item" : {
      "userID" : userID,
      "name" : name,
      "race" : race
    }
  }

  var additionalParams = {

  }

  apigClient.myresourcePost(null, body);



}

nunzio
  • 51
  • 1
  • 2
  • 7

1 Answers1

0

Welcome to StackOverflow so you're problem is you need to use callback like so...

callback is called as the eventual result of the function, you want to return callback(....) to ensure your tests work properly later down line.

const AWS = require('aws-sdk');
const db = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
exports.handler = async function(event, context, callback) {

    var responseCode = 200;

    var response = {
        statusCode: responseCode,
        headers: {
            "Access-Control-Allow-Origin": "*"

        },
        body: JSON.stringify(event)
    };

    console.log("Made it past context succeed");
    var characterData = JSON.parse(event.body);

    await db.put(characterData).promise();

    return callback(null, response)

};

NOTE Your dynamo DB call is in the wrong format and will generate an exception.

Context succeed is the old way, please see this answer for more info on returning proper http responses.

Mrk Fldig
  • 4,244
  • 5
  • 33
  • 64
  • I'll look into it, thank you! If I may ask, what is wrong with my Dynamo call? When I test the function either in Lambda or through Gateway, (where it doesn't throw CORS errors) the Lambda call works and the data gets added to my Dynamo table. – nunzio Nov 14 '19 at 23:15
  • Oh sorry it depends on the construction of your event.body to be fair, really you only wanna get DATA from the client rather than DDB structure. but yeah try that out, remember return callback(...) is the end of the execution! - actually that;s my bad because I didn't notice the DDB bit your sending – Mrk Fldig Nov 14 '19 at 23:18
  • Basically send the ITEM and then have the DDB table etc API side. Otherwise front end users can specify which table they insert into regardless of endpoint which is bad juju - but lets solve the CORS problem first! – Mrk Fldig Nov 14 '19 at 23:21
  • So I copy/pasted your edit into my Lambda function, and when I tested through the API, I got [the appropriate headers in the log](https://imgur.com/a/kLgZiJf) and the item added to my table. However, running it from my webpage still gives me [this error](https://imgur.com/a/B8eGWTa) about the CORS. Am I missing something in my webpage javascript perhaps? – nunzio Nov 15 '19 at 18:33
  • Err is your webpage HTTPS also? Could you update your question with your current code please buddy? By the looks of it you're using chrome. *thinking face* - I can do a chat with you to figure this out if ya like? – Mrk Fldig Nov 16 '19 at 19:07
  • I don't believe it is, the website is just hosted off a plain AWS S3 bucket, and Firefox is telling me "Connection is not secure" right by the address. I presume I would need to enable HTTPS in the S3 bucket, quick google searching says that needs to be done through AWS Cloudfront, is that correct? Additionally, I edited my webpage JS into the main post, if that could be another source of error. I apologize for how drawn out this has become, but you've been very helpful and I do really appreciate your willingness to help! – nunzio Nov 16 '19 at 20:53