mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-05 05:07:36 +03:00
http3: enforce ordering requirement between pseudo and regular headers (#3968)
* http3: enforce ordering requirement between pseudo and regular headers * simplify logic
This commit is contained in:
parent
4378283f95
commit
514df55288
2 changed files with 24 additions and 3 deletions
|
@ -17,6 +17,7 @@ func requestFromHeaders(headers []qpack.HeaderField) (*http.Request, error) {
|
||||||
var path, authority, method, protocol, scheme, contentLengthStr string
|
var path, authority, method, protocol, scheme, contentLengthStr string
|
||||||
|
|
||||||
httpHeaders := http.Header{}
|
httpHeaders := http.Header{}
|
||||||
|
var readFirstRegularHeader bool
|
||||||
for _, h := range headers {
|
for _, h := range headers {
|
||||||
// field names need to be lowercase, see section 4.2 of RFC 9114
|
// field names need to be lowercase, see section 4.2 of RFC 9114
|
||||||
if strings.ToLower(h.Name) != h.Name {
|
if strings.ToLower(h.Name) != h.Name {
|
||||||
|
@ -25,6 +26,18 @@ func requestFromHeaders(headers []qpack.HeaderField) (*http.Request, error) {
|
||||||
if !httpguts.ValidHeaderFieldValue(h.Value) {
|
if !httpguts.ValidHeaderFieldValue(h.Value) {
|
||||||
return nil, fmt.Errorf("invalid header field value for %s: %q", h.Name, h.Value)
|
return nil, fmt.Errorf("invalid header field value for %s: %q", h.Name, h.Value)
|
||||||
}
|
}
|
||||||
|
if h.IsPseudo() {
|
||||||
|
if readFirstRegularHeader {
|
||||||
|
// all pseudo headers must appear before regular header fields, see section 4.3 of RFC 9114
|
||||||
|
return nil, fmt.Errorf("received pseudo header %s after a regular header field", h.Name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !httpguts.ValidHeaderFieldName(h.Name) {
|
||||||
|
return nil, fmt.Errorf("invalid header field name: %q", h.Name)
|
||||||
|
}
|
||||||
|
readFirstRegularHeader = true
|
||||||
|
}
|
||||||
|
|
||||||
switch h.Name {
|
switch h.Name {
|
||||||
case ":path":
|
case ":path":
|
||||||
path = h.Value
|
path = h.Value
|
||||||
|
@ -40,9 +53,6 @@ func requestFromHeaders(headers []qpack.HeaderField) (*http.Request, error) {
|
||||||
contentLengthStr = h.Value
|
contentLengthStr = h.Value
|
||||||
default:
|
default:
|
||||||
if !h.IsPseudo() {
|
if !h.IsPseudo() {
|
||||||
if !httpguts.ValidHeaderFieldName(h.Name) {
|
|
||||||
return nil, fmt.Errorf("invalid header field name: %q", h.Name)
|
|
||||||
}
|
|
||||||
httpHeaders.Add(h.Name, h.Value)
|
httpHeaders.Add(h.Name, h.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,17 @@ var _ = Describe("Request", func() {
|
||||||
Expect(err).To(MatchError(`invalid header field value for content: "\n"`))
|
Expect(err).To(MatchError(`invalid header field value for content: "\n"`))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("rejects pseudo header fields after regular header fields", func() {
|
||||||
|
headers := []qpack.HeaderField{
|
||||||
|
{Name: ":path", Value: "/foo"},
|
||||||
|
{Name: "content-length", Value: "42"},
|
||||||
|
{Name: ":authority", Value: "quic.clemente.io"},
|
||||||
|
{Name: ":method", Value: "GET"},
|
||||||
|
}
|
||||||
|
_, err := requestFromHeaders(headers)
|
||||||
|
Expect(err).To(MatchError("received pseudo header :authority after a regular header field"))
|
||||||
|
})
|
||||||
|
|
||||||
It("rejects negative Content-Length values", func() {
|
It("rejects negative Content-Length values", func() {
|
||||||
headers := []qpack.HeaderField{
|
headers := []qpack.HeaderField{
|
||||||
{Name: ":path", Value: "/foo"},
|
{Name: ":path", Value: "/foo"},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue