-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
155 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// Code in this file is taken from https://github.com/nytimes/gziphandler.git | ||
// which is licensed under Apache 2.0 | ||
|
||
package api | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
type codings map[string]float64 | ||
|
||
const ( | ||
// DefaultQValue is the default qvalue to assign to an encoding if no explicit qvalue is set. | ||
// This is actually kind of ambiguous in RFC 2616, so hopefully it's correct. | ||
// The examples seem to indicate that it is. | ||
DefaultQValue = 1.0 | ||
|
||
// DefaultMinSize is the default minimum size until we enable gzip compression. | ||
// 1500 bytes is the MTU size for the internet since that is the largest size allowed at the network layer. | ||
// If you take a file that is 1300 bytes and compress it to 800 bytes, it’s still transmitted in that same 1500 byte packet regardless, so you’ve gained nothing. | ||
// That being the case, you should restrict the gzip compression to files with a size greater than a single packet, 1400 bytes (1.4KB) is a safe value. | ||
DefaultMinSize = 1400 | ||
) | ||
|
||
// acceptsGzip returns true if the given HTTP request indicates that it will | ||
// accept a gzipped response. | ||
func acceptsGzip(r *http.Request) bool { | ||
acceptedEncodings, _ := parseEncodings(r.Header.Get(acceptEncoding)) | ||
return acceptedEncodings["gzip"] > 0.0 | ||
} | ||
|
||
// parseEncodings attempts to parse a list of codings, per RFC 2616, as might | ||
// appear in an Accept-Encoding header. It returns a map of content-codings to | ||
// quality values, and an error containing the errors encountered. It's probably | ||
// safe to ignore those, because silently ignoring errors is how the internet | ||
// works. | ||
// | ||
// See: http://tools.ietf.org/html/rfc2616#section-14.3. | ||
func parseEncodings(s string) (codings, error) { | ||
c := make(codings) | ||
var e []string | ||
|
||
for _, ss := range strings.Split(s, ",") { | ||
coding, qvalue, err := parseCoding(ss) | ||
|
||
if err != nil { | ||
e = append(e, err.Error()) | ||
} else { | ||
c[coding] = qvalue | ||
} | ||
} | ||
|
||
// TODO (adammck): Use a proper multi-error struct, so the individual errors | ||
// can be extracted if anyone cares. | ||
if len(e) > 0 { | ||
return c, fmt.Errorf("errors while parsing encodings: %s", strings.Join(e, ", ")) | ||
} | ||
|
||
return c, nil | ||
} | ||
|
||
// parseCoding parses a single conding (content-coding with an optional qvalue), | ||
// as might appear in an Accept-Encoding header. It attempts to forgive minor | ||
// formatting errors. | ||
func parseCoding(s string) (coding string, qvalue float64, err error) { | ||
for n, part := range strings.Split(s, ";") { | ||
part = strings.TrimSpace(part) | ||
qvalue = DefaultQValue | ||
|
||
if n == 0 { | ||
coding = strings.ToLower(part) | ||
} else if strings.HasPrefix(part, "q=") { | ||
qvalue, err = strconv.ParseFloat(strings.TrimPrefix(part, "q="), 64) | ||
|
||
if qvalue < 0.0 { | ||
qvalue = 0.0 | ||
} else if qvalue > 1.0 { | ||
qvalue = 1.0 | ||
} | ||
} | ||
} | ||
|
||
if coding == "" { | ||
err = fmt.Errorf("empty content-coding") | ||
} | ||
|
||
return | ||
} |