4
votes

I am using the serverless framework to deploy my lambda to AWS and have been able to successfully run POST requests via Postman to the API Gateway associated with my lambda function, but when I try run a POST request from a form submission (AJAX request) on a local server I am receiving the 502 error message,

Access to XMLHttpRequest at 'https://*id*.execute-api.us-east-1.amazonaws.com/prod/message' from origin 'http://localhost:2368' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

which I didn't expect since I have the cors property in my serverless.yml set to true, which sets CORS configurations for the HTTP endpoint. Here is the function yaml setup:

functions:
  email:
    handler: handler.sendEmail
    events:
      - http:
          path: message
          method: post
          cors: true

Here is the jQuery AJAX request:

$.ajax({
    type: 'POST',
    url: 'https://*id*.execute-api.us-east-1.amazonaws.com/prod/message',
    crossDomain: true,
    data: JSON.stringify(formData),
    contentType: 'application/json',
    dataType: 'json',
    success: function(data) {
        console.log(data)
    },
    error: function(xhr, ajaxOptions, thrownError) {
        console.log(xhr);
        console.log(ajaxOptions);
        console.log(thrownError);
    }
});

Is there something that I need to adjust with the API Gateway configuration or within my Lambda application?

Here is my response function:

const generateResponse = (body, statusCode) => {
  console.log("generateResponse")
  console.log(body)
  return Promise.resolve({
      headers: {
          "access-control-allow-methods": "POST",
          "access-control-allow-origin": "*",
          "content-type": "application/json",
      },
      statusCode: statusCode,
      body: `{\"result\": ${body.message}}`
  });
};

Also provided is the ajax request:

$.ajax({
    type: 'POST',
    url: 'https://*my-lambda-id*.execute-api.us-east-1.amazonaws.com/prod/message',
    crossDomain: true,
    data: JSON.stringify(formData),
    contentType: 'application/json',
    dataType: 'json',
    success: function(data) {
        console.log(data)
    },
    error: function(xhr, ajaxOptions, thrownError) {
        console.log(xhr);
        console.log(ajaxOptions);
        console.log(thrownError);
    }
})

And the resulting OPTION and POST Request and Response Headers triggered by the AJAX:

OPTIONS:

Request URL: https://*my-lambda-id*.execute-api.us-east-1.amazonaws.com/prod/message
Request Method: OPTIONS
Status Code: 200 

Response Headers
access-control-allow-credentials: false
access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent
access-control-allow-methods: OPTIONS,POST
access-control-allow-origin: http://localhost:2368
content-length: 1
content-type: application/json
date: Tue, 08 Oct 2019 11:11:36 GMT
status: 200
via: 1.1 *id*.cloudfront.net (CloudFront)
x-amz-apigw-id: *id*
x-amz-cf-id: *id*
x-amz-cf-pop: *id*
x-amzn-requestid: *id*
x-cache: Miss from cloudfront

Request Headers
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: http://localhost:2368
Referer: http://localhost:2368/
Sec-Fetch-Mode: no-cors

POST

Request URL: https://*my-lambda-id*.execute-api.us-east-1.amazonaws.com/prod/message
Request Method: POST
Status Code: 502 

Request Headers
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/json
Origin: http://localhost:2368
Referer: http://localhost:2368/
Sec-Fetch-Mode: cors
1
The fact that you’re getting a 502 error is the actual problem. No 5xx error will ever have any CORS headers. So when you have a 502 error, it’s expected that the browser will also log a CORS error. But that doesn’t mean you have a CORS problem. If you fix the cause of the 502 error, then you’re likely gonna find that your CORS configuration is actually working as expected.sideshowbarker
@sideshowbarker thanks for the explanation and direction. I added my ajax request and headers to my question. Do you believe that the ajax configuration could be the reason for the 502cphill
Try NOT returning a promise. Just the response objectGareth McCumskey
Also, your POST request is showing a 502 shich has nothing to do with CORS. If the 502 is generated by AWS because of some error (such as the Promise not resolving for the request), there will be no CORS headers so you will also see CORS errors. If you fix the 502 I am pretty sure you will be CORS errors freeGareth McCumskey

1 Answers

4
votes

Wherever you return a response from your Lambda function you need to include the specific header CORS requests. The cors: true option you add to serverless.yml only helps make sure that the OPTIONS pre-flight requests work. Don't forget that this includes non-success responses as well.

For example:

return {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Credentials': true,
      'Access-Control-Allow-Headers': 'Authorization'
    }
  }