Skip to content

Commit

Permalink
Add /brotli endpoint (#27)
Browse files Browse the repository at this point in the history
Parity with http://httpbin.org/ .  This is similar to #20 but uses a
Go-only implementation translated by c2go:

https://github.com/andybalholm/brotli
  • Loading branch information
gaul committed Sep 21, 2020
1 parent d5c855a commit 862fbad
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ This way, you can write tests without relying on an external dependency like [ht
- `/cache/:n` Sets a Cache-Control header for _n_ seconds.
- `/gzip` Returns gzip-encoded data.
- `/deflate` Returns deflate-encoded data.
- `/brotli` Returns brotli-encoded data.
- `/robots.txt` Returns some robots.txt rules.
- `/deny` Denied by robots.txt file.
- `/basic-auth/:user/:passwd` Challenges HTTP Basic Auth.
Expand Down
10 changes: 6 additions & 4 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import:
version: ~1.3.0
- package: github.com/pkg/errors
version: ~0.8.0
- package: github.com/andybalholm/brotli
version: ~1.0.0
testImport:
- package: github.com/stretchr/testify
version: ~1.2.1
Expand Down
21 changes: 21 additions & 0 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"strings"
"time"

"github.com/andybalholm/brotli"
"github.com/gorilla/mux"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -64,6 +65,7 @@ func GetMux() *mux.Router {
r.HandleFunc(`/cache`, CacheHandler).Methods(http.MethodGet, http.MethodHead)
r.HandleFunc(`/cache/{n:[\d]+}`, SetCacheHandler).Methods(http.MethodGet, http.MethodHead)
r.HandleFunc(`/gzip`, GZIPHandler).Methods(http.MethodGet, http.MethodHead)
r.HandleFunc(`/brotli`, BrotliHandler).Methods(http.MethodGet, http.MethodHead)
r.HandleFunc(`/deflate`, DeflateHandler).Methods(http.MethodGet, http.MethodHead)
r.HandleFunc(`/html`, HTMLHandler).Methods(http.MethodGet, http.MethodHead)
r.HandleFunc(`/xml`, XMLHandler).Methods(http.MethodGet, http.MethodHead)
Expand Down Expand Up @@ -441,6 +443,25 @@ func DeflateHandler(w http.ResponseWriter, r *http.Request) {
}
}

// BrotliHandler returns a Brotli-encoded response
func BrotliHandler(w http.ResponseWriter, r *http.Request) {
h, _, _ := net.SplitHostPort(r.RemoteAddr)

v := brotliResponse{
headersResponse: headersResponse{getHeaders(r)},
ipResponse: ipResponse{h},
Compressed: true,
}

w.Header().Set("Content-Type", "application/json")
w.Header().Add("Content-Encoding", "br")
ww := brotli.NewWriter(w)
defer ww.Close() // flush
if err := writeJSON(ww, v); err != nil {
writeErrorJSON(w, errors.Wrap(err, "failed to write json"))
}
}

// RobotsTXTHandler returns a robots.txt response.
func RobotsTXTHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
Expand Down
25 changes: 25 additions & 0 deletions handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"time"

"github.com/ahmetb/go-httpbin"
"github.com/andybalholm/brotli"
"github.com/stretchr/testify/require"

"golang.org/x/net/html/charset"
Expand Down Expand Up @@ -570,6 +571,30 @@ func TestDeflate(t *testing.T) {
require.True(t, v.Deflated)
}

func TestBrotli(t *testing.T) {
srv := testServer()
defer srv.Close()

client := new(http.Client)
req, err := http.NewRequest("GET", srv.URL+"/brotli", nil)
require.Nil(t, err)

req.Header.Add("Accept-Encoding", "br")
resp, err := client.Do(req)
require.Nil(t, err)
defer resp.Body.Close()

require.EqualValues(t, "br", resp.Header.Get("Content-Encoding"))
require.EqualValues(t, "application/json", resp.Header.Get("Content-Type"))
zr := brotli.NewReader(resp.Body)

var v struct {
Compressed bool `json:"compressed"`
}
require.Nil(t, json.NewDecoder(zr).Decode(&v))
require.True(t, v.Compressed)
}

func TestRobotsTXT(t *testing.T) {
srv := testServer()
defer srv.Close()
Expand Down
6 changes: 6 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ type deflateResponse struct {
Deflated bool `json:"deflated"`
}

type brotliResponse struct {
headersResponse
ipResponse
Compressed bool `json:"compressed"`
}

type basicAuthResponse struct {
Authenticated bool `json:"authenticated"`
User string `json:"user"`
Expand Down

0 comments on commit 862fbad

Please sign in to comment.