diff options
author | nickajacks1 <128185314+nickajacks1@users.noreply.github.com> | 2024-01-02 00:43:40 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-02 09:43:40 +0100 |
commit | 868ee455d5f9b5ffebae03906d581eb360f5d835 (patch) | |
tree | d1aa9e56bfc7141ef1d9ccdd911ef03c269d26ef /header_test.go | |
parent | chore(deps): bump golang.org/x/crypto from 0.14.0 to 0.17.0 (#1678) (diff) | |
download | fasthttp-868ee455d5f9b5ffebae03906d581eb360f5d835.tar.gz fasthttp-868ee455d5f9b5ffebae03906d581eb360f5d835.tar.bz2 fasthttp-868ee455d5f9b5ffebae03906d581eb360f5d835.zip |
feat: add function to parse HTTP header parameters (#1685)
* feat: add function to parse HTTP header parameters
The implementation is based on RFC-9110 5.6.6.
* test: add fuzz for VisitHeaderParams
Diffstat (limited to 'header_test.go')
-rw-r--r-- | header_test.go | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/header_test.go b/header_test.go index 2893751..eaa9a50 100644 --- a/header_test.go +++ b/header_test.go @@ -1061,6 +1061,75 @@ func testRequestHeaderHasAcceptEncoding(t *testing.T, ae, v string, resultExpect } } +func TestVisitHeaderParams(t *testing.T) { + t.Parallel() + testVisitHeaderParams(t, "text/plain;charset=utf-8;q=0.39", [][2]string{{"charset", "utf-8"}, {"q", "0.39"}}) + testVisitHeaderParams(t, "text/plain; foo=bar ;", [][2]string{{"foo", "bar"}}) + testVisitHeaderParams(t, `text/plain; foo="bar"; `, [][2]string{{"foo", "bar"}}) + testVisitHeaderParams(t, `text/plain; foo="text/plain,text/html;charset=\"utf-8\""`, [][2]string{{"foo", `text/plain,text/html;charset=\"utf-8\"`}}) + testVisitHeaderParams(t, "text/plain foo=bar", [][2]string{}) + testVisitHeaderParams(t, "text/plain;", [][2]string{}) + testVisitHeaderParams(t, "text/plain; ", [][2]string{}) + testVisitHeaderParams(t, "text/plain; foo", [][2]string{}) + testVisitHeaderParams(t, "text/plain; foo=", [][2]string{}) + testVisitHeaderParams(t, "text/plain; =bar", [][2]string{}) + testVisitHeaderParams(t, "text/plain; foo = bar", [][2]string{}) + testVisitHeaderParams(t, `text/plain; foo="bar`, [][2]string{}) + testVisitHeaderParams(t, "text/plain;;foo=bar", [][2]string{}) + + parsed := make([][2]string, 0) + VisitHeaderParams([]byte(`text/plain; foo=bar; charset=utf-8`), func(key, value []byte) bool { + parsed = append(parsed, [2]string{string(key), string(value)}) + return !bytes.Equal(key, []byte("foo")) + }) + + if len(parsed) != 1 { + t.Fatalf("expected 1 HTTP parameter, parsed %v", len(parsed)) + } + + if parsed[0] != [2]string{"foo", "bar"} { + t.Fatalf("unexpected parameter %v=%v. Expecting foo=bar", parsed[0][0], parsed[0][1]) + } +} + +func testVisitHeaderParams(t *testing.T, header string, expectedParams [][2]string) { + parsed := make([][2]string, 0) + VisitHeaderParams([]byte(header), func(key, value []byte) bool { + parsed = append(parsed, [2]string{string(key), string(value)}) + return true + }) + + if len(parsed) != len(expectedParams) { + t.Fatalf("expected %v HTTP parameters, parsed %v", len(expectedParams), len(parsed)) + } + + for i := range expectedParams { + if expectedParams[i] != parsed[i] { + t.Fatalf("unexpected parameter %v=%v. Expecting %v=%v", parsed[i][0], parsed[i][1], expectedParams[i][0], expectedParams[i][1]) + } + } +} + +func FuzzVisitHeaderParams(f *testing.F) { + inputs := []string{ + `application/json; v=1; foo=bar; q=0.938; param=param; param="big fox"; q=0.43`, + `*/*`, + `\\`, + `text/plain; foo="\\\"\'\\''\'"`, + } + for _, input := range inputs { + f.Add([]byte(input)) + } + f.Fuzz(func(t *testing.T, header []byte) { + VisitHeaderParams(header, func(key, value []byte) bool { + if len(key) == 0 { + t.Errorf("Unexpected length zero parameter, failed input was: %s", header) + } + return true + }) + }) +} + func TestRequestMultipartFormBoundary(t *testing.T) { t.Parallel() |