@@ -8,6 +8,10 @@ import (
8
8
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
9
9
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
10
10
"github.com/h2non/bimg"
11
+ "github.com/klauspost/compress/gzip"
12
+ "github.com/klauspost/compress/zstd"
13
+ "go.uber.org/zap"
14
+ "io"
11
15
"net/http"
12
16
"strconv"
13
17
)
@@ -18,7 +22,9 @@ func init() {
18
22
httpcaddyfile .RegisterDirectiveOrder ("image_processor" , "before" , "respond" )
19
23
}
20
24
21
- type Middleware struct {}
25
+ type Middleware struct {
26
+ logger * zap.Logger
27
+ }
22
28
23
29
func (Middleware ) CaddyModule () caddy.ModuleInfo {
24
30
return caddy.ModuleInfo {
@@ -27,6 +33,11 @@ func (Middleware) CaddyModule() caddy.ModuleInfo {
27
33
}
28
34
}
29
35
36
+ func (m Middleware ) Provision (ctx caddy.Context ) error {
37
+ m .logger = ctx .Logger ()
38
+ return nil
39
+ }
40
+
30
41
func (m Middleware ) ServeHTTP (w http.ResponseWriter , r * http.Request , next caddyhttp.Handler ) error {
31
42
32
43
//Automatic return if not options set
@@ -46,26 +57,85 @@ func (m Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddy
46
57
return responseRecorder .WriteResponse ()
47
58
}
48
59
60
+ decoded , err := m .getDecodedBufferFromResponse (& responseRecorder )
61
+ if err != nil {
62
+ m .logger .Error ("error getting initial response" , zap .Error (err ))
63
+ return responseRecorder .WriteResponse ()
64
+ }
65
+
49
66
options , err := getOptions (r )
50
67
if err != nil {
51
- return err
68
+ m .logger .Error ("error parsing options" , zap .Error (err ))
69
+ return responseRecorder .WriteResponse ()
52
70
}
53
71
54
- newImage , err := bimg .NewImage (responseRecorder . Buffer (). Bytes () ).Process (options )
72
+ newImage , err := bimg .NewImage (decoded ).Process (options )
55
73
if err != nil {
74
+ m .logger .Error ("error processing image" , zap .Error (err ))
56
75
return responseRecorder .WriteResponse ()
57
76
}
58
77
78
+ // Remove intercepted headers from buffer
79
+ for header , _ := range w .Header () {
80
+ w .Header ().Del (header )
81
+ }
82
+
59
83
w .Header ().Set ("Content-Length" , strconv .Itoa (len (newImage )))
60
84
w .Header ().Set ("Content-Type" , "image/" + bimg .DetermineImageTypeName (newImage ))
61
85
62
86
if _ , err = w .Write (newImage ); err != nil {
63
- return err
87
+ m .logger .Error ("error writing processed image" , zap .Error (err ))
88
+ return responseRecorder .WriteResponse ()
64
89
}
65
90
66
91
return nil
67
92
}
68
93
94
+ func (m * Middleware ) getDecodedBufferFromResponse (r * caddyhttp.ResponseRecorder ) ([]byte , error ) {
95
+
96
+ encoding := (* r ).Header ().Get ("Content-Encoding" )
97
+ if encoding == "" {
98
+ return (* r ).Buffer ().Bytes (), nil
99
+ }
100
+
101
+ if encoding == "gzip" {
102
+ decoder , err := gzip .NewReader ((* r ).Buffer ())
103
+ if err != nil {
104
+ return nil , err
105
+ }
106
+ defer func (decoder * gzip.Reader ) {
107
+ err := decoder .Close ()
108
+ if err != nil {
109
+ return
110
+ }
111
+ }(decoder )
112
+
113
+ decodedOut := bytes.Buffer {}
114
+ _ , err = io .Copy (& decodedOut , decoder )
115
+ if err != nil {
116
+ return nil , err
117
+ }
118
+ return decodedOut .Bytes (), nil
119
+ }
120
+
121
+ if encoding == "zstd" {
122
+ // Try decode zstd
123
+ var decoder , err = zstd .NewReader ((* r ).Buffer (), zstd .WithDecoderConcurrency (0 ))
124
+ if err != nil {
125
+ return nil , err
126
+ }
127
+ defer decoder .Close ()
128
+ decodedOut := bytes.Buffer {}
129
+ _ , err = io .Copy (& decodedOut , decoder )
130
+ if err != nil {
131
+ return nil , err
132
+ }
133
+ return decodedOut .Bytes (), nil
134
+ }
135
+
136
+ return nil , fmt .Errorf ("unsupported encoding: %s" , encoding )
137
+
138
+ }
69
139
func (m * Middleware ) UnmarshalCaddyfile (d * caddyfile.Dispenser ) error {
70
140
return nil
71
141
@@ -239,6 +309,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
239
309
240
310
// Interface guards
241
311
var (
312
+ _ caddy.Provisioner = (* Middleware )(nil )
242
313
_ caddyhttp.MiddlewareHandler = (* Middleware )(nil )
243
314
_ caddyfile.Unmarshaler = (* Middleware )(nil )
244
315
)
0 commit comments