38
38
authToken = []byte ("token" )
39
39
)
40
40
41
+ // CompressionType is the type of otuput compression available in fasthttp
42
+ // for the response body.
43
+ type CompressionType string
44
+
45
+ const (
46
+ CompressionZstd CompressionType = "zstd"
47
+ CompressionBr CompressionType = "br"
48
+ CompressionGzip CompressionType = "gzip"
49
+ CompressionDeflate CompressionType = "deflate"
50
+ )
51
+
41
52
// FastRequestHandler is the fastglue HTTP request handler function
42
53
// that wraps over the fasthttp handler.
43
54
type FastRequestHandler func (* Request ) error
@@ -53,21 +64,52 @@ type Request struct {
53
64
Context interface {}
54
65
}
55
66
67
+ // CompressionOpt is the configuration for enabling and controlling compression.
68
+ // Enabling this will automatically compress the response based on the client's
69
+ // Accept-Encoding header by internally invoking fasthttp.CompressHandler()
70
+ // gzip|deflate|br|zstd are the supported compression types.
71
+ type CompressionOpt struct {
72
+ Enabled bool
73
+
74
+ // Type of compression to support (std, gzip, deflate, br). If no type is specified
75
+ // then fasthttp's default compression types and its internal order of priority are used.
76
+ //
77
+ // Important: The first type in the list is the preferred type
78
+ // irrespective of the ordering of types in the incoming client's Accept-Encoding header.
79
+ // That is because fasthttp's CompressHandler() internally uses arbitrary
80
+ // type ordering to compress the response. fastglue thus overrides the
81
+ // Accept-Encoding header to only have the first type in this list.
82
+ // For instance, if the list here is [zstd, br], and the incoming header is
83
+ // [gzip, deflate, br, zstd], fastglue will overwrite the header to [zstd],
84
+ // forcing fasthttp to compress the response using the preferred type here.
85
+ Types []CompressionType
86
+ }
87
+
56
88
// Fastglue is the "glue" wrapper over fasthttp and fasthttprouter.
57
89
type Fastglue struct {
58
90
Router * fasthttprouter.Router
59
91
Server * fasthttp.Server
60
- context interface {}
61
92
MatchedRoutePathParam string
62
- before []FastMiddleware
63
- after []FastMiddleware
93
+
94
+ context interface {}
95
+ before []FastMiddleware
96
+ after []FastMiddleware
97
+
98
+ opt Options
99
+ }
100
+
101
+ type Options struct {
102
+ CompressionOpt CompressionOpt
64
103
}
65
104
66
105
// New creates and returns a new instance of Fastglue.
67
- func New () * Fastglue {
68
- return & Fastglue {
106
+ func New (o Options ) * Fastglue {
107
+ f := & Fastglue {
69
108
Router : fasthttprouter .New (),
109
+ opt : o ,
70
110
}
111
+
112
+ return f
71
113
}
72
114
73
115
// ListenAndServe is a wrapper for fasthttp.ListenAndServe. It takes a TCP address,
@@ -150,7 +192,7 @@ func (f *Fastglue) Shutdown(s *fasthttp.Server, shutdownComplete chan error) {
150
192
// handler is the "proxy" abstraction that converts a fastglue handler into
151
193
// a fasthttp handler and passes execution in and out.
152
194
func (f * Fastglue ) handler (h FastRequestHandler ) func (* fasthttp.RequestCtx ) {
153
- return func (ctx * fasthttp.RequestCtx ) {
195
+ handler := func (ctx * fasthttp.RequestCtx ) {
154
196
req := & Request {
155
197
RequestCtx : ctx ,
156
198
Context : f .context ,
@@ -172,7 +214,35 @@ func (f *Fastglue) handler(h FastRequestHandler) func(*fasthttp.RequestCtx) {
172
214
}
173
215
}
174
216
217
+ // If compression is enabled, override the response header to
218
+ // the preferred type in the config.
219
+ if f .opt .CompressionOpt .Enabled {
220
+ for _ , typ := range f .opt .CompressionOpt .Types {
221
+ t := string (typ )
222
+ // If the preferred type is in the client's Accept-Encoding header,
223
+ // overwrite the request header to only have this type, forcing
224
+ // fasthttp.CompressHandler() to compress the response using it.
225
+ // This is because fasthttp internally does not respect the order
226
+ // in the client header and uses arbitrary ordering to compress the response.
227
+ if ctx .Request .Header .HasAcceptEncoding (t ) {
228
+ ctx .Request .Header .Set ("Accept-Encoding" , t )
229
+ break
230
+ }
231
+ }
232
+ }
233
+ }
234
+
235
+ // If compression is enabled, wrap the handler with fasthttp's CompressHandler
236
+ // which automatically handles the compression logic.
237
+ if f .opt .CompressionOpt .Enabled {
238
+ // fasthttp's compression handlers are pretty bad. This particular handler
239
+ // is the one that supports gzip|br|zstd|deflate.
240
+ return fasthttp .CompressHandlerBrotliLevel (handler ,
241
+ fasthttp .CompressBrotliDefaultCompression ,
242
+ fasthttp .CompressDefaultCompression )
175
243
}
244
+
245
+ return handler
176
246
}
177
247
178
248
// Handler returns fastglue's central fasthttp handler that can be registered
0 commit comments