Skip to content

Commit 2cd767f

Browse files
authored
Fix multiple websocket connection issues. (#58)
- 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 2cd767f

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

edge-http/src/lib.rs

Lines changed: 23 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,8 @@ impl ConnectionType {
499500
&& value.eq_ignore_ascii_case("Keep-Alive")
500501
{
501502
Some(Self::KeepAlive)
503+
} else if "Connection".eq_ignore_ascii_case(name) && value.eq_ignore_ascii_case("Upgrade") {
504+
Some(Self::Upgrade)
502505
} else {
503506
None
504507
}
@@ -535,6 +538,7 @@ impl ConnectionType {
535538
let connection = match self {
536539
Self::KeepAlive => "Keep-Alive",
537540
Self::Close => "Close",
541+
Self::Upgrade => "Upgrade",
538542
};
539543

540544
("Connection", connection.as_bytes())
@@ -546,6 +550,7 @@ impl Display for ConnectionType {
546550
match self {
547551
Self::KeepAlive => write!(f, "Keep-Alive"),
548552
Self::Close => write!(f, "Close"),
553+
Self::Upgrade => write!(f, "Upgrade"),
549554
}
550555
}
551556
}
@@ -619,6 +624,16 @@ impl BodyType {
619624
}
620625
} else if matches!(connection_type, ConnectionType::Close) {
621626
Ok(BodyType::Raw)
627+
} else if matches!(connection_type, ConnectionType::Upgrade) {
628+
if http11 {
629+
debug!("Unknown body type in response but the Connection is Upgrade. Assuming Content-Length=0.");
630+
Ok(BodyType::ContentLen(0))
631+
} else {
632+
warn!("Connection is set to Upgrade but the HTTP protocol version is not 1.1. This is not allowed.");
633+
Err(HeadersMismatchError::BodyTypeError(
634+
"Connection is set to Upgrade but the HTTP protocol version is not 1.1. This is not allowed.",
635+
))
636+
}
622637
} else if chunked_if_unspecified && http11 {
623638
// With HTTP1.1 we can safely upgrade the body to a chunked one
624639
Ok(BodyType::Chunked)
@@ -1183,6 +1198,14 @@ mod test {
11831198
BodyType::resolve(None, ConnectionType::Close, true, false, false).unwrap(),
11841199
BodyType::ContentLen(0)
11851200
);
1201+
assert_eq!(
1202+
BodyType::resolve(None, ConnectionType::Upgrade, false, true, false).unwrap(),
1203+
BodyType::ContentLen(0)
1204+
);
1205+
1206+
// Receiving a response with no body type after requesting a connection upgrade with
1207+
// HTTP1.0 is no allowed.
1208+
assert!(BodyType::resolve(None, ConnectionType::Upgrade, false, false, false).is_err());
11861209

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

0 commit comments

Comments
 (0)