@@ -4,6 +4,8 @@ import * as fs from 'node:fs/promises';
44import { createReadStream , readFileSync , statSync } from 'node:fs' ;
55import * as path from 'node:path' ;
66import { Buffer } from 'node:buffer' ;
7+ import { createBrotliCompress , createDeflate , createGzip } from 'node:zlib' ;
8+ import type { Gzip } from 'node:zlib' ;
79import chalk from 'chalk' ;
810import * as ejs from 'ejs' ;
911import mine from 'mime' ;
@@ -17,6 +19,7 @@ export default class Server {
1719 data : { [ k : string ] : ResourceItem [ ] } = { } ;
1820 cors : boolean = false ;
1921 cache : boolean = true ;
22+ compress : boolean = false ;
2023
2124 constructor ( options ?: ServerOptions ) {
2225 if ( options ?. port ) {
@@ -40,6 +43,9 @@ export default class Server {
4043 if ( ! options ?. cache ) {
4144 this . cache = false ;
4245 }
46+ if ( options ?. compress ) {
47+ this . compress = true ;
48+ }
4349 }
4450
4551 start ( ) {
@@ -57,7 +63,7 @@ export default class Server {
5763 if ( stat . isDirectory ( ) ) {
5864 this . processDirectory ( wholePath , res , requestUrl ) ;
5965 } else {
60- this . processFile ( wholePath , res ) ;
66+ this . processFile ( wholePath , res , req ) ;
6167 }
6268 }
6369 } catch {
@@ -92,11 +98,20 @@ export default class Server {
9298 res . end ( html ) ;
9399 }
94100
95- private async processFile ( file : string , res : Res ) {
101+ private async processFile ( file : string , res : Res , req : Req ) {
96102 if ( this . cache ) {
97103 this . processCache ( res , file ) ; // The homepage will not be cached.
98104 }
99105 res . setHeader ( 'Content-Type' , `${ mine . getType ( file ) ?? 'text/plain' } ;charset=utf-8` ) ;
106+ if ( this . compress ) {
107+ const compressedStreamResponse = this . processCompress ( req ) ;
108+ if ( compressedStreamResponse ) {
109+ const [ compressedStream , encoding ] = compressedStreamResponse ;
110+ res . setHeader ( 'Content-Encoding' , encoding ) ;
111+ createReadStream ( file ) . pipe ( compressedStream ) . pipe ( res ) ;
112+ return ;
113+ }
114+ }
100115 createReadStream ( file ) . pipe ( res ) ;
101116 }
102117
@@ -244,4 +259,15 @@ export default class Server {
244259 return res . end ( ) ;
245260 }
246261 }
262+
263+ private processCompress ( req : Req ) : [ Gzip , string ] | undefined {
264+ const acceptEncoding = req . headers [ 'accept-encoding' ] ;
265+ if ( acceptEncoding ?. includes ( 'gzip' ) ) {
266+ return [ createGzip ( ) , 'gzip' ] ;
267+ } else if ( acceptEncoding ?. includes ( 'deflate' ) ) {
268+ return [ createDeflate ( ) , 'deflate' ] ;
269+ } else if ( acceptEncoding ?. includes ( 'br' ) ) {
270+ return [ createBrotliCompress ( ) , 'br' ] ;
271+ }
272+ }
247273}
0 commit comments