@@ -10,11 +10,13 @@ const {
1010
1111const {
1212 kInspectorRequestId,
13+ kContentEncoding,
1314 kResourceType,
1415 getMonotonicTime,
1516 getNextRequestId,
1617 registerDiagnosticChannels,
1718 sniffMimeType,
19+ createDecompressor,
1820} = require ( 'internal/inspector/network' ) ;
1921const { Network } = require ( 'inspector' ) ;
2022const EventEmitter = require ( 'events' ) ;
@@ -27,6 +29,7 @@ const convertHeaderObject = (headers = {}) => {
2729 let host ;
2830 let charset ;
2931 let mimeType ;
32+ let contentEncoding ;
3033 const dict = { } ;
3134 for ( const { 0 : key , 1 : value } of ObjectEntries ( headers ) ) {
3235 const lowerCasedKey = key . toLowerCase ( ) ;
@@ -38,6 +41,9 @@ const convertHeaderObject = (headers = {}) => {
3841 charset = result . charset ;
3942 mimeType = result . mimeType ;
4043 }
44+ if ( lowerCasedKey === 'content-encoding' ) {
45+ contentEncoding = typeof value === 'string' ? value . toLowerCase ( ) : undefined ;
46+ }
4147 if ( typeof value === 'string' ) {
4248 dict [ key ] = value ;
4349 } else if ( ArrayIsArray ( value ) ) {
@@ -50,7 +56,7 @@ const convertHeaderObject = (headers = {}) => {
5056 dict [ key ] = String ( value ) ;
5157 }
5258 }
53- return [ dict , host , charset , mimeType ] ;
59+ return [ dict , host , charset , mimeType , contentEncoding ] ;
5460} ;
5561
5662/**
@@ -105,7 +111,10 @@ function onClientResponseFinish({ request, response }) {
105111 return ;
106112 }
107113
108- const { 0 : headers , 2 : charset , 3 : mimeType } = convertHeaderObject ( response . headers ) ;
114+ const { 0 : headers , 2 : charset , 3 : mimeType , 4 : contentEncoding } = convertHeaderObject ( response . headers ) ;
115+
116+ // Store content encoding on the request for later use
117+ request [ kContentEncoding ] = contentEncoding ;
109118
110119 Network . responseReceived ( {
111120 requestId : request [ kInspectorRequestId ] ,
@@ -121,24 +130,64 @@ function onClientResponseFinish({ request, response }) {
121130 } ,
122131 } ) ;
123132
124- // Unlike response.on('data', ...), this does not put the stream into flowing mode.
125- EventEmitter . prototype . on . call ( response , 'data' , ( chunk ) => {
126- Network . dataReceived ( {
127- requestId : request [ kInspectorRequestId ] ,
128- timestamp : getMonotonicTime ( ) ,
129- dataLength : chunk . byteLength ,
130- encodedDataLength : chunk . byteLength ,
131- data : chunk ,
133+ // Create a decompressor if the response is compressed
134+ const decompressor = createDecompressor ( contentEncoding ) ;
135+
136+ if ( decompressor ) {
137+ // Pipe decompressed data to DevTools
138+ decompressor . on ( 'data' , ( decompressedChunk ) => {
139+ Network . dataReceived ( {
140+ requestId : request [ kInspectorRequestId ] ,
141+ timestamp : getMonotonicTime ( ) ,
142+ dataLength : decompressedChunk . byteLength ,
143+ encodedDataLength : decompressedChunk . byteLength ,
144+ data : decompressedChunk ,
145+ } ) ;
132146 } ) ;
133- } ) ;
134147
135- // Wait until the response body is consumed by user code.
136- response . once ( 'end' , ( ) => {
137- Network . loadingFinished ( {
138- requestId : request [ kInspectorRequestId ] ,
139- timestamp : getMonotonicTime ( ) ,
148+ // Handle decompression errors gracefully - fall back to raw data
149+ decompressor . on ( 'error' , ( ) => {
150+ // If decompression fails, the raw data has already been sent via the fallback
140151 } ) ;
141- } ) ;
152+
153+ // Unlike response.on('data', ...), this does not put the stream into flowing mode.
154+ EventEmitter . prototype . on . call ( response , 'data' , ( chunk ) => {
155+ // Feed the chunk into the decompressor
156+ decompressor . write ( chunk ) ;
157+ } ) ;
158+
159+ // Wait until the response body is consumed by user code.
160+ response . once ( 'end' , ( ) => {
161+ // End the decompressor stream
162+ decompressor . end ( ) ;
163+ decompressor . once ( 'end' , ( ) => {
164+ Network . loadingFinished ( {
165+ requestId : request [ kInspectorRequestId ] ,
166+ timestamp : getMonotonicTime ( ) ,
167+ } ) ;
168+ } ) ;
169+ } ) ;
170+ } else {
171+ // No decompression needed, send data directly
172+ // Unlike response.on('data', ...), this does not put the stream into flowing mode.
173+ EventEmitter . prototype . on . call ( response , 'data' , ( chunk ) => {
174+ Network . dataReceived ( {
175+ requestId : request [ kInspectorRequestId ] ,
176+ timestamp : getMonotonicTime ( ) ,
177+ dataLength : chunk . byteLength ,
178+ encodedDataLength : chunk . byteLength ,
179+ data : chunk ,
180+ } ) ;
181+ } ) ;
182+
183+ // Wait until the response body is consumed by user code.
184+ response . once ( 'end' , ( ) => {
185+ Network . loadingFinished ( {
186+ requestId : request [ kInspectorRequestId ] ,
187+ timestamp : getMonotonicTime ( ) ,
188+ } ) ;
189+ } ) ;
190+ }
142191}
143192
144193module . exports = registerDiagnosticChannels ( [
0 commit comments