@@ -5,6 +5,12 @@ import staticRouter from "./src/static/staticRouter.js";
5
5
import * as ejs from "ejs" ;
6
6
import * as fastifyView from "@fastify/view" ;
7
7
import minifier from "html-minifier" ;
8
+ import { Stream } from "stream" ;
9
+ import toArray from "stream-to-array" ;
10
+ import zlib from "node:zlib" ;
11
+ import { pipeline } from "node:stream" ;
12
+ import { promisify } from "node:util" ;
13
+ import { getSizeRouter } from "./src/responseSize/responseSizeRouter.js" ;
8
14
9
15
/**
10
16
* Builds the server but does not start it. Need it for testing API
@@ -23,8 +29,92 @@ function buildServer(options = {}) {
23
29
} ,
24
30
} ) ;
25
31
32
+ fastify . decorate ( "responseSize" , {
33
+ use_compression : false ,
34
+ size_uncompressed : 0 ,
35
+ size_compressed : 0 ,
36
+ get : function ( ) {
37
+ return {
38
+ use_compression : this . use_compression ,
39
+ size_uncompressed : this . size_uncompressed ,
40
+ size_compressed : this . size_compressed ,
41
+ } ;
42
+ } ,
43
+ reset : function ( ) {
44
+ this . size_uncompressed = 0 ;
45
+ this . size_compressed = 0 ;
46
+ } ,
47
+ enableCompression : function ( val ) {
48
+ this . use_compression = val ;
49
+ } ,
50
+ add : function ( uncompressed , compressed ) {
51
+ this . size_uncompressed += uncompressed ;
52
+ this . size_compressed += compressed ;
53
+ } ,
54
+ } ) ;
55
+
56
+ fastify . register ( getSizeRouter ) ;
57
+
58
+ fastify . addHook ( "onSend" , async ( request , reply , payload ) => {
59
+ // const MISSING_HEADERS_AND_HTTP = 99;
60
+ let getSizeInfo = ( original , compressed ) => {
61
+ if ( ! compressed ) {
62
+ compressed = original ;
63
+ } else {
64
+ reply . header ( "Content-Length" , compressed . length ) ;
65
+ reply . header ( "Content-Encoding" , "br" ) ;
66
+ }
67
+ let headers = Object . entries ( reply . getHeaders ( ) ) . reduce ( ( p , [ e , v ] ) => p + `${ e } : ${ v } \n` , "" ) ;
68
+ // console.log(request.url, reply.statusCode, "\n", headers);
69
+ return {
70
+ compressed : compressed . length , // + headers.length + MISSING_HEADERS_AND_HTTP,
71
+ uncompressed : original . length , // + headers.length + MISSING_HEADERS_AND_HTTP
72
+ } ;
73
+ } ;
74
+
75
+ if ( request . url . startsWith ( "/css" ) || reply . statusCode != 200 || ! fastify . responseSize . use_compression ) {
76
+ return payload ;
77
+ } else {
78
+ if ( typeof payload == "string" ) {
79
+ let { uncompressed, compressed } = getSizeInfo ( payload ) ;
80
+ fastify . responseSize . add ( uncompressed , compressed ) ;
81
+ console . log (
82
+ `onSend: ${ request . url } as string with uncompressed size ${ uncompressed } sum uncompressed ${ fastify . responseSize . size_uncompressed } , compressed ${ fastify . responseSize . size_compressed } `
83
+ ) ;
84
+ } else if ( payload instanceof Stream ) {
85
+ return toArray ( payload )
86
+ . then ( ( chunks ) => {
87
+ const buffer = Buffer . concat ( chunks ) ;
88
+ if ( buffer . length >= 1024 ) {
89
+ let out = zlib . brotliCompressSync ( buffer ) ;
90
+ let { uncompressed, compressed } = getSizeInfo ( buffer , out ) ;
91
+ fastify . responseSize . add ( uncompressed , compressed ) ;
92
+ console . log (
93
+ `onSend: ${ request . url } as stream with uncompressed size ${ uncompressed } compressed ${ compressed } sum uncompressed ${ fastify . responseSize . size_uncompressed } , compressed ${ fastify . responseSize . size_compressed } `
94
+ ) ;
95
+ return out ;
96
+ } else {
97
+ let { uncompressed, compressed } = getSizeInfo ( buffer ) ;
98
+ fastify . responseSize . add ( uncompressed , compressed ) ;
99
+ console . log (
100
+ `onSend: ${ request . url } as stream with uncompressed size ${ uncompressed } (not compressed since below threshold) sum uncompressed ${ fastify . responseSize . size_uncompressed } , compressed ${ fastify . responseSize . size_compressed } `
101
+ ) ;
102
+ return buffer ;
103
+ }
104
+ } )
105
+ . catch ( ( err ) => {
106
+ console . log ( "onSend: Error" , err ) ;
107
+ } ) ;
108
+ } else {
109
+ console . log ( "onSend: Unknown payload type" , typeof payload , payload ) ;
110
+ }
111
+ return payload ;
112
+ }
113
+ } ) ;
114
+
26
115
fastify . addHook ( "onRequest" , ( request , reply , done ) => {
27
116
if ( request . url . endsWith ( "index.html" ) ) {
117
+ fastify . responseSize . reset ( ) ;
28
118
reply . header ( "Cross-Origin-Embedder-Policy" , "require-corp" ) ;
29
119
reply . header ( "Cross-Origin-Opener-Policy" , "same-origin" ) ;
30
120
}
0 commit comments