2.0.3 • Published 5 years ago

@spencerbeggs/aws-lambda-cors v2.0.3

Weekly downloads
10
License
MIT
Repository
github
Last release
5 years ago

AWS Lambda CORS

Build Status Coverage Status Known Vulnerabilities

AWS has made setting up microservice APIs a breeze by attaching Lambda functions to API Gateways with via Lambda Proxy Integrations in API Gateway. But when you need more than basic CORS handling you may find yourself writing a lot of duplicate or too-clever-by-half code to handle setting proper headers on your responses. Testing your handlers directly with a testing library like Jest can also become a chore as you may find yourself working around your CORS-handling code. This module attempts to abstrct basic header handling handling to allow you to focus of the business-logic of your serverless functions.

Basic Usage

const { cors } = require("@spencerbeggs/aws-lambda-cors");

module.export.handler = function() {
  const { event, context, callback, data, response } = cors(...arguments);
  response.body = JSON.stringify({
    message: "Hello, world!"
  });
  callback(null, response);
};

The cors function will automatically respond with a 204 repsonse when it encounters a OPTIONS request with the Access-Control-Allow-Origin, Access-Control-Allow-Headers, Access-Control-Allow-Methods andAccess-Control-Max-Age. For other types of requests the function returns the regular event, context and callback arguments available to a Lamabda functions you would expect to from a proxy integration.

The response argument is simply an object with origin headers setup and its statusCode propery set to 200. If you want to send a JSON response, you need to set the body property of the response object and send stringified JSON.

If the event passed to your function has a Content-Type header starting with to application/json, the function attempts to parse the event body with JSON.parse and return the resulting JSON as the data return value. If the body cannot be parsed into JSON, the funtion will automatically callback with a 400 response.

Note: You can set module.exports.handler to function() or async function() but you cannot set it to () => or async () => because fat arrow functions do not have bindings to the arguments keyword.

Advanced Usage

The cors function takes a second options argument that is an object, with the following optional properties: allowedOrigins, allowedMethods, allowedHeaders and maxAge. The allowedOrigins, allowedMethods and allowedHeaders properties can be passed as either arrays of strings or as a comma-seperated string. maxAge is just a string. You can also pass these options from process.env with the respective vaiable names: CORS_ALLOWED_ORIGINS, CORS_ALLOWED_METHODS, CORS_ALLOWED_HEADERS and CORS_MAX_AGE.

const { cors } = require("@spencerbeggs/aws-lambda-cors");

module.export.handler = function() {
  const options = {
    allowedOrigins: ["https://mysite.com", "https://anothersite.com"]
    allowedMethods: ["POST", "PATCH"],
    allowedHeaders: "X-Custom-Header",
    maxAge: "800"
  };
  const { event, context, callback, data, response } = cors(...arguments, options);
  response.body = JSON.stringify({
    message: "Hello, world!"
  });
  callback(null, response);
};

The default options object looks like:

const options = {
  allowedOrigins: "*",
  allowedMethods: ["GET", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"],
  allowedHeaders: [
    "Content-Type",
    "X-Amz-Date",
    "Authorization",
    "X-Api-Key",
    "X-Amz-Security-Token"
  ],
  maxAge: "600"
};

You can also set the options by passing values to process.env: process.env.CORS_ALLOWED_ORIGINS, process.env.CORS_ALLOWED_METHODS, process.env.CORS_ALLOWED_HEADERS and process.env.CORS_MAX_AGE.

Example CloudFormation Template

Below is a simple CloudFormation template that uses AWS:Serverless Transform that attaches API Gateway to a serverless function handler for your API endpoint. Note that both the POST and OPTIONS events point to the same code bundle as this module provides the CORS handling for both.

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Resources:
  Role:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
        - "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
  MyFunction:
    Type: "AWS::Serverless::Function"
    Properties:
      CodeUri: s3://my-lambda-functions-bucket/myfunction.zip
      Handler: index.handler
      Runtime: nodejs10.x
      Role: !GetAtt Role.Arn
      Timeout: 3
      Environment:
        Variables:
          CORS_ALLOWED_ORIGINS: "https://siteone.com,https://sitetwo.com"
          CORS_ALLOWED_METHODS: "POST"
      Events:
        post:
          Type: Api
          Properties:
            Path: /my-endpoint
            Method: POST
        options:
          Type: Api
          Properties:
            Path: /my-endpoint
            Method: OPTIONS
2.0.3

5 years ago

2.0.2

5 years ago

2.0.1

5 years ago

2.0.0

5 years ago

1.0.3

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago

0.0.1

5 years ago

0.0.1-0

5 years ago

0.0.0

5 years ago