Skip to content

Commit

Permalink
don't require the presense of the Capsule protocol header
Browse files Browse the repository at this point in the history
The header is optional. We only need to verify the value if the header
is present.
  • Loading branch information
marten-seemann committed Nov 14, 2024
1 parent 7499833 commit 6c1840a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 33 deletions.
40 changes: 19 additions & 21 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,29 +71,27 @@ func ParseRequest(r *http.Request, template *uritemplate.Template) (*Request, er
Err: fmt.Errorf("host in :authority (%s) does not match template host (%s)", r.Host, u.Host),
}
}
// The capsule protocol header is optional, but if it's present,
// we need to validate its value.
capsuleHeaderValues, ok := r.Header[http3.CapsuleProtocolHeader]
if !ok {
return nil, &RequestParseError{
HTTPStatus: http.StatusBadRequest,
Err: fmt.Errorf("missing Capsule-Protocol header"),
}
}
item, err := httpsfv.UnmarshalItem(capsuleHeaderValues)
if err != nil {
return nil, &RequestParseError{
HTTPStatus: http.StatusBadRequest,
Err: fmt.Errorf("invalid capsule header value: %s", capsuleHeaderValues),
if ok {
item, err := httpsfv.UnmarshalItem(capsuleHeaderValues)
if err != nil {
return nil, &RequestParseError{
HTTPStatus: http.StatusBadRequest,
Err: fmt.Errorf("invalid capsule header value: %s", capsuleHeaderValues),
}
}
}
if v, ok := item.Value.(bool); !ok {
return nil, &RequestParseError{
HTTPStatus: http.StatusBadRequest,
Err: fmt.Errorf("incorrect capsule header value type: %s", reflect.TypeOf(item.Value)),
}
} else if !v {
return nil, &RequestParseError{
HTTPStatus: http.StatusBadRequest,
Err: fmt.Errorf("incorrect capsule header value: %t", item.Value),
if v, ok := item.Value.(bool); !ok {
return nil, &RequestParseError{
HTTPStatus: http.StatusBadRequest,
Err: fmt.Errorf("incorrect capsule header value type: %s", reflect.TypeOf(item.Value)),
}
} else if !v {
return nil, &RequestParseError{
HTTPStatus: http.StatusBadRequest,
Err: fmt.Errorf("incorrect capsule header value: %t", item.Value),
}
}
}

Expand Down
25 changes: 13 additions & 12 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
"testing"

"github.com/dunglas/httpsfv"
"github.com/stretchr/testify/require"
"github.com/quic-go/quic-go/http3"
"github.com/yosida95/uritemplate/v3"

"github.com/stretchr/testify/require"
)

func TestRequestParsing(t *testing.T) {
Expand All @@ -34,6 +36,13 @@ func TestRequestParsing(t *testing.T) {
require.Equal(t, r.Target, "[::1]:1234")
})

t.Run("valid request, without the Capsule-Protocol header", func(t *testing.T) {
req := newRequest("https://localhost:1234/masque?h=localhost&p=1337")
req.Header.Del(http3.CapsuleProtocolHeader)
_, err := ParseRequest(req, template)
require.NoError(t, err)
})

t.Run("wrong request method", func(t *testing.T) {
req := newRequest("https://localhost:1234/masque")
req.Method = http.MethodHead
Expand All @@ -57,25 +66,17 @@ func TestRequestParsing(t *testing.T) {
require.Equal(t, http.StatusBadRequest, err.(*RequestParseError).HTTPStatus)
})

t.Run("missing Capsule-Protocol header", func(t *testing.T) {
req := newRequest("https://localhost:1234/masque")
req.Header.Del("Capsule-Protocol")
_, err := ParseRequest(req, template)
require.EqualError(t, err, "missing Capsule-Protocol header")
require.Equal(t, http.StatusBadRequest, err.(*RequestParseError).HTTPStatus)
})

t.Run("invalid Capsule-Protocol header", func(t *testing.T) {
req := newRequest("https://localhost:1234/masque")
req.Header.Set("Capsule-Protocol", "🤡")
req.Header.Set(http3.CapsuleProtocolHeader, "🤡")
_, err := ParseRequest(req, template)
require.EqualError(t, err, "invalid capsule header value: [🤡]")
require.Equal(t, http.StatusBadRequest, err.(*RequestParseError).HTTPStatus)
})

t.Run("invalid Capsule-Protocol header value type", func(t *testing.T) {
req := newRequest("https://localhost:1234/masque")
req.Header.Set("Capsule-Protocol", "1")
req.Header.Set(http3.CapsuleProtocolHeader, "1")
_, err := ParseRequest(req, template)
require.EqualError(t, err, "incorrect capsule header value type: int64")
require.Equal(t, http.StatusBadRequest, err.(*RequestParseError).HTTPStatus)
Expand All @@ -85,7 +86,7 @@ func TestRequestParsing(t *testing.T) {
req := newRequest("https://localhost:1234/masque")
v, err := httpsfv.Marshal(httpsfv.NewItem(false))
require.NoError(t, err)
req.Header.Set("Capsule-Protocol", v)
req.Header.Set(http3.CapsuleProtocolHeader, v)
_, err = ParseRequest(req, template)
require.EqualError(t, err, "incorrect capsule header value: false")
require.Equal(t, http.StatusBadRequest, err.(*RequestParseError).HTTPStatus)
Expand Down

0 comments on commit 6c1840a

Please sign in to comment.