Skip to content

Commit

Permalink
Merge pull request #1203 from hashicorp/f-gzip
Browse files Browse the repository at this point in the history
Compress HTTP API responses
  • Loading branch information
dadgar committed May 24, 2016
2 parents 4498288 + ef77f58 commit 18e565e
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 2 deletions.
45 changes: 45 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"bytes"
"compress/gzip"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -194,6 +195,7 @@ func (r *request) toHTTP() (*http.Request, error) {
return nil, err
}

req.Header.Add("Accept-Encoding", "gzip")
req.URL.Host = r.url.Host
req.URL.Scheme = r.url.Scheme
req.Host = r.url.Host
Expand Down Expand Up @@ -231,6 +233,26 @@ func (c *Client) newRequest(method, path string) *request {
return r
}

// multiCloser is to wrap a ReadCloser such that when close is called, multiple
// Closes occur.
type multiCloser struct {
reader io.Reader
inorderClose []io.Closer
}

func (m *multiCloser) Close() error {
for _, c := range m.inorderClose {
if err := c.Close(); err != nil {
return err
}
}
return nil
}

func (m *multiCloser) Read(p []byte) (int, error) {
return m.reader.Read(p)
}

// doRequest runs a request with our client
func (c *Client) doRequest(r *request) (time.Duration, *http.Response, error) {
req, err := r.toHTTP()
Expand All @@ -240,6 +262,29 @@ func (c *Client) doRequest(r *request) (time.Duration, *http.Response, error) {
start := time.Now()
resp, err := c.config.HttpClient.Do(req)
diff := time.Now().Sub(start)

// If the response is compressed, we swap the body's reader.
if resp != nil && resp.Header != nil {
var reader io.ReadCloser
switch resp.Header.Get("Content-Encoding") {
case "gzip":
greader, err := gzip.NewReader(resp.Body)
if err != nil {
return 0, nil, err
}

// The gzip reader doesn't close the wrapped reader so we use
// multiCloser.
reader = &multiCloser{
reader: greader,
inorderClose: []io.Closer{greader, resp.Body},
}
default:
reader = resp.Body
}
resp.Body = reader
}

return diff, resp, err
}

Expand Down
5 changes: 3 additions & 2 deletions command/agent/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strconv"
"time"

"github.com/NYTimes/gziphandler"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/ugorji/go/codec"
)
Expand Down Expand Up @@ -65,7 +66,7 @@ func NewHTTPServer(agent *Agent, config *Config, logOutput io.Writer) (*HTTPServ
srv.registerHandlers(config.EnableDebug)

// Start the server
go http.Serve(ln, mux)
go http.Serve(ln, gziphandler.GzipHandler(mux))
return srv, nil
}

Expand All @@ -86,7 +87,7 @@ func newScadaHttp(agent *Agent, list net.Listener) *HTTPServer {
srv.registerHandlers(false) // Never allow debug for SCADA

// Start the server
go http.Serve(list, mux)
go http.Serve(list, gziphandler.GzipHandler(mux))
return srv
}

Expand Down
13 changes: 13 additions & 0 deletions vendor/github.com/NYTimes/gziphandler/LICENSE.md

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

52 changes: 52 additions & 0 deletions vendor/github.com/NYTimes/gziphandler/README.md

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

144 changes: 144 additions & 0 deletions vendor/github.com/NYTimes/gziphandler/gzip.go

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

6 changes: 6 additions & 0 deletions vendor/vendor.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
"comment": "",
"ignore": "test",
"package": [
{
"checksumSHA1": "XeG94RjA9o/0wo9Fuw6NSRGYnjk=",
"path": "github.com/NYTimes/gziphandler",
"revision": "63027b26b87e2ae2ce3810393d4b81021cfd3a35",
"revisionTime": "2016-04-19T20:25:41Z"
},
{
"comment": "v0.8.7-87-g4b6ea73",
"path": "github.com/Sirupsen/logrus",
Expand Down
5 changes: 5 additions & 0 deletions website/source/docs/http/index.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ servicing the request. A target region can be explicitly specified with the `reg
parameter. The request will be transparently forwarded and serviced by a server in the
appropriate region.

## Compressed Responses

The HTTP API will gzip the response if the HTTP request denotes that the client accepts
gzip compression. This is achieved via the standard, `Accept-Encoding: gzip`

## Formatted JSON Output

By default, the output of all HTTP API requests is minimized JSON. If the client passes `pretty`
Expand Down

0 comments on commit 18e565e

Please sign in to comment.