Skip to content

Commit f3c8f52

Browse files
committed
feat: allow passing requestParameters to s3 integration
1 parent 2bc837f commit f3c8f52

File tree

5 files changed

+95
-3
lines changed

5 files changed

+95
-3
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,27 @@ Sample request after deploying.
176176
curl https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/s3 -d '{"message": "testtest"}' -H 'Content-Type:application/json'
177177
```
178178

179+
#### Customizing request parameters
180+
181+
Similar to the [SQS](#sqs) support, you can customize the default request parameters `serverless.yml` like so:
182+
183+
```yml
184+
custom:
185+
apiGatewayServiceProxies:
186+
- s3:
187+
path: /s3
188+
method: post
189+
action: PutObject
190+
bucket:
191+
Ref: S3Bucket
192+
key: static-key.json
193+
cors: true
194+
195+
requestParameters:
196+
# use auto generated object key (will override the static key)
197+
'integration.request.path.object': 'context.requestId'
198+
```
199+
179200
### SNS
180201

181202
Sample syntax for SNS proxy in `serverless.yml`.

lib/apiGateway/schema.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ const proxiesSchemas = {
157157
.valid('GetObject', 'PutObject', 'DeleteObject')
158158
.required(),
159159
bucket: stringOrRef.required(),
160-
key: key.required()
160+
key: key.required(),
161+
requestParameters
161162
})
162163
}),
163164
sns: Joi.object({

lib/apiGateway/validate.test.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,6 @@ describe('#validateServiceProxies()', () => {
581581

582582
const proxiesToTest = [
583583
{ proxy: 'kinesis', props: { streamName: 'streamName' } },
584-
{ proxy: 's3', props: { bucket: 'bucket', action: 'PutObject', key: 'myKey' } },
585584
{ proxy: 'sns', props: { topicName: 'topicName' } }
586585
]
587586
proxiesToTest.forEach(({ proxy, props }) => {
@@ -1015,6 +1014,18 @@ describe('#validateServiceProxies()', () => {
10151014
{ param: 'myKey' }
10161015
)
10171016
})
1017+
1018+
it('should throw if requestParameters is not a string to string mapping', () => {
1019+
shouldError(
1020+
'child "s3" fails because [child "requestParameters" fails because [child "key2" fails because ["key2" must be a string]]]',
1021+
'requestParameters',
1022+
{ key1: 'value', key2: [] }
1023+
)
1024+
})
1025+
1026+
it('should not throw if requestParameters is a string to string mapping', () => {
1027+
shouldSucceed('requestParameters', { key1: 'value1', key2: 'value2' })
1028+
})
10181029
})
10191030

10201031
describe('sns', () => {

lib/package/s3/compileMethodsToS3.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ module.exports = {
141141
'Fn::Sub': ['arn:aws:apigateway:${AWS::Region}:s3:path/{bucket}/{object}', {}]
142142
},
143143
PassthroughBehavior: 'WHEN_NO_MATCH',
144-
RequestParameters: requestParams
144+
RequestParameters: _.merge(requestParams, http.requestParameters)
145145
}
146146

147147
const integrationResponse = {

lib/package/s3/compileMethodsToS3.test.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,4 +567,63 @@ describe('#compileMethodsToS3()', () => {
567567

568568
expect(serverless.service.provider.compiledCloudFormationTemplate.Resources).to.be.empty
569569
})
570+
571+
const testRequestParameters = (requestParametersOverride) => {
572+
const http = {
573+
path: 's3',
574+
method: 'post',
575+
bucket: {
576+
Ref: 'MyBucket'
577+
},
578+
action: 'PutObject',
579+
key: 'static',
580+
auth: { authorizationType: 'NONE' },
581+
requestParameters: requestParametersOverride
582+
}
583+
584+
const requestParams = {
585+
'method.request.header.Content-Type': true
586+
}
587+
588+
const intRequestParams = {
589+
'integration.request.path.object': 'method.request.path.key',
590+
'integration.request.path.bucket': {
591+
'Fn::Sub': [
592+
"'${bucket}'",
593+
{
594+
bucket: {
595+
Ref: 'MyBucket'
596+
}
597+
}
598+
]
599+
},
600+
'integration.request.header.x-amz-acl': "'authenticated-read'",
601+
'integration.request.header.Content-Type': 'method.request.header.Content-Type'
602+
}
603+
604+
const responseParams = {
605+
'method.response.header.Content-Type': true,
606+
'method.response.header.Content-Length': true
607+
}
608+
609+
const intResponseParams = {
610+
'method.response.header.Content-Type': 'integration.response.header.Content-Type',
611+
'method.response.header.Content-Length': 'integration.response.header.Content-Length'
612+
}
613+
614+
testSingleProxy({
615+
http,
616+
logicalId: 'ApiGatewayMethods3Post',
617+
method: 'POST',
618+
intMethod: 'PUT',
619+
requestParams: requestParams,
620+
intRequestParams: _.merge(intRequestParams, requestParametersOverride),
621+
responseParams,
622+
intResponseParams
623+
})
624+
}
625+
626+
it('should add custom request parameters mapping', () => {
627+
testRequestParameters({ 'integration.request.path.object': 'context.requestId' })
628+
})
570629
})

0 commit comments

Comments
 (0)