Merge pull request #3722 from HeroesDieYoung/master

Allow request parameter configuration with lambda-proxy integration
This commit is contained in:
Eslam λ Hefnawy 2017-07-13 16:01:14 +07:00 committed by GitHub
commit f7d1e55be6
3 changed files with 129 additions and 14 deletions

View File

@ -332,10 +332,6 @@ Please note that those are the API keys names, not the actual values. Once you d
Clients connecting to this Rest API will then need to set any of these API keys values in the `x-api-key` header of their request. This is only necessary for functions where the `private` property is set to true.
## Lambda Integration
This method is more complicated and involves a lot more configuration of the `http` event syntax.
### Request Parameters
To pass optional and required parameters to your functions, so you can use them in API Gateway tests and SDK generation, marking them as `true` will make them required, `false` will make them optional.
@ -348,7 +344,6 @@ functions:
- http:
path: posts/create
method: post
integration: lambda
request:
parameters:
querystrings:
@ -369,13 +364,16 @@ functions:
- http:
path: posts/{id}
method: get
integration: lambda
request:
parameters:
paths:
id: true
```
## Lambda Integration
This method is more complicated and involves a lot more configuration of the `http` event syntax.
### Request templates
#### Default Request Templates

View File

@ -96,15 +96,42 @@ module.exports = {
}
} else if (http.integration === 'AWS_PROXY') {
// show a warning when request / response config is used with AWS_PROXY (LAMBDA-PROXY)
if (http.request || http.response) {
if (http.request) {
const keys = Object.keys(http.request);
if (!(keys.length === 1 && keys[0] === 'parameters')) {
const requestWarningMessage = [
'Warning! You\'re using the LAMBDA-PROXY in combination with a request',
` configuration in your function "${functionName}". Only the`,
' \'request.parameters\' configs are available in conjunction with',
' LAMBDA-PROXY. Serverless will remove this configuration automatically',
' before deployment.',
].join('');
this.serverless.cli.log(requestWarningMessage);
for (const key of keys) {
if (key !== 'parameters') {
delete http.request[key];
}
}
}
if (Object.keys(http.request).length === 0) {
// No keys left, delete the request object
delete http.request;
} else {
http.request = this.getRequest(http);
if (http.request.parameters) {
http.request.parameters = this.getRequestParameters(http.request);
}
}
}
if (http.response) {
const warningMessage = [
'Warning! You\'re using the LAMBDA-PROXY in combination with request / response',
'Warning! You\'re using the LAMBDA-PROXY in combination with response',
` configuration in your function "${functionName}".`,
' Serverless will remove this configuration automatically before deployment.',
].join('');
this.serverless.cli.log(warningMessage);
delete http.request;
delete http.response;
}
} else if (http.integration === 'HTTP' || http.integration === 'HTTP_PROXY') {
@ -246,7 +273,7 @@ module.exports = {
const integration = this.getIntegration(http);
if (integration === 'AWS_PROXY'
&& typeof arn === 'string' && arn.match(/^arn:aws:cognito-idp/) && authorizer.claims) {
&& typeof arn === 'string' && arn.match(/^arn:aws:cognito-idp/) && authorizer.claims) {
const errorMessage = [
'Cognito claims can only be filtered when using the lambda integration type',
];

View File

@ -945,7 +945,7 @@ describe('#validate()', () => {
expect(() => awsCompileApigEvents.validate()).to.throw(Error);
});
it('should process request parameters', () => {
it('should process request parameters for lambda integration', () => {
awsCompileApigEvents.serverless.service.functions = {
first: {
events: [
@ -988,6 +988,49 @@ describe('#validate()', () => {
});
});
it('should process request parameters for lambda-proxy integration', () => {
awsCompileApigEvents.serverless.service.functions = {
first: {
events: [
{
http: {
integration: 'lambda-proxy',
path: 'foo/bar',
method: 'GET',
request: {
parameters: {
querystrings: {
foo: true,
bar: false,
},
paths: {
foo: true,
bar: false,
},
headers: {
foo: true,
bar: false,
},
},
},
},
},
],
},
};
const validated = awsCompileApigEvents.validate();
expect(validated.events).to.be.an('Array').with.length(1);
expect(validated.events[0].http.request.parameters).to.deep.equal({
'method.request.querystring.foo': true,
'method.request.querystring.bar': false,
'method.request.path.foo': true,
'method.request.path.bar': false,
'method.request.header.foo': true,
'method.request.header.bar': false,
});
});
it('should throw an error if the provided response config is not an object', () => {
awsCompileApigEvents.serverless.service.functions = {
first: {
@ -1262,11 +1305,51 @@ describe('#validate()', () => {
awsCompileApigEvents.validate();
expect(logStub.calledOnce).to.be.equal(true);
expect(logStub.calledTwice).to.be.equal(true);
expect(logStub.args[0][0].length).to.be.at.least(1);
});
it('should remove request/response config with LAMBDA-PROXY', () => {
it('should not show a warning message when using request.parameter with LAMBDA-PROXY', () => {
awsCompileApigEvents.serverless.service.functions = {
first: {
events: [
{
http: {
method: 'GET',
path: 'users/list',
integration: 'lambda-proxy',
request: {
parameters: {
querystrings: {
foo: true,
bar: false,
},
paths: {
foo: true,
bar: false,
},
headers: {
foo: true,
bar: false,
},
},
},
},
},
],
},
};
// initialize so we get the log method from the CLI in place
serverless.init();
const logStub = sinon.stub(serverless.cli, 'log');
awsCompileApigEvents.validate();
expect(logStub.called).to.be.equal(false);
});
it('should remove non-parameter request/response config with LAMBDA-PROXY', () => {
awsCompileApigEvents.serverless.service.functions = {
first: {
events: [
@ -1279,6 +1362,11 @@ describe('#validate()', () => {
template: {
'template/1': '{ "stage" : "$context.stage" }',
},
parameters: {
paths: {
foo: true,
},
},
},
response: {},
},
@ -1294,8 +1382,10 @@ describe('#validate()', () => {
const validated = awsCompileApigEvents.validate();
expect(validated.events).to.be.an('Array').with.length(1);
expect(validated.events[0].http.request).to.equal(undefined);
expect(validated.events[0].http.response).to.equal(undefined);
expect(validated.events[0].http.request.parameters).to.deep.equal({
'method.request.path.foo': true,
});
});
it('should throw an error when an invalid integration type was provided', () => {