@@ -2,75 +2,51 @@ function getDelimiter(boundary) {
2
2
return `\r\n--${ boundary } \r\n` ;
3
3
}
4
4
5
- function getFinalDelimiter ( boundary ) {
6
- return `\r\n--${ boundary } --\r\n` ;
7
- }
8
-
9
5
function splitWithRest ( string , delim ) {
10
6
const index = string . indexOf ( delim ) ;
11
7
if ( index < 0 ) {
12
- return [ string ] ;
8
+ return [ undefined , string ] ;
13
9
}
14
10
return [ string . substring ( 0 , index ) , string . substring ( index + delim . length ) ] ;
15
11
}
16
12
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 ) ;
30
15
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 ) ;
38
17
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
+ }
52
25
}
53
26
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
61
29
return {
62
30
newBuffer : buffer ,
63
31
parts : previousParts ,
32
+ isPreamble
64
33
} ;
65
34
}
66
35
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' , '' ) ;
71
42
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 ) ;
74
49
}
75
- return { parts : newParts , newBuffer : '' } ;
50
+
51
+ return { parts, newBuffer : '' , isPreamble } ;
76
52
}
0 commit comments