@@ -59,13 +59,8 @@ async function getDevServer(compilation) {
59
59
let response = new Response ( null , { status } ) ;
60
60
61
61
for ( const plugin of resourcePlugins ) {
62
- // ignore plugins that serve pages, as those will be handled by Greenwood's standard HTML plugin
63
- if (
64
- ! plugin . servePage &&
65
- plugin . shouldServe &&
66
- ( await plugin . shouldServe ( url , request , response . clone ( ) ) )
67
- ) {
68
- const current = await plugin . serve ( url , request , response . clone ( ) ) ;
62
+ if ( ! plugin . servePage && plugin . shouldServe && ( await plugin . shouldServe ( url , request ) ) ) {
63
+ const current = await plugin . serve ( url , request ) ;
69
64
const merged = mergeResponse ( response . clone ( ) , current . clone ( ) ) ;
70
65
71
66
response = merged . clone ( ) ;
@@ -98,17 +93,26 @@ async function getDevServer(compilation) {
98
93
headers : new Headers ( header ) ,
99
94
} ) ;
100
95
101
- let response = initResponse ;
102
- for ( const plugin of resourcePlugins ) {
96
+ // we explicitly use "async" reduce here to avoid race conditions / Body consumed errors
97
+ // when looping through and sharing responses between plugins
98
+ const response = await resourcePlugins . reduce ( async ( responsePromise , plugin ) => {
99
+ const intermediateResponse = await responsePromise ;
103
100
if (
104
101
plugin . shouldPreIntercept &&
105
- ( await plugin . shouldPreIntercept ( url , request , response . clone ( ) ) )
102
+ ( await plugin . shouldPreIntercept ( url , request , intermediateResponse . clone ( ) ) )
106
103
) {
107
- const current = await plugin . preIntercept ( url , request , response . clone ( ) ) ;
108
-
109
- response = mergeResponse ( response . clone ( ) , current . clone ( ) ) ;
104
+ const current = await plugin . preIntercept (
105
+ url ,
106
+ request ,
107
+ await intermediateResponse . clone ( ) ,
108
+ ) ;
109
+ const merged = mergeResponse ( intermediateResponse . clone ( ) , current ) ;
110
+
111
+ return Promise . resolve ( merged ) ;
112
+ } else {
113
+ return Promise . resolve ( await responsePromise ) ;
110
114
}
111
- }
115
+ } , Promise . resolve ( initResponse . clone ( ) ) ) ;
112
116
113
117
ctx . body = response . body ? Readable . from ( response . body ) : "" ;
114
118
ctx . message = response . statusText ;
@@ -135,17 +139,22 @@ async function getDevServer(compilation) {
135
139
headers : new Headers ( header ) ,
136
140
} ) ;
137
141
138
- let response = initResponse ;
139
- for ( const plugin of resourcePlugins ) {
142
+ // we explicitly use "async" reduce here to avoid race conditions / Body consumed errors
143
+ // when looping through and sharing responses between plugins
144
+ const response = await resourcePlugins . reduce ( async ( responsePromise , plugin ) => {
145
+ const intermediateResponse = await responsePromise ;
140
146
if (
141
147
plugin . shouldIntercept &&
142
- ( await plugin . shouldIntercept ( url , request , response . clone ( ) ) )
148
+ ( await plugin . shouldIntercept ( url , request , intermediateResponse . clone ( ) ) )
143
149
) {
144
- const current = await plugin . intercept ( url , request , response . clone ( ) ) ;
150
+ const current = await plugin . intercept ( url , request , await intermediateResponse . clone ( ) ) ;
151
+ const merged = mergeResponse ( intermediateResponse . clone ( ) , current ) ;
145
152
146
- response = mergeResponse ( response . clone ( ) , current . clone ( ) ) ;
153
+ return Promise . resolve ( merged ) ;
154
+ } else {
155
+ return Promise . resolve ( await responsePromise ) ;
147
156
}
148
- }
157
+ } , Promise . resolve ( initResponse . clone ( ) ) ) ;
149
158
150
159
ctx . body = response . body ? Readable . from ( response . body ) : "" ;
151
160
ctx . message = response . statusText ;
@@ -174,7 +183,7 @@ async function getDevServer(compilation) {
174
183
statusText : message ,
175
184
status,
176
185
headers : new Headers ( header ) ,
177
- } ) ;
186
+ } ) . clone ( ) ;
178
187
const splitResponse = response . clone ( ) ;
179
188
const contents = await splitResponse . text ( ) ;
180
189
const inm = ctx . headers [ "if-none-match" ] ;
0 commit comments