Skip to content
This repository was archived by the owner on Dec 7, 2020. It is now read-only.

Commit b48a022

Browse files
zt-svBruno Oliveira da Silva
authored andcommitted
Using compress/gzip
1 parent 4c3331a commit b48a022

File tree

6 files changed

+116
-0
lines changed

6 files changed

+116
-0
lines changed

config_sample.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ skip-upstream-tls-verify: true|false
4444
scopes: []
4545
# enables more extra security features
4646
enable-security-filter: true
47+
# enables gzip compression for response
48+
enable-compression: true
4749
# headers permits you to inject custom headers into all requests
4850
headers:
4951
myheader_name: my_header_value

doc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ type Config struct {
250250
ContentSecurityPolicy string `json:"content-security-policy" yaml:"content-security-policy" usage:"specify the content security policy"`
251251
// LocalhostMetrics indicated the metrics can only be consume via localhost
252252
LocalhostMetrics bool `json:"localhost-metrics" yaml:"localhost-metrics" usage:"enforces the metrics page can only been requested from 127.0.0.1"`
253+
// EnableCompression enables gzip compression for response
254+
EnableCompression bool `json:"enable-compression" yaml:"enable-compression" usage:"enable gzip compression for response"`
253255

254256
// AccessTokenDuration is default duration applied to the access token cookie
255257
AccessTokenDuration time.Duration `json:"access-token-duration" yaml:"access-token-duration" usage:"fallback cookie duration for the access token when using refresh tokens"`

middleware.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@ limitations under the License.
1616
package main
1717

1818
import (
19+
"compress/gzip"
1920
"context"
2021
"fmt"
22+
"io"
23+
"io/ioutil"
2124
"net/http"
2225
"regexp"
2326
"strings"
27+
"sync"
2428
"time"
2529

2630
uuid "github.com/gofrs/uuid"
@@ -38,6 +42,47 @@ const (
3842
normalizeFlags purell.NormalizationFlags = purell.FlagRemoveDotSegments | purell.FlagRemoveDuplicateSlashes
3943
)
4044

45+
var gzPool = sync.Pool{
46+
New: func() interface{} {
47+
w := gzip.NewWriter(ioutil.Discard)
48+
return w
49+
},
50+
}
51+
52+
type gzipResponseWriter struct {
53+
io.Writer
54+
http.ResponseWriter
55+
}
56+
57+
func (w *gzipResponseWriter) WriteHeader(status int) {
58+
w.Header().Del("Content-Length")
59+
w.ResponseWriter.WriteHeader(status)
60+
}
61+
62+
func (w *gzipResponseWriter) Write(b []byte) (int, error) {
63+
return w.Writer.Write(b)
64+
}
65+
66+
// gzipMiddleware is responsible for compressing a response
67+
func gzipMiddleware(next http.Handler) http.Handler {
68+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
69+
if !strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
70+
next.ServeHTTP(w, req)
71+
return
72+
}
73+
74+
w.Header().Set("Content-Encoding", "gzip")
75+
76+
gz := gzPool.Get().(*gzip.Writer)
77+
defer gzPool.Put(gz)
78+
79+
gz.Reset(w)
80+
defer gz.Close()
81+
82+
next.ServeHTTP(&gzipResponseWriter{ResponseWriter: w, Writer: gz}, req)
83+
})
84+
}
85+
4186
// entrypointMiddleware is custom filtering for incoming requests
4287
func entrypointMiddleware(next http.Handler) http.Handler {
4388
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {

middleware_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,3 +1598,66 @@ func TestRolesAdmissionHandlerClaims(t *testing.T) {
15981598
newFakeProxy(cfg).RunTests(t, []fakeRequest{c.Request})
15991599
}
16001600
}
1601+
1602+
func TestGzipCompression(t *testing.T) {
1603+
requests := []struct {
1604+
EnableCompression bool
1605+
Request fakeRequest
1606+
}{
1607+
{
1608+
EnableCompression: true,
1609+
Request: fakeRequest{
1610+
URI: "/gambol99.htm",
1611+
ExpectedProxy: true,
1612+
Headers: map[string]string{
1613+
"Accept-Encoding": "gzip, deflate, br",
1614+
},
1615+
ExpectedHeaders: map[string]string{
1616+
"Content-Encoding": "gzip",
1617+
},
1618+
},
1619+
},
1620+
{
1621+
EnableCompression: true,
1622+
Request: fakeRequest{
1623+
URI: testAdminURI,
1624+
ExpectedProxy: false,
1625+
Headers: map[string]string{
1626+
"Accept-Encoding": "gzip, deflate, br",
1627+
},
1628+
ExpectedHeaders: map[string]string{
1629+
"Content-Encoding": "gzip",
1630+
},
1631+
},
1632+
},
1633+
{
1634+
EnableCompression: false,
1635+
Request: fakeRequest{
1636+
URI: "/gambol99.htm",
1637+
ExpectedProxy: true,
1638+
Headers: map[string]string{
1639+
"Accept-Encoding": "gzip, deflate, br",
1640+
},
1641+
ExpectedNoProxyHeaders: []string{"Content-Encoding"},
1642+
},
1643+
},
1644+
{
1645+
EnableCompression: false,
1646+
Request: fakeRequest{
1647+
URI: testAdminURI,
1648+
ExpectedProxy: false,
1649+
Headers: map[string]string{
1650+
"Accept-Encoding": "gzip, deflate, br",
1651+
},
1652+
ExpectedNoProxyHeaders: []string{"Content-Encoding"},
1653+
},
1654+
},
1655+
}
1656+
1657+
for _, c := range requests {
1658+
cfg := newFakeKeycloakConfig()
1659+
cfg.Resources = []*Resource{{URL: "/admin*", Methods: allHTTPMethods}}
1660+
cfg.EnableCompression = c.EnableCompression
1661+
newFakeProxy(cfg).RunTests(t, []fakeRequest{c.Request})
1662+
}
1663+
}

server.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ func (r *oauthProxy) createReverseProxy() error {
174174
// @step: enable the entrypoint middleware
175175
engine.Use(entrypointMiddleware)
176176

177+
if r.config.EnableCompression {
178+
engine.Use(gzipMiddleware)
179+
}
177180
if r.config.EnableLogging {
178181
engine.Use(r.loggingMiddleware)
179182
}

server_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ func newFakeKeycloakConfig() *Config {
455455
EnableLogging: false,
456456
EnableLoginHandler: true,
457457
EnableTokenHeader: true,
458+
EnableCompression: false,
458459
Listen: "127.0.0.1:0",
459460
OAuthURI: "/oauth",
460461
OpenIDProviderTimeout: time.Second * 5,

0 commit comments

Comments
 (0)