@@ -19,11 +19,16 @@ const https = require('https');
19
19
const url = require ( 'url' ) ;
20
20
const fs = require ( 'fs' ) ;
21
21
const path = require ( 'path' ) ;
22
+ const zlib = require ( 'zlib' ) ;
23
+ const util = require ( 'util' ) ;
22
24
const WebSocketServer = require ( 'ws' ) . Server ;
23
25
24
26
const fulfillSymbol = Symbol ( 'fullfil callback' ) ;
25
27
const rejectSymbol = Symbol ( 'reject callback' ) ;
26
28
29
+ const readFileAsync = util . promisify ( fs . readFile . bind ( fs ) ) ;
30
+ const gzipAsync = util . promisify ( zlib . gzip . bind ( zlib ) ) ;
31
+
27
32
class TestServer {
28
33
/**
29
34
* @param {string } dirPath
@@ -236,7 +241,7 @@ class TestServer {
236
241
* @param {!http.ServerResponse } response
237
242
* @param {string|undefined } filePath
238
243
*/
239
- serveFile ( request , response , filePath ) {
244
+ async serveFile ( request , response , filePath ) {
240
245
let pathName = url . parse ( request . url ) . path ;
241
246
if ( ! filePath ) {
242
247
if ( pathName === '/' )
@@ -258,27 +263,29 @@ class TestServer {
258
263
if ( this . _csp . has ( pathName ) )
259
264
response . setHeader ( 'Content-Security-Policy' , this . _csp . get ( pathName ) ) ;
260
265
261
- fs . readFile ( filePath , ( err , data ) => {
262
- if ( err ) {
263
- response . statusCode = 404 ;
264
- response . end ( `File not found: ${ filePath } ` ) ;
265
- return ;
266
- }
267
- const extension = filePath . substring ( filePath . lastIndexOf ( '.' ) + 1 ) ;
268
- const mimeType = extensionToMime [ extension ] || 'application/octet-stream' ;
269
- const isTextEncoding = / ^ t e x t \/ | ^ a p p l i c a t i o n \/ ( j a v a s c r i p t | j s o n ) / . test ( mimeType ) ;
270
- const contentType = isTextEncoding ? `${ mimeType } ; charset=utf-8` : mimeType ;
271
- response . setHeader ( 'Content-Type' , contentType ) ;
272
- if ( this . _gzipRoutes . has ( pathName ) ) {
273
- response . setHeader ( 'Content-Encoding' , 'gzip' ) ;
274
- const zlib = require ( 'zlib' ) ;
275
- zlib . gzip ( data , ( _ , result ) => {
276
- response . end ( result ) ;
277
- } ) ;
278
- } else {
279
- response . end ( data ) ;
280
- }
281
- } ) ;
266
+ const { err, data} = await readFileAsync ( filePath ) . then ( data => ( { data} ) ) . catch ( err => ( { err} ) ) ;
267
+ // The HTTP transaction might be already terminated after async hop here - do nothing in this case.
268
+ if ( response . writableEnded )
269
+ return ;
270
+ if ( err ) {
271
+ response . statusCode = 404 ;
272
+ response . end ( `File not found: ${ filePath } ` ) ;
273
+ return ;
274
+ }
275
+ const extension = filePath . substring ( filePath . lastIndexOf ( '.' ) + 1 ) ;
276
+ const mimeType = extensionToMime [ extension ] || 'application/octet-stream' ;
277
+ const isTextEncoding = / ^ t e x t \/ | ^ a p p l i c a t i o n \/ ( j a v a s c r i p t | j s o n ) / . test ( mimeType ) ;
278
+ const contentType = isTextEncoding ? `${ mimeType } ; charset=utf-8` : mimeType ;
279
+ response . setHeader ( 'Content-Type' , contentType ) ;
280
+ if ( this . _gzipRoutes . has ( pathName ) ) {
281
+ response . setHeader ( 'Content-Encoding' , 'gzip' ) ;
282
+ const result = await gzipAsync ( data ) ;
283
+ // The HTTP transaction might be already terminated after async hop here.
284
+ if ( ! response . writableEnded )
285
+ response . end ( result ) ;
286
+ } else {
287
+ response . end ( data ) ;
288
+ }
282
289
}
283
290
284
291
_onWebSocketConnection ( ws ) {
0 commit comments