@@ -2,75 +2,51 @@ function getDelimiter(boundary) {
22 return `\r\n--${ boundary } \r\n` ;
33}
44
5- function getFinalDelimiter ( boundary ) {
6- return `\r\n--${ boundary } --\r\n` ;
7- }
8-
95function splitWithRest ( string , delim ) {
106 const index = string . indexOf ( delim ) ;
117 if ( index < 0 ) {
12- return [ string ] ;
8+ return [ undefined , string ] ;
139 }
1410 return [ string . substring ( 0 , index ) , string . substring ( index + delim . length ) ] ;
1511}
1612
17- export function parseMultipartHttp ( buffer , boundary , previousParts = [ ] ) {
18- const delimeter = getDelimiter ( boundary ) ;
19- let [ , rest ] = splitWithRest ( buffer , delimeter ) ;
20- if ( ! ( rest && rest . length ) ) {
21- // we did not finish receiving the initial delimeter
22- return {
23- newBuffer : buffer ,
24- parts : previousParts ,
25- } ;
26- }
27- const parts = splitWithRest ( rest , '\r\n\r\n' ) ;
28- const headers = parts [ 0 ] ;
29- rest = parts [ 1 ] ;
13+ export function parseMultipartHttp ( buffer , boundary , previousParts = [ ] , isPreamble = true ) {
14+ const delimiter = getDelimiter ( boundary ) ;
3015
31- if ( ! ( rest && rest . length ) ) {
32- // we did not finish receiving the headers
33- return {
34- newBuffer : buffer ,
35- parts : previousParts ,
36- } ;
37- }
16+ const [ region , next ] = splitWithRest ( buffer , delimiter ) ;
3817
39- const headersArr = headers . split ( '\r\n' ) ;
40- const contentLengthHeader = headersArr . find (
41- ( headerLine ) => headerLine . toLowerCase ( ) . indexOf ( 'content-length:' ) >= 0
42- ) ;
43- if ( contentLengthHeader === undefined ) {
44- throw new Error ( 'Invalid MultiPart Response, no content-length header' ) ;
45- }
46- const contentLengthArr = contentLengthHeader . split ( ':' ) ;
47- let contentLength ;
48- if ( contentLengthArr . length === 2 && ! isNaN ( parseInt ( contentLengthArr [ 1 ] ) ) ) {
49- contentLength = parseInt ( contentLengthArr [ 1 ] ) ;
50- } else {
51- throw new Error ( 'Invalid MultiPart Response, could not parse content-length' ) ;
18+ if ( region !== undefined && ( region . length || region . trim ( ) === '' ) && isPreamble ) {
19+ if ( next && next . length ) {
20+ // if we have stuff after the boundary; and we're in preamble—we recurse
21+ return parseMultipartHttp ( next , boundary , previousParts , false ) ;
22+ } else {
23+ return { newBuffer : '' , parts : previousParts , isPreamble : false } ;
24+ }
5225 }
5326
54- // Strip out the final delimiter
55- const finalDelimeter = getFinalDelimiter ( boundary ) ;
56- rest = rest . replace ( finalDelimeter , '' ) ;
57- const uint = new TextEncoder ( ) . encode ( rest ) ;
58-
59- if ( uint . length < contentLength ) {
60- // still waiting for more body to be sent;
27+ if ( ! ( region && region . length ) ) {
28+ // we need more things
6129 return {
6230 newBuffer : buffer ,
6331 parts : previousParts ,
32+ isPreamble
6433 } ;
6534 }
6635
67- const body = new TextDecoder ( ) . decode ( uint . subarray ( 0 , contentLength ) ) ;
68- const nextBuffer = new TextDecoder ( ) . decode ( uint . subarray ( contentLength ) ) ;
69- const part = JSON . parse ( body ) ;
70- const newParts = [ ...previousParts , part ] ;
36+ let [ _headers , body ] = splitWithRest ( region , '\r\n\r\n' ) ;
37+
38+ // remove trailing boundary things
39+ body = body
40+ . replace ( delimiter + '\r\n' , '' )
41+ . replace ( delimiter + '--\r\n' , '' ) ;
7142
72- if ( nextBuffer . length ) {
73- return parseMultipartHttp ( nextBuffer , boundary , newParts ) ;
43+ const payload = JSON . parse ( body ) ;
44+ const parts = [ ...previousParts , payload ] ;
45+
46+ if ( next && next . length ) {
47+ // we have more parts
48+ return parseMultipartHttp ( next , boundary , parts , isPreamble ) ;
7449 }
75- return { parts : newParts , newBuffer : '' } ;
50+
51+ return { parts, newBuffer : '' , isPreamble } ;
7652}
0 commit comments