mirror of
https://github.com/serverless/serverless.git
synced 2026-01-25 15:07:39 +00:00
Merge pull request #4854 from bsdkurt/master
Add maxAge option for CORS
This commit is contained in:
commit
714c7586d5
@ -224,6 +224,21 @@ functions:
|
||||
|
||||
Configuring the `cors` property sets [Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin), [Access-Control-Allow-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers), [Access-Control-Allow-Methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods),[Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials) headers in the CORS preflight response.
|
||||
|
||||
To enable the `Access-Control-Max-Age` preflight response header, set the `maxAge` property in the `cors` object:
|
||||
|
||||
```yml
|
||||
functions:
|
||||
hello:
|
||||
handler: handler.hello
|
||||
events:
|
||||
- http:
|
||||
path: hello
|
||||
method: get
|
||||
cors:
|
||||
origin: '*'
|
||||
maxAge: 86400
|
||||
```
|
||||
|
||||
If you want to use CORS with the lambda-proxy integration, remember to include the `Access-Control-Allow-*` headers in your headers object, like this:
|
||||
|
||||
```javascript
|
||||
|
||||
@ -25,6 +25,16 @@ module.exports = {
|
||||
'Access-Control-Allow-Credentials': `'${config.allowCredentials}'`,
|
||||
};
|
||||
|
||||
// Enable CORS Max Age usage if set
|
||||
if (_.has(config, 'maxAge')) {
|
||||
if (_.isInteger(config.maxAge) && config.maxAge > 0) {
|
||||
preflightHeaders['Access-Control-Max-Age'] = `'${config.maxAge}'`;
|
||||
} else {
|
||||
const errorMessage = 'maxAge should be an integer over 0';
|
||||
throw new this.serverless.classes.Error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (_.includes(config.methods, 'ANY')) {
|
||||
preflightHeaders['Access-Control-Allow-Methods'] =
|
||||
preflightHeaders['Access-Control-Allow-Methods']
|
||||
|
||||
@ -67,18 +67,21 @@ describe('#compileCors()', () => {
|
||||
headers: ['*'],
|
||||
methods: ['OPTIONS', 'PUT'],
|
||||
allowCredentials: false,
|
||||
maxAge: 86400,
|
||||
},
|
||||
'users/create': {
|
||||
origins: ['*', 'http://example.com'],
|
||||
headers: ['*'],
|
||||
methods: ['OPTIONS', 'POST'],
|
||||
allowCredentials: true,
|
||||
maxAge: 86400,
|
||||
},
|
||||
'users/delete': {
|
||||
origins: ['*'],
|
||||
headers: ['CustomHeaderA', 'CustomHeaderB'],
|
||||
methods: ['OPTIONS', 'DELETE'],
|
||||
allowCredentials: false,
|
||||
maxAge: 86400,
|
||||
},
|
||||
'users/any': {
|
||||
origins: ['http://example.com'],
|
||||
@ -117,6 +120,13 @@ describe('#compileCors()', () => {
|
||||
.ResponseParameters['method.response.header.Access-Control-Allow-Credentials']
|
||||
).to.equal('\'true\'');
|
||||
|
||||
expect(
|
||||
awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
|
||||
.Resources.ApiGatewayMethodUsersCreateOptions
|
||||
.Properties.Integration.IntegrationResponses[0]
|
||||
.ResponseParameters['method.response.header.Access-Control-Max-Age']
|
||||
).to.equal('\'86400\'');
|
||||
|
||||
// users/update
|
||||
expect(
|
||||
awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
|
||||
@ -139,6 +149,13 @@ describe('#compileCors()', () => {
|
||||
.ResponseParameters['method.response.header.Access-Control-Allow-Credentials']
|
||||
).to.equal('\'false\'');
|
||||
|
||||
expect(
|
||||
awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
|
||||
.Resources.ApiGatewayMethodUsersUpdateOptions
|
||||
.Properties.Integration.IntegrationResponses[0]
|
||||
.ResponseParameters['method.response.header.Access-Control-Max-Age']
|
||||
).to.equal('\'86400\'');
|
||||
|
||||
// users/delete
|
||||
expect(
|
||||
awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
|
||||
@ -168,6 +185,13 @@ describe('#compileCors()', () => {
|
||||
.ResponseParameters['method.response.header.Access-Control-Allow-Credentials']
|
||||
).to.equal('\'false\'');
|
||||
|
||||
expect(
|
||||
awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
|
||||
.Resources.ApiGatewayMethodUsersDeleteOptions
|
||||
.Properties.Integration.IntegrationResponses[0]
|
||||
.ResponseParameters['method.response.header.Access-Control-Max-Age']
|
||||
).to.equal('\'86400\'');
|
||||
|
||||
// users/any
|
||||
expect(
|
||||
awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
|
||||
@ -198,4 +222,34 @@ describe('#compileCors()', () => {
|
||||
).to.equal('\'false\'');
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw error if maxAge is not an integer greater than 0', () => {
|
||||
awsCompileApigEvents.validated.corsPreflight = {
|
||||
'users/update': {
|
||||
origin: 'http://example.com',
|
||||
headers: ['*'],
|
||||
methods: ['OPTIONS', 'PUT'],
|
||||
allowCredentials: false,
|
||||
maxAge: -1,
|
||||
},
|
||||
};
|
||||
|
||||
expect(() => awsCompileApigEvents.compileCors())
|
||||
.to.throw(Error, 'maxAge should be an integer over 0');
|
||||
});
|
||||
|
||||
it('should throw error if maxAge is not an integer', () => {
|
||||
awsCompileApigEvents.validated.corsPreflight = {
|
||||
'users/update': {
|
||||
origin: 'http://example.com',
|
||||
headers: ['*'],
|
||||
methods: ['OPTIONS', 'PUT'],
|
||||
allowCredentials: false,
|
||||
maxAge: 'five',
|
||||
},
|
||||
};
|
||||
|
||||
expect(() => awsCompileApigEvents.compileCors())
|
||||
.to.throw(Error, 'maxAge should be an integer over 0');
|
||||
});
|
||||
});
|
||||
|
||||
@ -61,6 +61,11 @@ module.exports = {
|
||||
cors.origin = http.cors.origin || '*';
|
||||
cors.allowCredentials = cors.allowCredentials || http.cors.allowCredentials;
|
||||
|
||||
// when merging, last one defined wins
|
||||
if (_.has(http.cors, 'maxAge')) {
|
||||
cors.maxAge = http.cors.maxAge;
|
||||
}
|
||||
|
||||
corsPreflight[http.path] = cors;
|
||||
}
|
||||
|
||||
@ -332,10 +337,15 @@ module.exports = {
|
||||
if (cors.methods.indexOf(http.method.toUpperCase()) === NOT_FOUND) {
|
||||
cors.methods.push(http.method.toUpperCase());
|
||||
}
|
||||
if (_.has(cors, 'maxAge')) {
|
||||
if (!_.isInteger(cors.maxAge) || cors.maxAge < 1) {
|
||||
const errorMessage = 'maxAge should be an integer over 0';
|
||||
throw new this.serverless.classes.Error(errorMessage);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cors.methods.push(http.method.toUpperCase());
|
||||
}
|
||||
|
||||
return cors;
|
||||
},
|
||||
|
||||
|
||||
@ -643,6 +643,7 @@ describe('#validate()', () => {
|
||||
headers: ['X-Foo-Bar'],
|
||||
origins: ['acme.com'],
|
||||
methods: ['POST', 'OPTIONS'],
|
||||
maxAge: 86400,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -657,10 +658,11 @@ describe('#validate()', () => {
|
||||
methods: ['POST', 'OPTIONS'],
|
||||
origins: ['acme.com'],
|
||||
allowCredentials: false,
|
||||
maxAge: 86400,
|
||||
});
|
||||
});
|
||||
|
||||
it('should merge all preflight origins, method, headers and allowCredentials for a path', () => {
|
||||
it('should merge all preflight cors options for a path', () => {
|
||||
awsCompileApigEvents.serverless.service.functions = {
|
||||
first: {
|
||||
events: [
|
||||
@ -673,6 +675,7 @@ describe('#validate()', () => {
|
||||
'http://example.com',
|
||||
],
|
||||
allowCredentials: true,
|
||||
maxAge: 10000,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
@ -683,6 +686,7 @@ describe('#validate()', () => {
|
||||
origins: [
|
||||
'http://example2.com',
|
||||
],
|
||||
maxAge: 86400,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
@ -717,12 +721,35 @@ describe('#validate()', () => {
|
||||
.to.deep.equal(['http://example2.com', 'http://example.com']);
|
||||
expect(validated.corsPreflight['users/{id}'].headers)
|
||||
.to.deep.equal(['TestHeader2', 'TestHeader']);
|
||||
expect(validated.corsPreflight.users.maxAge)
|
||||
.to.equal(86400);
|
||||
expect(validated.corsPreflight.users.allowCredentials)
|
||||
.to.equal(true);
|
||||
expect(validated.corsPreflight['users/{id}'].allowCredentials)
|
||||
.to.equal(false);
|
||||
});
|
||||
|
||||
it('should throw an error if the maxAge is not a positive integer', () => {
|
||||
awsCompileApigEvents.serverless.service.functions = {
|
||||
first: {
|
||||
events: [
|
||||
{
|
||||
http: {
|
||||
method: 'POST',
|
||||
path: '/foo/bar',
|
||||
cors: {
|
||||
origin: '*',
|
||||
maxAge: -1,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
expect(() => awsCompileApigEvents.validate()).to.throw(Error);
|
||||
});
|
||||
|
||||
it('should add default statusCode to custom statusCodes', () => {
|
||||
awsCompileApigEvents.serverless.service.functions = {
|
||||
first: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user