Skip to content

Commit 961aa05

Browse files
SjonHortensiusfjl
authored andcommitted
rpc: enable compression on HTTP transport (#19997)
This change adds support for gzip encoding on HTTP responses. Gzip encoding is used when the client sets the 'accept-encoding: gzip' header. Original change by @brianosaurus, with fixes from @SjonHortensius.
1 parent 54b271a commit 961aa05

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

rpc/gzip.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2019 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package rpc
18+
19+
import (
20+
"compress/gzip"
21+
"io"
22+
"io/ioutil"
23+
"net/http"
24+
"strings"
25+
"sync"
26+
)
27+
28+
var gzPool = sync.Pool{
29+
New: func() interface{} {
30+
w := gzip.NewWriter(ioutil.Discard)
31+
return w
32+
},
33+
}
34+
35+
type gzipResponseWriter struct {
36+
io.Writer
37+
http.ResponseWriter
38+
}
39+
40+
func (w *gzipResponseWriter) WriteHeader(status int) {
41+
w.Header().Del("Content-Length")
42+
w.ResponseWriter.WriteHeader(status)
43+
}
44+
45+
func (w *gzipResponseWriter) Write(b []byte) (int, error) {
46+
return w.Writer.Write(b)
47+
}
48+
49+
func newGzipHandler(next http.Handler) http.Handler {
50+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
51+
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
52+
next.ServeHTTP(w, r)
53+
return
54+
}
55+
56+
w.Header().Set("Content-Encoding", "gzip")
57+
58+
gz := gzPool.Get().(*gzip.Writer)
59+
defer gzPool.Put(gz)
60+
61+
gz.Reset(w)
62+
defer gz.Close()
63+
64+
next.ServeHTTP(&gzipResponseWriter{ResponseWriter: w, Writer: gz}, r)
65+
})
66+
}

rpc/http.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv ht
216216
// Wrap the CORS-handler within a host-handler
217217
handler := newCorsHandler(srv, cors)
218218
handler = newVHostHandler(vhosts, handler)
219+
handler = newGzipHandler(handler)
219220

220221
// Make sure timeout values are meaningful
221222
if timeouts.ReadTimeout < time.Second {

0 commit comments

Comments
 (0)