Skip to content

Commit a076ad1

Browse files
committed
feat(serverHandler): enable response content compression if possible
1 parent 7b92a9d commit a076ad1

File tree

7 files changed

+105
-28
lines changed

7 files changed

+105
-28
lines changed

src/serverCompress/main.go

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package serverCompress
2+
3+
import (
4+
"io"
5+
"net/http"
6+
)
7+
8+
const minLengthDigits = 3
9+
10+
// responseWriter implements http.ResponseWriter
11+
type responseWriter struct {
12+
rw http.ResponseWriter
13+
r *http.Request
14+
writer io.Writer
15+
closer io.Closer
16+
}
17+
18+
func (rw *responseWriter) Header() http.Header {
19+
return rw.rw.Header()
20+
}
21+
22+
func (rw *responseWriter) Write(bs []byte) (int, error) {
23+
if rw.writer == nil {
24+
rw.init(0)
25+
}
26+
return rw.writer.Write(bs)
27+
}
28+
29+
func (rw *responseWriter) WriteHeader(status int) {
30+
if rw.writer == nil {
31+
rw.init(status)
32+
}
33+
rw.rw.WriteHeader(status)
34+
}
35+
36+
func (rw *responseWriter) init(status int) {
37+
lengthDigits := len(rw.rw.Header().Get("Content-Length"))
38+
if lengthDigits >= minLengthDigits || (lengthDigits == 0 && status/100 != 3) {
39+
wc, ok := GetWriter(rw.rw, rw.r)
40+
if ok {
41+
rw.writer = wc
42+
rw.closer = wc
43+
return
44+
}
45+
}
46+
47+
rw.writer = rw.rw
48+
}
49+
50+
func (rw *responseWriter) Close() {
51+
if rw.closer != nil {
52+
rw.closer.Close()
53+
}
54+
}
55+
56+
func NewResponseWriter(w http.ResponseWriter, r *http.Request) *responseWriter {
57+
return &responseWriter{
58+
rw: w,
59+
r: r,
60+
}
61+
}

src/serverCompress/util.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package serverCompress
2+
3+
import (
4+
"mjpclab.dev/ghfs/src/util"
5+
"strings"
6+
)
7+
8+
var compressibleTypes = []string{
9+
"application/javascript",
10+
"application/x-javascript",
11+
"application/json",
12+
"application/xhtml+xml",
13+
"application/xml",
14+
"image/svg+xml",
15+
}
16+
17+
func isCompressibleType(contentType string) bool {
18+
if strings.HasPrefix(contentType, "text/") {
19+
return true
20+
}
21+
22+
sepIndex := strings.IndexByte(contentType, ';')
23+
if sepIndex > 0 {
24+
contentType = contentType[:sepIndex]
25+
}
26+
return util.Contains(compressibleTypes, contentType)
27+
}

src/serverCompress/writer.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@ import (
88
"net/http"
99
)
1010

11+
const contentEncGzip = "gzip"
12+
const contentEncDeflate = "deflate"
13+
14+
var encodings = []string{contentEncGzip, contentEncDeflate}
15+
1116
func GetWriter(w http.ResponseWriter, r *http.Request) (wc io.WriteCloser, ok bool) {
1217
header := w.Header()
1318
if len(header.Get("Content-Encoding")) > 0 {
1419
return nil, false
1520
}
21+
if !isCompressibleType(header.Get("Content-Type")) {
22+
return nil, false
23+
}
1624

1725
accepts := acceptHeaders.ParseAccepts(r.Header.Get("Accept-Encoding"))
1826
_, encoding, hasSupportedEncoding := accepts.GetPreferredValue(encodings)

src/serverHandler/json.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package serverHandler
22

33
import (
44
"encoding/json"
5-
"io"
6-
"mjpclab.dev/ghfs/src/serverCompress"
75
"net/http"
86
"os"
97
"time"
@@ -87,17 +85,10 @@ func (h *aliasHandler) json(w http.ResponseWriter, r *http.Request, data *respon
8785
return
8886
}
8987

90-
var bodyW io.Writer
91-
if compressW, useCompressW := serverCompress.GetWriter(w, r); useCompressW {
92-
bodyW = compressW
93-
defer compressW.Close()
94-
} else {
95-
bodyW = w
96-
}
9788
w.WriteHeader(data.Status)
9889

9990
jsonData := getJsonData(data)
100-
encoder := json.NewEncoder(bodyW)
91+
encoder := json.NewEncoder(w)
10192
err := encoder.Encode(jsonData)
10293
h.logError(err)
10394
}

src/serverHandler/page.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ package serverHandler
22

33
import (
44
"html/template"
5-
"io"
65
"mjpclab.dev/ghfs/src/acceptHeaders"
76
"mjpclab.dev/ghfs/src/i18n"
8-
"mjpclab.dev/ghfs/src/serverCompress"
97
tplutil "mjpclab.dev/ghfs/src/tpl/util"
108
"mjpclab.dev/ghfs/src/util"
119
"net/http"
@@ -83,16 +81,9 @@ func (h *aliasHandler) page(w http.ResponseWriter, r *http.Request, data *respon
8381
return
8482
}
8583

86-
var bodyW io.Writer
87-
if compressW, useCompressW := serverCompress.GetWriter(w, r); useCompressW {
88-
defer compressW.Close()
89-
bodyW = compressW
90-
} else {
91-
bodyW = w
92-
}
9384
w.WriteHeader(data.Status)
9485

9586
updateSubItemsHtml(data)
96-
err := h.theme.RenderPage(bodyW, data)
87+
err := h.theme.RenderPage(w, data)
9788
h.logError(err)
9889
}

src/serverHandler/preprocessHandler.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package serverHandler
22

33
import (
44
"mjpclab.dev/ghfs/src/middleware"
5+
"mjpclab.dev/ghfs/src/serverCompress"
56
"mjpclab.dev/ghfs/src/serverLog"
67
"net/http"
78
)
@@ -15,23 +16,27 @@ type preprocessHandler struct {
1516
func (pph preprocessHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
1617
logRequest(pph.logger, r)
1718

19+
rw := serverCompress.NewResponseWriter(w, r)
20+
1821
if len(pph.preMiddlewares) > 0 {
1922
middlewareContext := &middleware.Context{
2023
PrefixReqPath: r.URL.RawPath, // init by pathTransformHandler
2124
VhostReqPath: r.URL.Path,
2225
Logger: pph.logger,
2326
}
2427
for i := range pph.preMiddlewares {
25-
processResult := pph.preMiddlewares[i](w, r, middlewareContext)
28+
processResult := pph.preMiddlewares[i](rw, r, middlewareContext)
2629
if processResult == middleware.Processed {
30+
rw.Close()
2731
return
2832
} else if processResult == middleware.SkipRests {
2933
break
3034
}
3135
}
3236
}
3337

34-
pph.nextHandler.ServeHTTP(w, r)
38+
pph.nextHandler.ServeHTTP(rw, r)
39+
rw.Close()
3540
}
3641

3742
func newPreprocessHandler(logger *serverLog.Logger, preMiddlewares []middleware.Middleware, nextHandler http.Handler) http.Handler {

0 commit comments

Comments
 (0)