4

I am running into another CORS issue with Serverless and AWS. Seems I need to tell it specifically to allow a PUT method, but I am not sure where this code goes. I have the following code for my Lambda function:

module.exports.update = (event, context, callback) => {
  const timestamp = new Date().getTime();
  const data = JSON.parse(event.body);
  if (typeof event.pathParameters.timeoffgroupid !== 'string') {
    console.error('Validation Failed');
    callback(new Error('Couldn\'t update the todo item.'));
    return;
  }
  const params = {
    TableName: 'TimeOffGroup',
    Key: {
      timeoffgroupid: event.pathParameters.timeoffgroupid,
    },
    ExpressionAttributeValues: {
      ':timeOffGroup': data.timeOffGroup,
      ':timeOffGroupColor': data.timeOffGroupColor,
      ':dateModified': timestamp
    },
    UpdateExpression: 'SET timeOffGroup = :timeOffGroup, timeOffGroupColor = :timeOffGroupColor, dateModified = :dateModified',
    ReturnValues: 'ALL_NEW',
  };

  dynamoDb.update(params, (error, result) => {
    if (error) {
      console.error(error);
      callback(new Error('Couldn\'t update the todo item.'));
      return;
    }
    const response = {
      statusCode: 200,
      body: JSON.stringify(result.Attributes),
      headers: {
        "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
        "Access-Control-Allow-Credentials" : true
      }
    };
    callback(null, response);
  });
};

The error I am getting is:

XMLHttpRequest cannot load https://pwqlomgq89.execute-api.us-east-1.amazonaws.com/dev/timeoffgroup/7d463800-0935-11e7-b618-4b1d72ddca8e?timeOffGroup=Holiday+edited. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 502. angular.js:14328 Possibly unhandled rejection: {"data":null,"status":-1,"config":{"method":"PUT","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","data":{},"url":"https://pwqlomgq89.execute-api.us-east-1.amazonaws.com/dev/timeoffgroup/7d463800-0935-11e7-b618-4b1d72ddca8e","params":{"timeOffGroup":"Holiday edited"},"headers":{"Accept":"application/json, text/plain, /","Content-Type":"application/json;charset=utf-8"}},"statusText":""}

I have followed all of the calls on serverless tutorials to get the CORS to work. But it seems I got the get and create to work, but the PUT command is not working. Is there some place I need to still set the update command to allow PUT for cross domain?

Looks like I might need more here for a PUT method access: headers:

{
    "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
    "Access-Control-Allow-Credentials" : true
}
sideshowbarker
  • 62,215
  • 21
  • 143
  • 153
Todd Coulson
  • 217
  • 2
  • 14
  • The reason you’re getting that particular error message is probably just that your server is not configured to add the Access-Control-Allow-Origin response header to server-error responses. The real underlying problem which that message indicates is that there’s a 502 error on the server side, which would seem to indicate some other failure is happening that’s unrelated to your CORS configuration. So you probably want to look through you server logs to get more details about what’s causing that 502 server failure so you can fix that. It could be something as simple as minor syntax error – sideshowbarker Mar 21 '17 at 22:55
  • 1
    Yeah I looked at the server logs, it is saying "ValidationException: Invalid UpdateExpression: An expression attribute value used in expression is not defined; attribute value: :timeOffGroupColor" Looking through for typo now. – Todd Coulson Mar 22 '17 at 12:50
  • I have an undefined value in javascript being passed into the function. I can clear this up now, thanks all for the help. – Todd Coulson Mar 22 '17 at 13:11

2 Answers2

2

It seems that your problem is that you don't handle the OPTIONS verb. See this answer to understand more about this requirement.

Before making the PUT request, the browser will preflight an OPTIONS request as a safety measure to ensure that this kind of request is expected by the server. If you don't support OPTIONS, it won't make the PUT request.

To fix this, change your serverless.yml file to add OPTIONS support.

functions:
  func:
    handler: handler.func
    events:
      - http: PUT foo/bar
      - http: OPTIONS foo/bar

Modify your handle with something like this:

module.exports.func = (event, context, callback) => {

  try {
    switch(event.httpMethod + ' ' + event.resource) {
      case 'PUT /foo/bar':
        handlePut(callback);
        break;
      case 'OPTIONS /foo/bar':
        handleOptions(callback);
        break;
      default:
        // return HTTP 400
    }
  }
  catch (err) {
     // return HTTP 500
  }
};

const handlePut = (callback) => {
    callback(null, { 
        statusCode: 200, 
        headers: {
            'Access-Control-Allow-Origin': '*'
        }, 
        body: JSON.stringify({
            message: 'PUT'
        })
    });
};

const handleOptions = (callback) => {
    callback(null, {
        statusCode: 200,
        headers: {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Headers': 'origin, content-type, accept',
            'Access-Control-Allow-Methods': 'POST, PUT, OPTIONS'
        }
    });
};
Community
  • 1
  • 1
Zanon
  • 22,850
  • 18
  • 101
  • 110
0

You can try by increasing the time out in lambda. This fixes CORS problem of mine.