amazon-archives / awsmobile-cli

CLI experience for Frontend developers in the JavaScript ecosystem.
Apache License 2.0
142 stars 35 forks source link

Unable to save record by calling the gateway api created by awsmobile #92

Closed SagarMhatre closed 6 years ago

SagarMhatre commented 6 years ago

I have followed the doc at [https://docs.aws.amazon.com/aws-mobile/latest/developerguide/web-access-databases.html] (Access Your Database) & created an employee table & cloud-api.


>  awsmobile database enable --prompt

Welcome to NoSQL database wizard
You will be asked a series of questions to help determine how to best construct your NoSQL database table.

? Should the data of this table be open or restricted by user? Open
? Table name employee

You can now add columns to the table.

? What would you like to name this column id
? Choose the data type string
? Would you like to add another column Yes
? What would you like to name this column age
? Choose the data type number
? Would you like to add another column Yes
? What would you like to name this column image
? Choose the data type string
? Would you like to add another column No

Before you create the database, you must specify how items in your table are uniquely organized. This is done by specifying a Primary key. The primary key uniquely identifies each item in the table, so that no two items can have the same key.
This could be and individual column or a combination that has "primary key" and a "sort key".
To learn more about primary key:
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.PrimaryKey

? Select primary key id
? Select sort key (No Sort Key)

You can optionally add global secondary indexes for this table. These are useful when running queries defined by a different column than the primary key.
To learn more about indexes:
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.SecondaryIndexes

? Add index No

> awsmobile cloud-api enable --prompt

This feature will create an API using Amazon API Gateway and AWS Lambda. You can optionally have the lambda function perform CRUD operations against your Amazon DynamoDB table.

? Select from one of the choices below. Create CRUD API for an existing Amazon DynamoDB table
? Select Amazon DynamoDB table to connect to a CRUD API employee
? Restrict API access to signed-in users No
Adding lambda function code on:
C:\Users\Laptop\Documents\Workspace\angular\angular5\awsmobilejs\backend\cloud-api\employee/
...
Path to be used on API for get and remove an object should be like:
/employee/object/:id

Path to be used on API for list objects on get method should be like:
/employee/:id

JSON to be used as data on put request should be like:
{
  "age": "INSERT VALUE HERE",
  "image": "INSERT VALUE HERE",
  "id": "INSERT VALUE HERE"
}

To test the api from the command line (after awsmobile push) use this commands
awsmobile cloud-api invoke employeeCRUD <method> <path> [init]

Now, when I invoke

$ awsmobile cloud-api invoke employeeCRUD post /employee '{"body": {"id":"harsha", "age":20, "image":"harshajpg"}}'

I get the error

init not valid JSON format

I have also tried it from the Mobile Hub Console (Testing employeeCRUD) by sending a post request to /employee with body*

{
    "id": "harsha",
    "age": 20,
    "image": "harsha.jpg"
}

But I get the response

{
  "error": {
    "message": "One or more parameter values were invalid: Missing the key id in the item",
    "code": "ValidationException",
    "time": "2018-03-31T04:57:16.676Z",
    "requestId": "EA4AHTI099LRGIDVKRRUKP9QMJVV4KQNSO5AEMVJF66Q9ASUAAJG",
    "statusCode": 400,
    "retryable": false,
    "retryDelay": 29.379546445147042
  },
  "url": "/employee",
  "body": {}
}

Even a GET request to /employee from the Mobile Hub Web Console yields:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /employee</pre>
</body>
</html>
SagarMhatre commented 6 years ago

Further, when I dig into the "One or more parameter values were invalid: Missing the key id in the item" issue, I tried setting up my own Lambda Function with the below nodejs code

exports.dynamodb_handler = function(event, context, callback) {
  console.log('Event' + JSON.stringify(event.body));

    // Load the AWS SDK for Node.js
    var AWS = require('aws-sdk');
    // Set the region 
    AWS.config.update({region: 'ap-south-1'});

    // Create DynamoDB document client
    var docClient = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10'});

    var params = {
      TableName: 'employee',
      Item : JSON.parse(event.body)
    };

    // Call DynamoDB to add the item to the table
    docClient.put(params, function(err, data) {
      if (err) {
        console.log("Error", err);
      } else {
        console.log("Success", data);
      }
    });

     var responseBody = {
        message: "hello",
        input: event
    };

    // The output from a Lambda proxy integration must be 
    // of the following JSON object. The 'headers' property 
    // is for custom response headers in addition to standard 
    // ones. The 'body' property  must be a JSON string. For 
    // base64-encoded payload, you must also set the 'isBase64Encoded'
    // property to 'true'.
    var response = {
        statusCode: 201,
        headers: {
            "x-custom-header" : "my custom header value"
        },
        body: JSON.stringify(responseBody)
    };
    console.log("response: " + JSON.stringify(response))
    callback(null, response);
}

Here, if we send the request through the API Gateway as

{
    "id" : "sagar16",
    "image" : "sagar.jpg",
    "age":32
}

it works fine & makes an entry to the table. If we call the same using the Lambda Web Console Function Testing

{
  "body": {
    "id": "sagar19",
    "image":  "sagar.jpg",
    "age": 20 
  }
}

It gives an error SyntaxError: Unexpected token o in JSON at position 1

Now, If we simply change the below in our lambda code (Remove the JSON.parse at the params.Item before the put)

var params = {
      TableName: 'employee',
      Item : event.body
    };

it works fine with the Lambda Web Console Testing , but now if we try it with the above API Request, the cloudwatch logs show the below error

Error { ValidationException: One or more parameter values were invalid: Missing the key id in the item

Edited by: MhatreSagar on Mar 31, 2018 7:27 AM

elorzafe commented 6 years ago

Hi @SagarMhatre which version of the cli are you using?

SagarMhatre commented 6 years ago

1.0.16

elorzafe commented 6 years ago

Hi @SagarMhatre I did the same steps (macOS Sierra). I had awsmobile-cli@1.0.16. Which OS are you using?

SagarMhatre commented 6 years ago

Windows 10

But I do not think that it maybe a OS issue since the lambda function when called directly from the web ui also gives an error

elorzafe commented 6 years ago

I will reproduce this on windows 10 and I will let you know.

Thanks!

SagarMhatre commented 6 years ago

I have tested it with awsmobile 1.1.4 & it worked.

The error on the Mobile Hub Console (Testing employeeCRUD) by sending a post request to /employee with body* still stays, but I think it is because my API is a secured one & requires login.