diff --git a/spec/batch.spec.js b/spec/batch.spec.js index b47254eb14..9df64bbdbe 100644 --- a/spec/batch.spec.js +++ b/spec/batch.spec.js @@ -852,4 +852,61 @@ describe('batch', () => { expect(result.data).toEqual(jasmine.any(Array)); }); }); + + describe('nested batch requests', () => { + it('rejects sub-request that targets the batch endpoint', async () => { + await expectAsync( + request({ + method: 'POST', + url: 'http://localhost:8378/1/batch', + headers, + body: JSON.stringify({ + requests: [ + { + method: 'POST', + path: '/1/batch', + body: { + requests: [{ method: 'GET', path: '/1/classes/TestClass' }], + }, + }, + ], + }), + }) + ).toBeRejectedWith( + jasmine.objectContaining({ + status: 400, + data: jasmine.objectContaining({ + error: 'nested batch requests are not allowed', + }), + }) + ); + }); + + it('rejects when any sub-request among valid ones targets the batch endpoint', async () => { + await expectAsync( + request({ + method: 'POST', + url: 'http://localhost:8378/1/batch', + headers, + body: JSON.stringify({ + requests: [ + { method: 'GET', path: '/1/classes/TestClass' }, + { + method: 'POST', + path: '/1/batch', + body: { requests: [{ method: 'GET', path: '/1/classes/TestClass' }] }, + }, + ], + }), + }) + ).toBeRejectedWith( + jasmine.objectContaining({ + status: 400, + data: jasmine.objectContaining({ + error: 'nested batch requests are not allowed', + }), + }) + ); + }); + }); }); diff --git a/src/batch.js b/src/batch.js index 73192f8227..00740c9cda 100644 --- a/src/batch.js +++ b/src/batch.js @@ -101,6 +101,9 @@ async function handleBatch(router, req) { const rateLimits = req.config.rateLimits || []; for (const restRequest of req.body.requests) { const routablePath = makeRoutablePath(restRequest.path); + if ((restRequest.method || 'GET').toUpperCase() === 'POST' && routablePath === batchPath) { + throw new Parse.Error(Parse.Error.INVALID_JSON, 'nested batch requests are not allowed'); + } for (const limit of rateLimits) { const pathExp = limit.path.regexp || limit.path; if (!pathExp.test(routablePath)) {