Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

serverless-step-functions

Package Overview
Dependencies
Maintainers
1
Versions
131
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

serverless-step-functions - npm Package Compare versions

Comparing version 1.0.5 to 1.1.0

lib/deploy/events/apiGateway/cors.js

43

lib/deploy/events/apiGateway/methods.js

@@ -27,4 +27,4 @@ 'use strict';

_.merge(template,
this.getMethodIntegration(event.stateMachineName, stateMachineObj.name),
this.getMethodResponses()
this.getMethodIntegration(event.stateMachineName, stateMachineObj.name, event.http),
this.getMethodResponses(event.http)
);

@@ -45,3 +45,3 @@

getMethodIntegration(stateMachineName, customName) {
getMethodIntegration(stateMachineName, customName, http) {
const stateMachineLogicalId = this.getStateMachineLogicalId(stateMachineName, customName);

@@ -97,2 +97,5 @@ const apiToStepFunctionsIamRoleLogicalId = this.getApiToStepFunctionsIamRoleLogicalId();

},
};
const integrationResponse = {
IntegrationResponses: [

@@ -114,2 +117,17 @@ {

if (http && http.cors) {
let origin = http.cors.origin;
if (http.cors.origins && http.cors.origins.length) {
origin = http.cors.origins.join(',');
}
integrationResponse.IntegrationResponses.forEach((val, i) => {
integrationResponse.IntegrationResponses[i].ResponseParameters = {
'method.response.header.Access-Control-Allow-Origin': `'${origin}'`,
};
});
}
_.merge(integration, integrationResponse);
return {

@@ -122,4 +140,4 @@ Properties: {

getMethodResponses() {
return {
getMethodResponses(http) {
const methodResponse = {
Properties: {

@@ -140,3 +158,18 @@ MethodResponses: [

};
if (http && http.cors) {
let origin = http.cors.origin;
if (http.cors.origins && http.cors.origins.length) {
origin = http.cors.origins.join(',');
}
methodResponse.Properties.MethodResponses.forEach((val, i) => {
methodResponse.Properties.MethodResponses[i].ResponseParameters = {
'method.response.header.Access-Control-Allow-Origin': `'${origin}'`,
};
});
}
return methodResponse;
},
};

@@ -74,2 +74,21 @@ 'use strict';

});
it('should set Access-Control-Allow-Origin header when cors is true',
() => {
expect(serverlessStepFunctions.getMethodIntegration('stateMachine', 'custom', {
cors: {
origins: ['*', 'http://example.com'],
},
}).Properties.Integration.IntegrationResponses[0]
.ResponseParameters['method.response.header.Access-Control-Allow-Origin'])
.to.equal('\'*,http://example.com\'');
expect(serverlessStepFunctions.getMethodIntegration('stateMachine', 'custom', {
cors: {
origin: '*',
},
}).Properties.Integration.IntegrationResponses[0]
.ResponseParameters['method.response.header.Access-Control-Allow-Origin'])
.to.equal('\'*\'');
});
});

@@ -82,3 +101,22 @@

});
it('should set Access-Control-Allow-Origin header when cors is true',
() => {
expect(serverlessStepFunctions.getMethodResponses({
cors: {
origins: ['*', 'http://example.com'],
},
}).Properties.MethodResponses[0]
.ResponseParameters['method.response.header.Access-Control-Allow-Origin'])
.to.equal('\'*,http://example.com\'');
expect(serverlessStepFunctions.getMethodResponses({
cors: {
origin: '*',
},
}).Properties.MethodResponses[0]
.ResponseParameters['method.response.header.Access-Control-Allow-Origin'])
.to.equal('\'*\'');
});
});
});
'use strict';
const NOT_FOUND = -1;
const _ = require('lodash');

@@ -8,2 +8,3 @@

const events = [];
const corsPreflight = {};

@@ -18,2 +19,16 @@ _.forEach(this.getAllStateMachines(), (stateMachineName) => {

if (http.cors) {
http.cors = this.getCors(http);
const cors = corsPreflight[http.path] || {};
cors.headers = _.union(http.cors.headers, cors.headers);
cors.methods = _.union(http.cors.methods, cors.methods);
cors.origins = _.union(http.cors.origins, cors.origins);
cors.origin = http.cors.origin || '*';
cors.allowCredentials = cors.allowCredentials || http.cors.allowCredentials;
corsPreflight[http.path] = cors;
}
events.push({

@@ -29,2 +44,3 @@ stateMachineName,

events,
corsPreflight,
};

@@ -91,2 +107,60 @@ },

},
getCors(http) {
const headers = [
'Content-Type',
'X-Amz-Date',
'Authorization',
'X-Api-Key',
'X-Amz-Security-Token',
'X-Amz-User-Agent',
];
let cors = {
origins: ['*'],
origin: '*',
methods: ['OPTIONS'],
headers,
allowCredentials: false,
};
if (typeof http.cors === 'object') {
cors = http.cors;
cors.methods = cors.methods || [];
cors.allowCredentials = Boolean(cors.allowCredentials);
if (cors.origins && cors.origin) {
const errorMessage = [
'You can only use "origin" or "origins",',
' but not both at the same time to configure CORS.',
' Please check the docs for more info.',
].join('');
throw new this.serverless.classes.Error(errorMessage);
}
if (cors.headers) {
if (!Array.isArray(cors.headers)) {
const errorMessage = [
'CORS header values must be provided as an array.',
' Please check the docs for more info.',
].join('');
throw new this.serverless.classes.Error(errorMessage);
}
} else {
cors.headers = headers;
}
if (cors.methods.indexOf('OPTIONS') === NOT_FOUND) {
cors.methods.push('OPTIONS');
}
if (cors.methods.indexOf(http.method.toUpperCase()) === NOT_FOUND) {
cors.methods.push(http.method.toUpperCase());
}
} else {
cors.methods.push(http.method.toUpperCase());
}
return cors;
},
};

@@ -221,2 +221,197 @@ 'use strict';

});
it('should throw an error if "origin" and "origins" CORS config is used', () => {
serverlessStepFunctions.serverless.service.stepFunctions = {
stateMachines: {
first: {
events: [
{
http: {
method: 'POST',
path: '/foo/bar',
cors: {
origin: '*',
origins: ['*'],
},
},
},
],
},
},
};
expect(() => serverlessStepFunctions.httpValidate())
.to.throw(Error, 'can only use');
});
it('should process cors defaults', () => {
serverlessStepFunctions.serverless.service.stepFunctions = {
stateMachines: {
first: {
events: [
{
http: {
method: 'POST',
path: '/foo/bar',
cors: true,
},
},
],
},
},
};
const validated = serverlessStepFunctions.httpValidate();
expect(validated.events).to.be.an('Array').with.length(1);
expect(validated.events[0].http.cors).to.deep.equal({
headers: ['Content-Type', 'X-Amz-Date', 'Authorization', 'X-Api-Key',
'X-Amz-Security-Token', 'X-Amz-User-Agent'],
methods: ['OPTIONS', 'POST'],
origin: '*',
origins: ['*'],
allowCredentials: false,
});
});
it('should throw if cors headers are not an array', () => {
serverlessStepFunctions.serverless.service.stepFunctions = {
stateMachines: {
first: {
events: [
{
http: {
method: 'POST',
path: '/foo/bar',
cors: {
headers: true,
},
},
},
],
},
},
};
expect(() => serverlessStepFunctions.httpValidate()).to.throw(Error);
});
it('should process cors options', () => {
serverlessStepFunctions.serverless.service.stepFunctions = {
stateMachines: {
first: {
events: [
{
http: {
method: 'POST',
path: '/foo/bar',
cors: {
headers: ['X-Foo-Bar'],
origins: ['acme.com'],
methods: ['POST', 'OPTIONS'],
},
},
},
],
},
},
};
const validated = serverlessStepFunctions.httpValidate();
expect(validated.events).to.be.an('Array').with.length(1);
expect(validated.events[0].http.cors).to.deep.equal({
headers: ['X-Foo-Bar'],
methods: ['POST', 'OPTIONS'],
origins: ['acme.com'],
allowCredentials: false,
});
});
it('should merge all preflight origins, method, headers and allowCredentials for a path', () => {
serverlessStepFunctions.serverless.service.stepFunctions = {
stateMachines: {
first: {
events: [
{
http: {
method: 'GET',
path: 'users',
cors: {
origins: [
'http://example.com',
],
allowCredentials: true,
},
},
}, {
http: {
method: 'POST',
path: 'users',
cors: {
origins: [
'http://example2.com',
],
},
},
}, {
http: {
method: 'PUT',
path: 'users/{id}',
cors: {
headers: [
'TestHeader',
],
},
},
}, {
http: {
method: 'DELETE',
path: 'users/{id}',
cors: {
headers: [
'TestHeader2',
],
},
},
},
],
},
},
};
const validated = serverlessStepFunctions.httpValidate();
expect(validated.corsPreflight['users/{id}'].methods)
.to.deep.equal(['OPTIONS', 'DELETE', 'PUT']);
expect(validated.corsPreflight.users.origins)
.to.deep.equal(['http://example2.com', 'http://example.com']);
expect(validated.corsPreflight['users/{id}'].headers)
.to.deep.equal(['TestHeader2', 'TestHeader']);
expect(validated.corsPreflight.users.allowCredentials)
.to.equal(true);
expect(validated.corsPreflight['users/{id}'].allowCredentials)
.to.equal(false);
});
it('serverlessStepFunctions', () => {
serverlessStepFunctions.serverless.service.stepFunctions = {
stateMachines: {
first: {
events: [
{
http: {
method: 'POST',
path: '/foo/bar',
cors: {
methods: ['POST'],
},
},
},
],
},
},
};
const validated = serverlessStepFunctions.httpValidate();
expect(validated.events).to.be.an('Array').with.length(1);
expect(validated.events[0].http.cors.methods).to.deep.equal(['POST', 'OPTIONS']);
});
});

@@ -10,2 +10,3 @@ 'use strict';

const httpMethods = require('./deploy/events/apiGateway/methods');
const httpCors = require('./deploy/events/apiGateway/cors');
const httpIamRole = require('./deploy/events/apiGateway/iamRole');

@@ -40,2 +41,3 @@ const httpDeployment = require('./deploy/events/apiGateway/deployment');

httpMethods,
httpCors,
httpIamRole,

@@ -105,2 +107,3 @@ httpDeployment,

.then(this.compileMethods)
.then(this.compileCors)
.then(this.compileHttpIamRole)

@@ -107,0 +110,0 @@ .then(this.compileDeployment);

@@ -98,2 +98,4 @@ 'use strict';

.stub(serverlessStepFunctions, 'compileMethods').returns(BbPromise.resolve());
const compileCorsStub = sinon
.stub(serverlessStepFunctions, 'compileCors').returns(BbPromise.resolve());
const compileHttpIamRoleStub = sinon

@@ -109,2 +111,3 @@ .stub(serverlessStepFunctions, 'compileHttpIamRole').returns(BbPromise.resolve());

expect(compileMethodsStub.notCalled).to.be.equal(true);
expect(compileCorsStub.notCalled).to.be.equal(true);
expect(compileHttpIamRoleStub.notCalled).to.be.equal(true);

@@ -116,2 +119,3 @@ expect(compileDeploymentStub.notCalled).to.be.equal(true);

serverlessStepFunctions.compileMethods.restore();
serverlessStepFunctions.compileCors.restore();
serverlessStepFunctions.compileHttpIamRole.restore();

@@ -132,2 +136,4 @@ serverlessStepFunctions.compileDeployment.restore();

.stub(serverlessStepFunctions, 'compileMethods').returns(BbPromise.resolve());
const compileCorsStub = sinon
.stub(serverlessStepFunctions, 'compileCors').returns(BbPromise.resolve());
const compileHttpIamRoleStub = sinon

@@ -143,3 +149,4 @@ .stub(serverlessStepFunctions, 'compileHttpIamRole').returns(BbPromise.resolve());

expect(compileMethodsStub.calledAfter(compileResourcesStub)).to.be.equal(true);
expect(compileHttpIamRoleStub.calledAfter(compileMethodsStub)).to.be.equal(true);
expect(compileCorsStub.calledAfter(compileMethodsStub)).to.be.equal(true);
expect(compileHttpIamRoleStub.calledAfter(compileCorsStub)).to.be.equal(true);
expect(compileDeploymentStub.calledAfter(compileHttpIamRoleStub)).to.be.equal(true);

@@ -146,0 +153,0 @@

2

package.json
{
"name": "serverless-step-functions",
"version": "1.0.5",
"version": "1.1.0",
"description": "The module is AWS Step Functions plugin for Serverless Framework",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -118,2 +118,43 @@ [![serverless](http://public.serverless.com/badges/v3.svg)](http://www.serverless.com) [![Build Status](https://travis-ci.org/horike37/serverless-step-functions.svg?branch=master)](https://travis-ci.org/horike37/serverless-step-functions) [![npm version](https://badge.fury.io/js/serverless-step-functions.svg)](https://badge.fury.io/js/serverless-step-functions) [![Coverage Status](https://coveralls.io/repos/github/horike37/serverless-step-functions/badge.svg?branch=master)](https://coveralls.io/github/horike37/serverless-step-functions?branch=master) [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)

#### Enabling CORS
To set CORS configurations for your HTTP endpoints, simply modify your event configurations as follows:
```yml
stepFunctions:
stateMachines:
hello:
events:
- http:
path: posts/create
method: POST
cors: true
definition:
```
Setting cors to true assumes a default configuration which is equivalent to:
```yml
stepFunctions:
stateMachines:
hello:
events:
- http:
path: posts/create
method: POST
cors:
origin: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: false
definition:
```
Configuring the cors property sets Access-Control-Allow-Origin, Access-Control-Allow-Headers, Access-Control-Allow-Methods,Access-Control-Allow-Credentials headers in the CORS preflight response.
#### Send request to an API

@@ -120,0 +161,0 @@ You can input an value as json in request body, the value is passed as the input value of your statemachine

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc