Skip to content

Commit

Permalink
Fix request pseudo-header construction for CONNECT & OPTION methods
Browse files Browse the repository at this point in the history
CONNECT & OPTIONS request has special requirements regarding :path & :scheme pseudo-header which were not met.

Construction of pseudo-header was fixed to not include :path & :scheme fields for CONNECT method.
Empty :path field for OPTIONS requests now translates to '*' value sent in :path field.

CONNECT request changes were tested against server based on hyper 1.2.
  • Loading branch information
mstyura committed Apr 23, 2024
1 parent e2168de commit 2c029e6
Showing 1 changed file with 28 additions and 16 deletions.
44 changes: 28 additions & 16 deletions src/frame/headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,32 +554,44 @@ impl Pseudo {
pub fn request(method: Method, uri: Uri, protocol: Option<Protocol>) -> Self {
let parts = uri::Parts::from(uri);

let mut path = parts
.path_and_query
.map(|v| BytesStr::from(v.as_str()))
.unwrap_or(BytesStr::from_static(""));

match method {
Method::OPTIONS | Method::CONNECT => {}
_ if path.is_empty() => {
path = BytesStr::from_static("/");
}
_ => {}
}
let (scheme, path) = if method == Method::CONNECT {
// CONNECT requests MUST NOT include :scheme & :path pseudo-header fields
// See: https://datatracker.ietf.org/doc/html/rfc9113#section-8.5
(None, None)
} else {
let path = parts
.path_and_query
.map(|v| BytesStr::from(v.as_str()))
.unwrap_or(BytesStr::from_static(""));

let path = if !path.is_empty() {
path
} else {
if method == Method::OPTIONS {
// An OPTIONS request for an "http" or "https" URI that does not include a path component;
// these MUST include a ":path" pseudo-header field with a value of '*' (see Section 7.1 of [HTTP]).
// See: https://datatracker.ietf.org/doc/html/rfc9113#section-8.3.1
// TODO: Validate URI is "http" or "https".
BytesStr::from_static("*")
} else {
BytesStr::from_static("/")
}
};

(parts.scheme, Some(path).filter(|p| !p.is_empty()))
};

let mut pseudo = Pseudo {
method: Some(method),
scheme: None,
authority: None,
path: Some(path).filter(|p| !p.is_empty()),
path,
protocol,
status: None,
};

// If the URI includes a scheme component, add it to the pseudo headers
//
// TODO: Scheme must be set...
if let Some(scheme) = parts.scheme {
if let Some(scheme) = scheme {
pseudo.set_scheme(scheme);
}

Expand Down

0 comments on commit 2c029e6

Please sign in to comment.