Skip to content

Commit 06c7bcb

Browse files
authored
feat: configurable payload limit using cds.server.body_parser.limit (#177)
1 parent 4b0cb2a commit 06c7bcb

File tree

8 files changed

+43
-30
lines changed

8 files changed

+43
-30
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- Support for configuring request payload limit using global flag `cds.server.body_parser.limit`
13+
1214
### Changed
1315

1416
- To improve performance, binary payloads are no longer validated to check if they are properly base64 or base64url encoded

lib/GraphQLAdapter.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function GraphQLAdapter(options) {
2020
: defaultErrorFormatter
2121

2222
router
23-
.use(express.json()) //> required by logger below
23+
.use(express.json({ ...cds.env.server.body_parser })) //> required by logger below
2424
.use(queryLogger)
2525

2626
if (options.graphiql) router.use(graphiql)

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@
4040
},
4141
"devDependencies": {
4242
"@cap-js/graphql": "file:.",
43+
"@cap-js/sqlite": "^1",
4344
"axios": "^1",
4445
"express": "^4.17.1",
4546
"jest": "^29.3.1",
46-
"semver": "^7.4.0",
47-
"@cap-js/sqlite": "^1"
47+
"semver": "^7.4.0"
4848
}
4949
}

test/resources/bookshop/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"index.js"
1111
],
1212
"dependencies": {
13+
"@cap-js/graphql": "*",
1314
"@sap/cds": ">=5.9",
1415
"express": "^4.17.1"
1516
},

test/resources/custom-handlers/package.json

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
2+
"Note: Programmatic configuration of GraphQL protocol adapter in server.js": "",
3+
"__dependencies": {
4+
"@cap-js/graphql": "*"
5+
},
26
"devDependencies": {
37
"@cap-js/sqlite": "*"
48
}

test/resources/types/package.json

+10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
{
22
"dependencies": {
3+
"@cap-js/graphql": "*"
4+
},
5+
"devDependencies": {
36
"@cap-js/sqlite": "*"
7+
},
8+
"cds": {
9+
"server": {
10+
"body_parser": {
11+
"limit": "110KB"
12+
}
13+
}
414
}
515
}

test/resources/types/server.js

-6
This file was deleted.

test/tests/types.test.js

+23-21
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1+
const consumers = require('node:stream/consumers')
2+
13
const { gql } = require('../util')
24

35
const _toBase64Url = value => value.replace(/\//g, '_').replace(/\+/g, '-')
46

5-
const _getTestBuffer = length => {
6-
const testString = 'Test String! '
7-
let string = testString.repeat(Math.ceil(length / testString.length)).slice(0, length)
8-
return Buffer.from(string)
7+
const _getTestString = length => {
8+
const testString = 'This is a test string! '
9+
return testString.repeat(Math.ceil(length / testString.length)).slice(0, length)
910
}
1011

12+
const _getTestBuffer = length => Buffer.from(_getTestString(length))
13+
14+
// e.g. base64 string with length 96 -> requires buffer with length 72
15+
const _neededBufferLengthForBase64StringWithLength = length => Math.ceil((length * 6) / 8)
16+
1117
const _getMutationForFieldWithLiteralValue = (field, value, quoted) => ({
1218
query: gql`
1319
mutation {
@@ -48,9 +54,7 @@ describe('graphql - types parsing and validation', () => {
4854
// Prevent axios from throwing errors for non 2xx status codes
4955
axios.defaults.validateStatus = false
5056

51-
beforeEach(async () => {
52-
await data.reset()
53-
})
57+
beforeEach(data.reset)
5458

5559
describe('cds.Binary', () => {
5660
const field = 'myBinary'
@@ -1002,12 +1006,9 @@ describe('graphql - types parsing and validation', () => {
10021006
})
10031007

10041008
// Note: maps to same type as cds.Binary
1005-
// REVISIT: express-graphql limits request body size to 100kb by default:
1006-
// - https://github.com/graphql/express-graphql/issues/346
1007-
// - https://github.com/graphql/express-graphql/blob/28e4c2924ea6984bf918465cefdadae340d8780e/src/parseBody.ts#L96
1008-
describe.skip('cds.LargeBinary', () => {
1009+
describe('cds.LargeBinary', () => {
10091010
const field = 'myLargeBinary'
1010-
const buffer = _getTestBuffer(500000) // 500 KB
1011+
const buffer = _getTestBuffer(_neededBufferLengthForBase64StringWithLength(105000)) // 105 KB as base64 string
10111012

10121013
describe('input literal', () => {
10131014
test('cds.LargeBinary is correctly parsed from large input literal base64 encoded string value', async () => {
@@ -1018,7 +1019,8 @@ describe('graphql - types parsing and validation', () => {
10181019
expect(response.data).toEqual({ data })
10191020

10201021
const result = await SELECT.one.from('sap.cds.graphql.types.MyEntity').columns(field)
1021-
expect(result[field]).toEqual(buffer)
1022+
const bufferFromDB = await consumers.buffer(result[field])
1023+
expect(bufferFromDB).toEqual(buffer)
10221024
})
10231025

10241026
test('cds.LargeBinary is correctly parsed from large input literal base64url encoded string value', async () => {
@@ -1029,7 +1031,8 @@ describe('graphql - types parsing and validation', () => {
10291031
expect(response.data).toEqual({ data })
10301032

10311033
const result = await SELECT.one.from('sap.cds.graphql.types.MyEntity').columns(field)
1032-
expect(result[field]).toEqual(buffer)
1034+
const bufferFromDB = await consumers.buffer(result[field])
1035+
expect(bufferFromDB).toEqual(buffer)
10331036
})
10341037
})
10351038

@@ -1042,7 +1045,8 @@ describe('graphql - types parsing and validation', () => {
10421045
expect(response.data).toEqual({ data })
10431046

10441047
const result = await SELECT.one.from('sap.cds.graphql.types.MyEntity').columns(field)
1045-
expect(result[field]).toEqual(buffer)
1048+
const bufferFromDB = await consumers.buffer(result[field])
1049+
expect(bufferFromDB).toEqual(buffer)
10461050
})
10471051

10481052
test('cds.LargeBinary is correctly parsed from large variable base64url encoded string value', async () => {
@@ -1053,18 +1057,16 @@ describe('graphql - types parsing and validation', () => {
10531057
expect(response.data).toEqual({ data })
10541058

10551059
const result = await SELECT.one.from('sap.cds.graphql.types.MyEntity').columns(field)
1056-
expect(result[field]).toEqual(buffer)
1060+
const bufferFromDB = await consumers.buffer(result[field])
1061+
expect(bufferFromDB).toEqual(buffer)
10571062
})
10581063
})
10591064
})
10601065

10611066
// Note: maps to same type as cds.String
1062-
// REVISIT: express-graphql limits request body size to 100kb by default:
1063-
// - https://github.com/graphql/express-graphql/issues/346
1064-
// - https://github.com/graphql/express-graphql/blob/28e4c2924ea6984bf918465cefdadae340d8780e/src/parseBody.ts#L96
1065-
describe.skip('cds.LargeString', () => {
1067+
describe('cds.LargeString', () => {
10661068
const field = 'myLargeString'
1067-
const value = 'This is a test string! '.repeat(100000)
1069+
const value = _getTestString(105000) // 105 KB
10681070

10691071
test('cds.LargeString is correctly parsed from input literal', async () => {
10701072
const body = _getMutationForFieldWithLiteralValue(field, value, true)

0 commit comments

Comments
 (0)