Rick-777
Rick-777

Reputation: 10248

Serving gzipped content for Go

I'm starting to write server-side applications in Go. I'd like to use the Accept-Encoding request header to determine whether to compress the response entity using GZIP. I had hoped to find a way to do this directly using the http.Serve or http.ServeFile methods.

This is quite a general requirement; did I miss something or do I need to roll my own solution?

Upvotes: 46

Views: 38923

Answers (4)

Rick-777
Rick-777

Reputation: 10248

For the sake of completeness, I eventually answered my own question with a handler that is simple and specialises in solving this issue.

This serves static files from a Go http server, including the asked-for performance-enhancing features. It is based on the standard net/http ServeFiles, with gzip/brotli and cache performance enhancements.

Upvotes: 2

nanmu42
nanmu42

Reputation: 1

There is yet another "out of the box" middleware now, supporting net/http and Gin:

https://github.com/nanmu42/gzip

net/http example:

import github.com/nanmu42/gzip

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        writeString(w, fmt.Sprintf("This content is compressed: l%sng!", strings.Repeat("o", 1000)))
    })

    // wrap http.Handler using default settings
    log.Println(http.ListenAndServe(fmt.Sprintf(":%d", 3001), gzip.DefaultHandler().WrapHandler(mux)))
}

func writeString(w http.ResponseWriter, payload string) {
    w.Header().Set("Content-Type", "text/plain; charset=utf8")
    _, _ = io.WriteString(w, payload+"\n")
}

Gin example:

import github.com/nanmu42/gzip

func main() {
    g := gin.Default()

    // use default settings
    g.Use(gzip.DefaultHandler().Gin)

    g.GET("/", func(c *gin.Context) {
        c.JSON(http.StatusOK, map[string]interface{}{
            "code": 0,
            "msg":  "hello",
            "data": fmt.Sprintf("l%sng!", strings.Repeat("o", 1000)),
        })
    })

    log.Println(g.Run(fmt.Sprintf(":%d", 3000)))
}

Upvotes: 0

rputikar
rputikar

Reputation: 1543

There is no “out of the box” support for gzip-compressed HTTP responses yet. But adding it is pretty trivial. Have a look at

https://gist.github.com/the42/1956518

also

https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/cgUp8_ATNtc

Upvotes: 30

Zippo
Zippo

Reputation: 16420

The New York Times have released their gzip middleware package for Go.

You just pass your http.HandlerFunc through their GzipHandler and you're done. It looks like this:

package main

import (
    "io"
    "net/http"
    "github.com/nytimes/gziphandler"
)

func main() {
    withoutGz := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "text/plain")
        io.WriteString(w, "Hello, World")
    })

    withGz := gziphandler.GzipHandler(withoutGz)

    http.Handle("/", withGz)
    http.ListenAndServe("0.0.0.0:8000", nil)
}

Upvotes: 30

Related Questions