I am stuck on this basic CORS issue but nothing seems to help.
Tried everything in Serverless CORS Survival Guide(https://www.serverless.com/blog/cors-api-gateway-survival-guide/)
Everything working fine in serverless offline
Here I am getting all the expected response headers for the same
Error In Browser-
Access to fetch at 'https://XXXXXXXXX.execute-api.us-east-1.amazonaws.com/dev/spaces_config/ap1' from origin 'https://XXXXXXXXX.com' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
My Setup->
I am using this boilerplate-> https://github.com/serverless/examples/aws-node-rest-api-typescript
Serverless.yml-
provider:
name: aws
runtime: nodejs16.x
memorySize: 512
timeout: 30
environment:
NODE_ENV: dev
plugins:
- serverless-plugin-typescript
- serverless-offline
package:
exclude:
- config/.env.stg
- config/.env.pro
include:
- config/.env.dev
functions:
createSpace:
handler: handler.createSpace
events:
- http:
path: spaces
method: post
cors:
origin: "*"
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: true
findSpace:
handler: handler.findSpace
events:
- http:
path: spaces
method: get
cors:
origin: "*"
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: true
findSpaceConfig:
handler: handler.findSpaceConfig
events:
- http:
path: spaces_config
method: get
cors:
origin: "*"
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: true
updateSpaceConfig:
handler: handler.updateSpaceConfig
events:
- http:
path: spaces_config/{space_id}
method: put
cors:
origin: "*"
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: true
findOneSpaceConfigById:
handler: handler.findOneSpaceConfigById
events:
- http:
path: spaces_config/{space_id}
method: get
cors:
origin: "*"
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: true
Also tried with cors: true
Handler.js File-
import { Handler, Context, APIGatewayEvent } from "aws-lambda";
import dotenv from "dotenv";
// import middy from "middy";
// import { cors } from "middy/middlewares";
// cross-env NODE_ENV=dev ts-node handler.ts
dotenv.config({
path: `config/.env.${process.env["NODE_ENV"]}`,
});
export * from "./app/connections/mongo";
import { SpacesController } from "./app/controller/spaces";
import { spaces } from "./app/model/spaces";
import { SpacesConfigController } from "./app/controller/spaces_config";
import { spaces_config } from "./app/model/spaces_config";
// Spaces
const spacesController = new SpacesController(spaces);
export const createSpace: Handler = (
event: APIGatewayEvent,
context: Context
) => {
return spacesController.create(event, context);
};
export const findSpace: Handler = () => spacesController.find();
// Spaces Config
const spacesConfigController = new SpacesConfigController(spaces_config);
export const findSpaceConfig: Handler = () => spacesConfigController.find();
export const updateSpaceConfig: Handler = (event: APIGatewayEvent) =>
spacesConfigController.update(event);
export const findOneSpaceConfigById: Handler = (
event: APIGatewayEvent,
context: Context
) => {
return spacesConfigController.findOne(event, context);
};
// export const findOneSpaceConfigById = middy(findOneSpaceConfigByI).use(cors());
In the boilerplate, there is a file message.ts(https://github.com/serverless/examples/blob/master/aws-node-rest-api-typescript/app/utils/message.ts) where we can customize the response. After middy was not working above, I tried sending response headers manually.
I was not getting any response header when I was using middy.
message.ts-
import { ResponseVO } from "../types/response";
enum StatusCode {
success = 200,
}
class Result {
private statusCode: number;
private code: number;
private message: string;
private data?: any;
constructor(statusCode: number, code: number, message: string, data?: any) {
this.statusCode = statusCode;
this.code = code;
this.message = message;
this.data = data;
}
/**
* Serverless: According to the API Gateway specs, the body content must be stringified
*/
bodyToString() {
return {
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": true,
"Content-Type": "application/json",
"Access-Control-Allow-Methods": "GET,PUT,POST,PATCH,OPTIONS",
"Access-Control-Allow-Headers":
"Content-Type, Accept, x-access-token ,Authorization",
},
statusCode: this.statusCode,
body: JSON.stringify({
code: this.code,
message: this.message,
data: this.data,
}),
};
}
}
export class MessageUtil {
static success(data: object): ResponseVO {
const result = new Result(StatusCode.success, 0, "success", data);
return result.bodyToString();
}
static error(code: number = 400, message: string) {
const result = new Result(StatusCode.success, code, message);
console.log(result.bodyToString());
return result.bodyToString();
}
}
Dependencies Used-
Stuck on the problem for a very long time.
Any help will be appreciated.
Thanks
This issue is likely occurring because the JavaScript for the browser is sending headers that are not in the allowed list in your serverless.yml. You probably do not need to send those headers either as sending them from the browser doesn't assist in resolving CORS and may complicate it. I would recommend removing all headers from your message.ts except Content-type and trying again.