Return rejection if WebSocket request couldn't be upgraded (#1135)

* Return rejection if `WebSocket` request couldn't be upgraded

* make rejection about connection upgrades

* changelog links
This commit is contained in:
David Pedersen
2022-07-15 11:28:59 +02:00
parent 27786a5fef
commit e2ff65fd7c
2 changed files with 63 additions and 8 deletions
+6 -1
View File
@@ -7,7 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# Unreleased
- None.
- **fixed:** If `WebSocketUpgrade` cannot upgrade the connection it will return a
`WebSocketUpgradeRejection::ConnectionNotUpgradable` rejection ([#1135])
- **changed:** `WebSocketUpgradeRejection` has a new variant `ConnectionNotUpgradable`
variant ([#1135])
[#1135]: https://github.com/tokio-rs/axum/pull/1135
# 0.5.12 (10. July, 2022)
+57 -7
View File
@@ -267,14 +267,15 @@ where
return Err(InvalidWebSocketVersionHeader.into());
}
let sec_websocket_key =
if let Some(key) = req.headers_mut().remove(header::SEC_WEBSOCKET_KEY) {
key
} else {
return Err(WebSocketKeyHeaderMissing.into());
};
let sec_websocket_key = req
.headers_mut()
.remove(header::SEC_WEBSOCKET_KEY)
.ok_or(WebSocketKeyHeaderMissing)?;
let on_upgrade = req.extensions_mut().remove::<OnUpgrade>().unwrap();
let on_upgrade = req
.extensions_mut()
.remove::<OnUpgrade>()
.ok_or(ConnectionNotUpgradable)?;
let sec_websocket_protocol = req.headers().get(header::SEC_WEBSOCKET_PROTOCOL).cloned();
@@ -564,6 +565,20 @@ pub mod rejection {
pub struct WebSocketKeyHeaderMissing;
}
define_rejection! {
#[status = UPGRADE_REQUIRED]
#[body = "WebSocket request couldn't be upgraded since no upgrade state was present"]
/// Rejection type for [`WebSocketUpgrade`](super::WebSocketUpgrade).
///
/// This rejection is returned if the connection cannot be upgraded for example if the
/// request is HTTP/1.0.
///
/// See [MDN] for more details about connection upgrades.
///
/// [MDN]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade
pub struct ConnectionNotUpgradable;
}
composite_rejection! {
/// Rejection used for [`WebSocketUpgrade`](super::WebSocketUpgrade).
///
@@ -575,6 +590,7 @@ pub mod rejection {
InvalidUpgradeHeader,
InvalidWebSocketVersionHeader,
WebSocketKeyHeaderMissing,
ConnectionNotUpgradable,
}
}
}
@@ -640,3 +656,37 @@ pub mod close_code {
/// action.
pub const AGAIN: u16 = 1013;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{body::Body, routing::get};
use http::{Request, Version};
use tower::ServiceExt;
#[tokio::test]
async fn rejects_http_1_0_requests() {
let svc = get(|ws: Result<WebSocketUpgrade, WebSocketUpgradeRejection>| {
let rejection = ws.unwrap_err();
assert!(matches!(
rejection,
WebSocketUpgradeRejection::ConnectionNotUpgradable(_)
));
std::future::ready(())
});
let req = Request::builder()
.version(Version::HTTP_10)
.method(Method::GET)
.header("upgrade", "websocket")
.header("connection", "Upgrade")
.header("sec-websocket-key", "6D69KGBOr4Re+Nj6zx9aQA==")
.header("sec-websocket-version", "13")
.body(Body::empty())
.unwrap();
let res = svc.oneshot(req).await.unwrap();
assert_eq!(res.status(), StatusCode::OK);
}
}