Skip to content

Commit 7a7f5fb

Browse files
fix: replace unwraps with errors in fullstack WebSockets (#5248)
* fix: replace unwraps with errors in fullstack WebSockets * refactor: pull the conversions to fullstack `RequestError` up from the core crate * no breaking changes --------- Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
1 parent 4070d0c commit 7a7f5fb

File tree

1 file changed

+104
-6
lines changed

1 file changed

+104
-6
lines changed

‎packages/fullstack/src/payloads/websocket.rs‎

Lines changed: 104 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ impl IntoRequest<UpgradingWebsocket> for WebSocketOptions {
607607
.map(String::as_str)
608608
.collect::<Vec<_>>(),
609609
)
610-
.unwrap();
610+
.map_err(|error| RequestError::Connect(error.to_string()))?;
611611

612612
return Ok(UpgradingWebsocket {
613613
protocol: Some(socket.protocol()),
@@ -619,14 +619,11 @@ impl IntoRequest<UpgradingWebsocket> for WebSocketOptions {
619619

620620
#[cfg(not(target_arch = "wasm32"))]
621621
{
622-
let response = native::send_request(request, &self.protocols)
623-
.await
624-
.unwrap();
622+
let response = native::send_request(request, &self.protocols).await?;
625623

626624
let (inner, protocol) = response
627625
.into_stream_and_protocol(self.protocols, None)
628-
.await
629-
.unwrap();
626+
.await?;
630627

631628
return Ok(UpgradingWebsocket {
632629
protocol,
@@ -1139,6 +1136,7 @@ mod native {
11391136
use crate::ClientRequest;
11401137

11411138
use super::{CloseCode, Message, WebsocketError};
1139+
use dioxus_fullstack_core::RequestError;
11421140
use reqwest::{
11431141
header::{HeaderName, HeaderValue},
11441142
Response, StatusCode, Version,
@@ -1466,4 +1464,104 @@ mod native {
14661464
u16::from(value).into()
14671465
}
14681466
}
1467+
1468+
impl From<HandshakeError> for RequestError {
1469+
fn from(value: HandshakeError) -> Self {
1470+
let string = value.to_string();
1471+
match value {
1472+
HandshakeError::UnexpectedStatusCode(status) => {
1473+
Self::Status(string, status.as_u16())
1474+
}
1475+
HandshakeError::UnsupportedHttpVersion(_)
1476+
| HandshakeError::MissingHeader { .. }
1477+
| HandshakeError::UnexpectedHeaderValue { .. }
1478+
| HandshakeError::ExpectedAProtocol
1479+
| HandshakeError::UnexpectedProtocol { .. }
1480+
| HandshakeError::ServerRespondedWithDifferentVersion => Self::Connect(string),
1481+
}
1482+
}
1483+
}
1484+
1485+
trait IntoRequestError {
1486+
fn into_request_error(self) -> RequestError;
1487+
}
1488+
1489+
impl IntoRequestError for reqwest::Error {
1490+
fn into_request_error(self) -> RequestError {
1491+
const DEFAULT_STATUS_CODE: u16 = 0;
1492+
let string = self.to_string();
1493+
if self.is_builder() {
1494+
RequestError::Builder(string)
1495+
} else if self.is_redirect() {
1496+
RequestError::Redirect(string)
1497+
} else if self.is_status() {
1498+
RequestError::Status(
1499+
string,
1500+
self.status()
1501+
.as_ref()
1502+
.map(StatusCode::as_u16)
1503+
.unwrap_or(DEFAULT_STATUS_CODE),
1504+
)
1505+
} else if self.is_body() {
1506+
RequestError::Body(string)
1507+
} else if self.is_decode() {
1508+
RequestError::Decode(string)
1509+
} else if self.is_upgrade() {
1510+
RequestError::Connect(string)
1511+
} else {
1512+
RequestError::Request(string)
1513+
}
1514+
}
1515+
}
1516+
1517+
impl IntoRequestError for tungstenite::Error {
1518+
fn into_request_error(self) -> RequestError {
1519+
match self {
1520+
tungstenite::Error::ConnectionClosed => {
1521+
RequestError::Connect("websocket connection closed".to_owned())
1522+
}
1523+
tungstenite::Error::AlreadyClosed => {
1524+
RequestError::Connect("websocket already closed".to_owned())
1525+
}
1526+
tungstenite::Error::Io(error) => RequestError::Connect(error.to_string()),
1527+
tungstenite::Error::Tls(error) => RequestError::Connect(error.to_string()),
1528+
tungstenite::Error::Capacity(error) => RequestError::Body(error.to_string()),
1529+
tungstenite::Error::Protocol(error) => RequestError::Request(error.to_string()),
1530+
tungstenite::Error::WriteBufferFull(message) => {
1531+
RequestError::Body(message.to_string())
1532+
}
1533+
tungstenite::Error::Utf8(error) => RequestError::Decode(error),
1534+
tungstenite::Error::AttackAttempt => {
1535+
RequestError::Request("Tungstenite attack attempt detected".to_owned())
1536+
}
1537+
tungstenite::Error::Url(error) => RequestError::Builder(error.to_string()),
1538+
tungstenite::Error::Http(response) => {
1539+
let status_code = response.status();
1540+
RequestError::Status(format!("HTTP error: {status_code}"), status_code.as_u16())
1541+
}
1542+
tungstenite::Error::HttpFormat(error) => RequestError::Builder(error.to_string()),
1543+
}
1544+
}
1545+
}
1546+
1547+
impl From<WebsocketError> for RequestError {
1548+
fn from(value: WebsocketError) -> Self {
1549+
match value {
1550+
WebsocketError::ConnectionClosed { code, description } => {
1551+
Self::Connect(format!("connection closed ({code}): {description}"))
1552+
}
1553+
WebsocketError::AlreadyClosed => Self::Connect(value.to_string()),
1554+
WebsocketError::Capacity => Self::Body(value.to_string()),
1555+
WebsocketError::Unexpected => Self::Request(value.to_string()),
1556+
WebsocketError::Uninitialized => Self::Builder(value.to_string()),
1557+
WebsocketError::Handshake(error) => error.into(),
1558+
WebsocketError::Reqwest(error) => error.into_request_error(),
1559+
WebsocketError::Tungstenite(error) => error.into_request_error(),
1560+
WebsocketError::Serialization(error) => Self::Serialization(error.to_string()),
1561+
WebsocketError::Deserialization(error) => Self::Decode(error.to_string()),
1562+
WebsocketError::Json(error) => Self::Decode(error.to_string()),
1563+
WebsocketError::Cbor(error) => Self::Decode(error.to_string()),
1564+
}
1565+
}
1566+
}
14691567
}

0 commit comments

Comments
 (0)