Skip to content
Snippets Groups Projects
Commit 16a105f9 authored by Will McCutchen's avatar Will McCutchen
Browse files

WIP

parent 4ec6c82f
No related branches found
No related tags found
No related merge requests found
......@@ -339,3 +339,61 @@ func (b *base64Helper) Decode() ([]byte, error) {
_, err := base64.StdEncoding.Decode(buff, []byte(b.data))
return buff, err
}
// parseAcceptEncodings parses an Accept-Encoding header value into a map of
// coding name and weight. Invalid or malformed codings are ignored, and
// parsing does not attempt to accommodate variations in whitespace in the
// input format.
//
// For more info:
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
// https://httpwg.org/specs/rfc9110.html#field.accept-encoding
func parseAcceptEncodings(acceptEncodingHeaderVal string) codings {
var (
codingVals = strings.Split(acceptEncodingHeaderVal, ",")
result = make(codings, 0, len(codingVals))
)
for _, codingVal := range codingVals {
if idx := strings.Index(codingVal, ";"); idx > -1 {
// should have a ;q=x.y weight
if !strings.HasPrefix(codingVal[idx:], ";q=") {
continue
}
// 3 == len(";q=")
if q, err := strconv.ParseFloat(codingVal[idx+3:], 64); err == nil {
name := strings.TrimSpace(codingVal[:idx])
if len(name) > 0 {
result = append(result, coding{name, q})
}
}
} else {
// no weight given, default to 1.0
name := strings.TrimSpace(codingVal)
if len(name) > 0 {
result = append(result, coding{name, 1.0})
}
}
}
return result
}
type coding struct {
name string
weight float64
}
type codings []coding
func (cs codings) Preferred() string {
var (
result string
best float64
)
for _, c := range cs {
if c.weight > best {
result = c.name
best = c.weight
}
}
return result
}
......@@ -215,3 +215,94 @@ func Test_getClientIP(t *testing.T) {
})
}
}
func TestParseAcceptEncodings(t *testing.T) {
t.Parallel()
testCases := []struct {
given string
expected codings
expectPreferred string
}{
{
given: "gzip",
expected: codings{{"gzip", 1.0}},
expectPreferred: "gzip",
},
{
given: "gzip, compress, br",
expected: codings{{"gzip", 1.0}, {"compress", 1.0}, {"br", 1.0}},
expectPreferred: "gzip", // first entry wins tie
},
{
given: "br;q=0.8, gzip;q=1.0, *;q=0.1",
expected: codings{{"br", 0.8}, {"gzip", 1.0}, {"*", 0.1}},
expectPreferred: "gzip",
},
{
given: "deflate, gzip;q=1.0, *;q=0.5",
expected: codings{{"deflate", 1.0}, {"gzip", 1.0}, {"*", 0.5}},
expectPreferred: "deflate",
},
{
given: "",
expected: codings{},
},
{
given: " ",
expected: codings{},
},
{
// malformed entry ignored
given: "deflate, ;",
expected: codings{{"deflate", 1.0}},
expectPreferred: "deflate",
},
{
// malformed entry ignored
given: "deflate, gzip;",
expected: codings{{"deflate", 1.0}},
expectPreferred: "deflate",
},
{
// malformed entry ignored
given: "deflate, gzip;q=",
expected: codings{{"deflate", 1.0}},
expectPreferred: "deflate",
},
{
// malformed entry without encoding name is ignored
given: "deflate, ;q=1.0",
expected: codings{{"deflate", 1.0}},
expectPreferred: "deflate",
},
{
// strict parsing of qvalues does not allow any spaces
given: "deflate, gzip; q=1.0",
expected: codings{{"deflate", 1.0}},
expectPreferred: "deflate",
},
{
// strict parsing of qvalues does not allow any spaces
given: "deflate, gzip;q = 1.0",
expected: codings{{"deflate", 1.0}},
expectPreferred: "deflate",
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.given, func(t *testing.T) {
t.Parallel()
got := parseAcceptEncodings(tc.given)
if !reflect.DeepEqual(tc.expected, got) {
t.Fatalf("failed to parse %q:\ngot: %#v\nwant: %#v", tc.given, got, tc.expected)
}
gotPreferred := got.Preferred()
if !reflect.DeepEqual(tc.expectPreferred, gotPreferred) {
t.Fatalf("expected preferred coding %#v, got %#v", tc.expectPreferred, gotPreferred)
}
})
}
}
......@@ -58,6 +58,20 @@ func limitRequestSize(maxSize int64, h http.Handler) http.Handler {
})
}
func gzipHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// buf := &bytes.Buffer{}
// gzw := gzip.NewWriter(buf)
// gzw.Write(body)
// gzw.Close()
// gzBody := buf.Bytes()
// w.Header().Set("Content-Encoding", "gzip")
// writeJSON(w, gzBody, http.StatusOK)
})
}
// headResponseWriter implements http.ResponseWriter in order to discard the
// body of the response
type headResponseWriter struct {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment