Skip to content

Commit

Permalink
httputil/ParseMultiValuesHeader: return empty slice if input is empty…
Browse files Browse the repository at this point in the history
… after trimming

+ minor optimization
  • Loading branch information
System-Glitch committed Jun 20, 2024
1 parent 6b679d3 commit 437c0bd
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 5 deletions.
1 change: 1 addition & 0 deletions lang/lang_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ func (suite *LangTestSuite) TestDetectLanguage() {
suite.Equal(l.languages["en-US"], l.DetectLanguage("en, fr-FR;q=0.9"))
suite.Equal(l.languages["en-US"], l.DetectLanguage("*"))
suite.Equal(l.languages["en-US"], l.DetectLanguage("notalang"))
suite.Equal(l.languages["en-US"], l.DetectLanguage(""))
}

func (suite *LangTestSuite) TestLanguagesGet() {
Expand Down
34 changes: 34 additions & 0 deletions log/log_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package log

import (
"io"
"net/http"
"net/http/httptest"
"testing"

"goyave.dev/goyave/v5"
"goyave.dev/goyave/v5/config"
"goyave.dev/goyave/v5/slog"
)

func BenchmarkServeHTTPWithLogs(b *testing.B) {
cfg := config.LoadDefault()
cfg.Set("app.debug", false)
logger := slog.New(slog.NewHandler(false, io.Discard))
s, _ := goyave.New(goyave.Options{Config: cfg, Logger: logger})

s.RegisterRoutes(func(_ *goyave.Server, r *goyave.Router) {
r.GlobalMiddleware(CombinedLogMiddleware())
r.Get("/user/{id}", func(r *goyave.Response, req *goyave.Request) {
r.String(http.StatusOK, req.RouteParams["id"])
})
})

req := httptest.NewRequest(http.MethodGet, "/user/1", nil)

b.ReportAllocs()
b.ResetTimer()
for n := 0; n < b.N; n++ {
s.Router().ServeHTTP(httptest.NewRecorder(), req)
}
}
3 changes: 3 additions & 0 deletions middleware/compress/compress.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ func (m *Middleware) getEncoder(response *goyave.Response, request *goyave.Reque
return nil
}
acceptedEncodings := httputil.ParseMultiValuesHeader(request.Header().Get("Accept-Encoding"))
if len(acceptedEncodings) == 0 {
return nil
}
groupedByPriority := lo.PartitionBy(acceptedEncodings, func(h httputil.HeaderValue) float64 {
return h.Priority
})
Expand Down
5 changes: 5 additions & 0 deletions middleware/compress/compress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,11 @@ func TestEncoderPriority(t *testing.T) {
acceptEncoding: "gzip;q=0.8, *;q=1.0",
want: br,
},
{
encoders: []Encoder{br, zstd, gzip},
acceptEncoding: "",
want: nil,
},
}

for _, c := range cases {
Expand Down
25 changes: 20 additions & 5 deletions util/httputil/httputil.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ var qualityValueRegex = regexp.MustCompile(`^q=([01]\.[0-9]{1,3})$`)
// quality values into account. The result is a slice of values sorted
// according to the order of priority.
//
// The input is trimmed. If the input is empty, returns an empty slice.
//
// See: https://developer.mozilla.org/en-US/docs/Glossary/Quality_values
//
// For the following header:
Expand All @@ -30,10 +32,19 @@ var qualityValueRegex = regexp.MustCompile(`^q=([01]\.[0-9]{1,3})$`)
//
// [{text/html 1} {*/* 0.7} {text/* 0.5}]
func ParseMultiValuesHeader(header string) []HeaderValue {
split := strings.Split(header, ",")
values := make([]HeaderValue, 0, len(split))
count := strings.Count(header, ",")
values := make([]HeaderValue, 0, count+1)

for _, v := range split {
h := strings.TrimSpace(header)
if h == "" {
return values
}
for {
comma := strings.Index(h, ",")
if comma == -1 {
comma = len(h)
}
v := h[:comma]
val := HeaderValue{}
if i := strings.Index(v, ";"); i != -1 {
// Parse priority
Expand All @@ -49,13 +60,17 @@ func ParseMultiValuesHeader(header string) []HeaderValue {
// Priority set to 0 if the quality value cannot be parsed
val.Priority = priority

val.Value = strings.Trim(v[:i], " ")
val.Value = strings.TrimSpace(v[:i])
} else {
val.Value = strings.Trim(v, " ")
val.Value = strings.TrimSpace(v)
val.Priority = 1
}

values = append(values, val)
if comma == len(h) {
break
}
h = h[comma+1:]
}

sort.Sort(byPriority(values))
Expand Down
8 changes: 8 additions & 0 deletions util/httputil/httputil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,12 @@ func TestParseMultiValuesHeader(t *testing.T) {
expected = []HeaderValue{{Value: "fr", Priority: 0.3}}
result = ParseMultiValuesHeader("fr;q=0.3")
assert.Equal(t, expected, result)

expected = []HeaderValue{}
result = ParseMultiValuesHeader("")
assert.Equal(t, expected, result)

expected = []HeaderValue{}
result = ParseMultiValuesHeader(" ")
assert.Equal(t, expected, result)
}

0 comments on commit 437c0bd

Please sign in to comment.