Skip to content

Commit 565fe4a

Browse files
Merge pull request #297 from horike37/feature/api_gw_response_template
feat: support response headers and template
2 parents a341fa1 + 848f336 commit 565fe4a

File tree

3 files changed

+102
-9
lines changed

3 files changed

+102
-9
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ This is the Serverless Framework plugin for AWS Step Functions.
2929
- [Shared Authorizer](#shared-authorizer)
3030
- [LAMBDA_PROXY request template](#lambda_proxy-request-template)
3131
- [Customizing request body mapping templates](#customizing-request-body-mapping-templates)
32+
- [Customizing response headers and templates](#customizing-response-headers-and-templates)
3233
- [Send request to an API](#send-request-to-an-api)
3334
- [Setting API keys for your Rest API](#setting-api-keys-for-your-rest-api)
3435
- [Schedule](#schedule)
@@ -696,6 +697,31 @@ stepFunctions:
696697
definition:
697698
```
698699

700+
#### Customizing response headers and templates
701+
702+
If you'd like to add custom headers in the HTTP response, or customize the default response template (which just returns the response from Step Function's StartExecution API), then you can do so by including your custom headers and [API Gateway response mapping template](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html) in `serverless.yml` like so:
703+
704+
```yml
705+
stepFunctions:
706+
stateMachines:
707+
hello:
708+
events:
709+
- http:
710+
path: posts/create
711+
method: POST
712+
response:
713+
headers:
714+
Content-Type: "'application/json'"
715+
X-Application-Id: "'my-app'"
716+
template:
717+
application/json: |
718+
{
719+
"status": 200,
720+
"info": "OK"
721+
}
722+
definition:
723+
```
724+
699725
#### Send request to an API
700726

701727
You can input an value as json in request body, the value is passed as the input value of your statemachine

lib/deploy/events/apiGateway/methods.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,19 @@ module.exports = {
182182
),
183183
};
184184

185+
const responseParams = _.mapKeys(
186+
_.get(http, 'response.headers', {}),
187+
(value, key) => `method.response.header.${key}`,
188+
);
189+
const responseTemplates = _.get(http, 'response.template', {});
190+
185191
const integrationResponse = {
186192
IntegrationResponses: [
187193
{
188194
StatusCode: 200,
189195
SelectionPattern: 200,
190-
ResponseParameters: {},
191-
ResponseTemplates: {},
196+
ResponseParameters: responseParams,
197+
ResponseTemplates: responseTemplates,
192198
},
193199
{
194200
StatusCode: 400,
@@ -206,9 +212,8 @@ module.exports = {
206212
}
207213

208214
integrationResponse.IntegrationResponses.forEach((val, i) => {
209-
integrationResponse.IntegrationResponses[i].ResponseParameters = {
210-
'method.response.header.Access-Control-Allow-Origin': `'${origin}'`,
211-
};
215+
integrationResponse.IntegrationResponses[i]
216+
.ResponseParameters['method.response.header.Access-Control-Allow-Origin'] = `'${origin}'`;
212217
});
213218
}
214219

@@ -298,11 +303,15 @@ module.exports = {
298303
},
299304

300305
getMethodResponses(http) {
306+
const responseParams = _.mapKeys(
307+
_.get(http, 'response.headers', {}),
308+
(value, key) => `method.response.header.${key}`,
309+
);
301310
const methodResponse = {
302311
Properties: {
303312
MethodResponses: [
304313
{
305-
ResponseParameters: {},
314+
ResponseParameters: responseParams,
306315
ResponseModels: {},
307316
StatusCode: 200,
308317
},
@@ -322,9 +331,8 @@ module.exports = {
322331
}
323332

324333
methodResponse.Properties.MethodResponses.forEach((val, i) => {
325-
methodResponse.Properties.MethodResponses[i].ResponseParameters = {
326-
'method.response.header.Access-Control-Allow-Origin': `'${origin}'`,
327-
};
334+
methodResponse.Properties.MethodResponses[i]
335+
.ResponseParameters['method.response.header.Access-Control-Allow-Origin'] = `'${origin}'`;
328336
});
329337
}
330338

lib/deploy/events/apiGateway/methods.test.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,52 @@ describe('#methods()', () => {
141141
}).Properties.Integration.Uri['Fn::Join'][1][2])
142142
.to.equal(':states:action/DescribeExecution');
143143
});
144+
145+
it('should return a custom template for application/json when one is given',
146+
() => {
147+
const httpWithResponseTemplate = {
148+
path: 'foo/bar1',
149+
method: 'post',
150+
response: {
151+
template: {
152+
'application/json': 'custom template',
153+
},
154+
},
155+
};
156+
const resource = serverlessStepFunctions
157+
.getMethodIntegration('stateMachine', undefined, httpWithResponseTemplate);
158+
const responseTemplates = resource
159+
.Properties.Integration.IntegrationResponses
160+
.find(x => x.StatusCode === 200)
161+
.ResponseTemplates;
162+
expect(responseTemplates['application/json'])
163+
.to.be.equal('custom template');
164+
});
165+
166+
it('should return custom headers when one is given',
167+
() => {
168+
const httpWithResponseHeaders = {
169+
path: 'foo/bar1',
170+
method: 'post',
171+
response: {
172+
headers: {
173+
'Content-Type': 'text',
174+
'X-Application-Id': 'id',
175+
},
176+
},
177+
};
178+
const resource = serverlessStepFunctions
179+
.getMethodIntegration('stateMachine', undefined, httpWithResponseHeaders);
180+
181+
const intResponseParams = resource
182+
.Properties.Integration.IntegrationResponses
183+
.find(x => x.StatusCode === 200)
184+
.ResponseParameters;
185+
expect(intResponseParams['method.response.header.Content-Type'])
186+
.to.be.equal('text');
187+
expect(intResponseParams['method.response.header.X-Application-Id'])
188+
.to.be.equal('id');
189+
});
144190
});
145191

146192
describe('#getIntegrationRequestTemplates()', () => {
@@ -322,6 +368,19 @@ describe('#methods()', () => {
322368
.ResponseParameters['method.response.header.Access-Control-Allow-Origin'])
323369
.to.equal('\'*\'');
324370
});
371+
372+
it('should set custom custom headers when one is given',
373+
() => {
374+
expect(serverlessStepFunctions.getMethodResponses({
375+
response: {
376+
headers: {
377+
'X-Application-Id': 'id',
378+
},
379+
},
380+
}).Properties.MethodResponses[0]
381+
.ResponseParameters['method.response.header.X-Application-Id'])
382+
.to.equal('id');
383+
});
325384
});
326385

327386
describe('#getMethodAuthorization()', () => {

0 commit comments

Comments
 (0)