Skip to content

Commit e53235c

Browse files
committed
Fix multiple websocket connection issues.
- The websocket client sends two Connection headers: HTTP/1.1 GET / Host: 127.0.0.1 Origin: foo.com Content-Length: 0 Connection: Upgrade Upgrade: websocket Sec-WebSocket-Version: 13 Sec-WebSocket-Key: h57ZiKx+KAwmKbB+mxR8Ag== Connection: Keep-Alive The last "Connection: Keep-Alive" is added because the ConnectionType enum does not have an "Upgrade" variant. Adding the variant prevents this issue. - If the websocket client does not receive a "Content-Length: 0" header in the server's response, an error is returned stating "Unknown body type in a response with a Keep-Alive connection. This is not allowed." This occurs with the example client using the "websockets.chilkat.io/" service. This is corrected by assuming a "BodyType::ContentLen(0)" for the response when no other BodyType is provided and the "Connection: Upgrade" header is present.
1 parent b429fca commit e53235c

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

edge-http/src/lib.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ impl<const N: usize> Default for Headers<'_, N> {
444444
pub enum ConnectionType {
445445
KeepAlive,
446446
Close,
447+
Upgrade,
447448
}
448449

449450
impl ConnectionType {
@@ -499,6 +500,10 @@ impl ConnectionType {
499500
&& value.eq_ignore_ascii_case("Keep-Alive")
500501
{
501502
Some(Self::KeepAlive)
503+
} else if "Connection".eq_ignore_ascii_case(name)
504+
&& value.eq_ignore_ascii_case("Upgrade")
505+
{
506+
Some(Self::Upgrade)
502507
} else {
503508
None
504509
}
@@ -535,6 +540,7 @@ impl ConnectionType {
535540
let connection = match self {
536541
Self::KeepAlive => "Keep-Alive",
537542
Self::Close => "Close",
543+
Self::Upgrade => "Upgrade",
538544
};
539545

540546
("Connection", connection.as_bytes())
@@ -546,6 +552,7 @@ impl Display for ConnectionType {
546552
match self {
547553
Self::KeepAlive => write!(f, "Keep-Alive"),
548554
Self::Close => write!(f, "Close"),
555+
Self::Upgrade => write!(f, "Upgrade"),
549556
}
550557
}
551558
}
@@ -619,6 +626,16 @@ impl BodyType {
619626
}
620627
} else if matches!(connection_type, ConnectionType::Close) {
621628
Ok(BodyType::Raw)
629+
} else if matches!(connection_type, ConnectionType::Upgrade) {
630+
if http11 {
631+
debug!("Unknown body type in response but the Connection is Upgrade. Assuming Content-Length=0.");
632+
Ok(BodyType::ContentLen(0))
633+
} else {
634+
warn!("Connection is set to Upgrade but the HTTP protocol version is not 1.1. This is not allowed.");
635+
Err(HeadersMismatchError::BodyTypeError(
636+
"Connection is set to Upgrade but the HTTP protocol version is not 1.1. This is not allowed.",
637+
))
638+
}
622639
} else if chunked_if_unspecified && http11 {
623640
// With HTTP1.1 we can safely upgrade the body to a chunked one
624641
Ok(BodyType::Chunked)
@@ -1183,6 +1200,21 @@ mod test {
11831200
BodyType::resolve(None, ConnectionType::Close, true, false, false).unwrap(),
11841201
BodyType::ContentLen(0)
11851202
);
1203+
assert_eq!(
1204+
BodyType::resolve(None, ConnectionType::Upgrade, false, true, false).unwrap(),
1205+
BodyType::ContentLen(0)
1206+
);
1207+
1208+
// Receiving a response with no body type after requesting a connection upgrade with
1209+
// HTTP1.0 is no allowed.
1210+
assert!(BodyType::resolve(
1211+
None,
1212+
ConnectionType::Upgrade,
1213+
false,
1214+
false,
1215+
false
1216+
)
1217+
.is_err());
11861218

11871219
// Request or response with a chunked body type is invalid for HTTP1.0
11881220
assert!(BodyType::resolve(

0 commit comments

Comments
 (0)