cphill
cphill

Reputation: 5924

502 bad gateway error for cross-origin request

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

Upvotes: 8

Views: 25424

Answers (1)

Gareth McCumskey
Gareth McCumskey

Reputation: 1540

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'
    }
  }

Upvotes: 6

Related Questions