@@ -122,6 +122,18 @@ export class Polling extends Transport {
122122 return ;
123123 }
124124
125+ const contentLengthHeader = Number ( req . headers [ "content-length" ] ) ;
126+ if ( ! contentLengthHeader ) {
127+ this . onError ( "invalid content-length header" ) ;
128+ res . writeStatus ( "400 Invalid content-length header" ) . end ( ) ;
129+ return ;
130+ }
131+ if ( contentLengthHeader > this . maxHttpBufferSize ) {
132+ this . onError ( "payload too large" ) ;
133+ res . writeStatus ( "413 Payload Too Large" ) . end ( ) ;
134+ return ;
135+ }
136+
125137 const isBinary = "application/octet-stream" === req . headers [ "content-type" ] ;
126138
127139 if ( isBinary && this . protocol === 4 ) {
@@ -131,11 +143,11 @@ export class Polling extends Transport {
131143 this . dataReq = req ;
132144 this . dataRes = res ;
133145
134- let chunks = [ ] ;
146+ let buffer ;
135147 let contentLength = 0 ;
136148
137149 const cleanup = ( ) => {
138- this . dataReq = this . dataRes = chunks = null ;
150+ this . dataReq = this . dataRes = null ;
139151 } ;
140152
141153 const onClose = ( ) => {
@@ -154,8 +166,8 @@ export class Polling extends Transport {
154166 res . writeHeader ( key , String ( headers [ key ] ) ) ;
155167 } ) ;
156168
157- const onEnd = ( ) => {
158- this . onData ( Buffer . concat ( chunks ) . toString ( ) ) ;
169+ const onEnd = ( buffer ) => {
170+ this . onData ( buffer . toString ( ) ) ;
159171
160172 if ( this . readyState !== "closing" ) {
161173 res . end ( "ok" ) ;
@@ -165,18 +177,36 @@ export class Polling extends Transport {
165177
166178 res . onAborted ( onClose ) ;
167179
168- res . onData ( ( chunk , isLast ) => {
169- chunks . push ( Buffer . from ( chunk ) ) ;
170- contentLength += Buffer . byteLength ( chunk ) ;
171- if ( contentLength > this . maxHttpBufferSize ) {
172- this . onError ( "payload too large" ) ;
173- res . writeStatus ( "413 Payload Too Large" ) ;
174- res . end ( ) ;
180+ res . onData ( ( arrayBuffer , isLast ) => {
181+ const totalLength = contentLength + arrayBuffer . byteLength ;
182+ if ( totalLength > contentLengthHeader ) {
183+ this . onError ( "content-length mismatch" ) ;
184+ res . close ( ) ; // calls onAborted
175185 return ;
176186 }
187+
188+ if ( ! buffer ) {
189+ if ( isLast ) {
190+ onEnd ( Buffer . from ( arrayBuffer ) ) ;
191+ return ;
192+ }
193+ buffer = Buffer . allocUnsafe ( contentLengthHeader ) ;
194+ }
195+
196+ Buffer . from ( arrayBuffer ) . copy ( buffer , contentLength ) ;
197+
177198 if ( isLast ) {
178- onEnd ( ) ;
199+ if ( totalLength != contentLengthHeader ) {
200+ this . onError ( "content-length mismatch" ) ;
201+ res . writeStatus ( "400 content-length mismatch" ) . end ( ) ;
202+ cleanup ( ) ;
203+ return ;
204+ }
205+ onEnd ( buffer ) ;
206+ return ;
179207 }
208+
209+ contentLength = totalLength ;
180210 } ) ;
181211 }
182212
0 commit comments