- Building Microservices with Go
- Nic Jackson
- 461字
- 2021-07-15 17:28:12
Accept-Encoding - gzip, deflate
REST endpoints should always support gzip and deflate encoding, when applicable.
Implementing gzip support in Go is relatively straightforward; we showed how it is possible to implement middleware into your microservices in Chapter 1, Introduction to Microservices. In the following example, we will use this technique to create a gzip response writer.
The core of writing a response in a gzipped format is the compress/gzip package, which is part of the standard library. It allows you to create a Writer interface that implements ioWriteCloser wrapping an existing io.Writer, which writes to the given writer using the gzip compression:
func NewWriter(w io.Writer) *Writer
To create our handler we are going to write the NewGzipHandler function, this returns a new http.Handler that will wrap our standard output handler.
The first thing we need to do is create our own ResponseWriter that embeds http.ResponseWriter.
Example 2.1 chapter2/gzip/gzip_deflate.go:
68 type GzipResponseWriter struct {
69 gw *gzip.Writer
70 http.ResponseWriter
71}
The core method for this is the implementation of the Write method:
73 func (w GzipResponseWriter) Write(b []byte) (int, error) {
74 if _, ok := w.Header()["Content-Type"] !ok {
75 // If content type is not set, infer it from the uncompressed body.
76 w.Header().Set("Content-Type", http.DetectContentType(b))
77 }
78 return w.gw.Write(b)
79 }
If you look at the implementation for Write in the standard http.Response struct there is a whole load of stuff going on in there that we neither want to lose or re-implement because the gzip.Writer object is created with a writer when we call Write on it, it then in turn calls write on http.Response and we lose none of the complexity.
Internally in our NewGzipHandler our handler checks to see if the client has sent the Accept-Encoding header and if so we will write the response using the GzipResponseWriter method if the client has requested uncompressed content then we only call ServeHttp with the standard ResponseWriter:
40 type GZipHandler struct {
41 next http.Handler
42 }
43
44 func (h *GZipHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
45 encodings := r.Header.Get("Accept-Encoding")
46
47 if strings.Contains(encodings, "gzip") {
48 h.serveGzipped(w, r)
49 } else if strings.Contains(encodings, "deflate") {
50 panic("Deflate not implemented")
51 } else {
52 h.servePlain(w, r)
53 }
54 }
55
56 func (h *GZipHandler) serveGzipped(w http.ResponseWriter, r *http.Request) {
57 gzw := gzip.NewWriter(w)
58 defer gzw.Close()
59
60 w.Header().Set("Content-Encoding", "gzip")
61 h.next.ServeHTTP(GzipResponseWriter{gzw, w}, r)
62 }
63 func (h *GZipHandler) servePlain(w http.ResponseWriter, r *http.Request) 64 {
65 h.next.ServeHTTP(w, r)
66 }
This is by no means a comprehensive example and there are many open source packages like the one from the team at the NY Times (https://github.com/NYTimes/gziphandler), which manages this for you.
As a little programming test, why not try and modify this example to implement DEFLATE.
- C語言程序設計案例教程
- Mastering Objectoriented Python
- 技術領導力:程序員如何才能帶團隊
- 程序員考試案例梳理、真題透解與強化訓練
- Python應用輕松入門
- SEO實戰密碼
- Jupyter數據科學實戰
- 大數據分析與應用實戰:統計機器學習之數據導向編程
- Swift 4從零到精通iOS開發
- HTML5+CSS3+jQuery Mobile APP與移動網站設計從入門到精通
- 從Excel到Python數據分析:Pandas、xlwings、openpyxl、Matplotlib的交互與應用
- C Primer Plus(第6版)中文版【最新修訂版】
- JBoss AS 7 Development
- 數據結構與算法詳解
- 前端程序員面試算法寶典