@@ -594,6 +594,154 @@ describe('batch', () => {
594594 } ) ;
595595 }
596596
597+ describe ( 'batch request size limit' , ( ) => {
598+ it ( 'should reject batch request when sub-requests exceed batchRequestLimit' , async ( ) => {
599+ await reconfigureServer ( {
600+ requestComplexity : { batchRequestLimit : 2 } ,
601+ } ) ;
602+ await expectAsync (
603+ request ( {
604+ method : 'POST' ,
605+ url : 'http://localhost:8378/1/batch' ,
606+ headers,
607+ body : JSON . stringify ( {
608+ requests : [
609+ { method : 'GET' , path : '/1/classes/TestClass' } ,
610+ { method : 'GET' , path : '/1/classes/TestClass' } ,
611+ { method : 'GET' , path : '/1/classes/TestClass' } ,
612+ ] ,
613+ } ) ,
614+ } )
615+ ) . toBeRejectedWith (
616+ jasmine . objectContaining ( {
617+ status : 400 ,
618+ data : jasmine . objectContaining ( {
619+ error : jasmine . stringContaining ( '3' ) ,
620+ } ) ,
621+ } )
622+ ) ;
623+ } ) ;
624+
625+ it ( 'should allow batch request when sub-requests are within batchRequestLimit' , async ( ) => {
626+ await reconfigureServer ( {
627+ requestComplexity : { batchRequestLimit : 5 } ,
628+ } ) ;
629+ const result = await request ( {
630+ method : 'POST' ,
631+ url : 'http://localhost:8378/1/batch' ,
632+ headers,
633+ body : JSON . stringify ( {
634+ requests : [
635+ { method : 'POST' , path : '/1/classes/TestClass' , body : { key : 'v1' } } ,
636+ { method : 'POST' , path : '/1/classes/TestClass' , body : { key : 'v2' } } ,
637+ ] ,
638+ } ) ,
639+ } ) ;
640+ expect ( result . data . length ) . toEqual ( 2 ) ;
641+ expect ( result . data [ 0 ] . success . objectId ) . toBeDefined ( ) ;
642+ expect ( result . data [ 1 ] . success . objectId ) . toBeDefined ( ) ;
643+ } ) ;
644+
645+ it ( 'should allow batch request at exactly batchRequestLimit' , async ( ) => {
646+ await reconfigureServer ( {
647+ requestComplexity : { batchRequestLimit : 2 } ,
648+ } ) ;
649+ const result = await request ( {
650+ method : 'POST' ,
651+ url : 'http://localhost:8378/1/batch' ,
652+ headers,
653+ body : JSON . stringify ( {
654+ requests : [
655+ { method : 'POST' , path : '/1/classes/TestClass' , body : { key : 'v1' } } ,
656+ { method : 'POST' , path : '/1/classes/TestClass' , body : { key : 'v2' } } ,
657+ ] ,
658+ } ) ,
659+ } ) ;
660+ expect ( result . data . length ) . toEqual ( 2 ) ;
661+ } ) ;
662+
663+ it ( 'should not limit batch request when batchRequestLimit is -1 (disabled)' , async ( ) => {
664+ await reconfigureServer ( {
665+ requestComplexity : { batchRequestLimit : - 1 } ,
666+ } ) ;
667+ const requests = Array . from ( { length : 20 } , ( _ , i ) => ( {
668+ method : 'POST' ,
669+ path : '/1/classes/TestClass' ,
670+ body : { key : `v${ i } ` } ,
671+ } ) ) ;
672+ const result = await request ( {
673+ method : 'POST' ,
674+ url : 'http://localhost:8378/1/batch' ,
675+ headers,
676+ body : JSON . stringify ( { requests } ) ,
677+ } ) ;
678+ expect ( result . data . length ) . toEqual ( 20 ) ;
679+ } ) ;
680+
681+ it ( 'should not limit batch request by default (no requestComplexity configured)' , async ( ) => {
682+ const requests = Array . from ( { length : 20 } , ( _ , i ) => ( {
683+ method : 'POST' ,
684+ path : '/1/classes/TestClass' ,
685+ body : { key : `v${ i } ` } ,
686+ } ) ) ;
687+ const result = await request ( {
688+ method : 'POST' ,
689+ url : 'http://localhost:8378/1/batch' ,
690+ headers,
691+ body : JSON . stringify ( { requests } ) ,
692+ } ) ;
693+ expect ( result . data . length ) . toEqual ( 20 ) ;
694+ } ) ;
695+
696+ it ( 'should bypass batchRequestLimit for master key requests' , async ( ) => {
697+ await reconfigureServer ( {
698+ requestComplexity : { batchRequestLimit : 2 } ,
699+ } ) ;
700+ const result = await request ( {
701+ method : 'POST' ,
702+ url : 'http://localhost:8378/1/batch' ,
703+ headers : {
704+ ...headers ,
705+ 'X-Parse-Master-Key' : 'test' ,
706+ } ,
707+ body : JSON . stringify ( {
708+ requests : [
709+ { method : 'GET' , path : '/1/classes/TestClass' } ,
710+ { method : 'GET' , path : '/1/classes/TestClass' } ,
711+ { method : 'GET' , path : '/1/classes/TestClass' } ,
712+ ] ,
713+ } ) ,
714+ } ) ;
715+ expect ( result . data . length ) . toEqual ( 3 ) ;
716+ } ) ;
717+
718+ it ( 'should include limit in error message when batch exceeds batchRequestLimit' , async ( ) => {
719+ await reconfigureServer ( {
720+ requestComplexity : { batchRequestLimit : 5 } ,
721+ } ) ;
722+ await expectAsync (
723+ request ( {
724+ method : 'POST' ,
725+ url : 'http://localhost:8378/1/batch' ,
726+ headers,
727+ body : JSON . stringify ( {
728+ requests : Array . from ( { length : 10 } , ( ) => ( {
729+ method : 'GET' ,
730+ path : '/1/classes/TestClass' ,
731+ } ) ) ,
732+ } ) ,
733+ } )
734+ ) . toBeRejectedWith (
735+ jasmine . objectContaining ( {
736+ status : 400 ,
737+ data : jasmine . objectContaining ( {
738+ error : jasmine . stringContaining ( '5' ) ,
739+ } ) ,
740+ } )
741+ ) ;
742+ } ) ;
743+ } ) ;
744+
597745 describe ( 'subrequest path type validation' , ( ) => {
598746 it ( 'rejects object path in batch subrequest with proper error instead of 500' , async ( ) => {
599747 await expectAsync (
0 commit comments