first pass of merging in warp (doesn't build)

This commit is contained in:
Ryan Ward
2026-07-01 16:08:58 -05:00
parent 2f64909469
commit 4770ac06b5
3662 changed files with 414574 additions and 89772 deletions
+61 -3
View File
@@ -14,6 +14,8 @@ mod sink_map_err;
use anyhow::anyhow;
#[cfg(not(target_family = "wasm"))]
pub use async_tungstenite::tungstenite;
#[cfg(not(target_family = "wasm"))]
pub use async_tungstenite::tungstenite::client::IntoClientRequest;
#[cfg(not(target_family = "wasm"))]
use async_tungstenite::tungstenite::http::HeaderValue;
@@ -22,9 +24,6 @@ use futures_util::{future, SinkExt, TryStreamExt};
use itertools::Itertools;
use thiserror::Error;
#[cfg(not(target_family = "wasm"))]
pub use async_tungstenite::tungstenite;
use crate::sink_map_err::map_err;
// Unfortunately, `anyhow::Error` does not implement `std::error::Error`, which is required by the
@@ -128,11 +127,70 @@ impl WebSocket {
Ok(Self(socket))
}
/// Connect to `url`, attaching the provided extra request headers to the
/// HTTP upgrade handshake.
///
/// Custom handshake headers are not supported on wasm websockets, so
/// `headers` is ignored there.
pub async fn connect_with_headers<'a>(
url: &str,
protocols: impl IntoIterator<Item = &'a str>,
headers: Vec<(&'a str, String)>,
) -> anyhow::Result<Self> {
cfg_if::cfg_if! {
if #[cfg(not(target_family = "wasm"))] {
// `connect` accepts any `IntoClientRequest` and handles
// protocol negotiation + wrapping, so build the enriched
// request and hand it off.
let request = build_request_with_headers(url, headers)?;
Self::connect(request, protocols).await
} else {
let _ = headers;
Self::connect(url, protocols).await
}
}
}
pub async fn into_graphql_client_builder(self) -> graphql_ws_client::ClientBuilder {
self.0.into_graphql_client_builder().await
}
}
/// If `err` originated from a websocket handshake that received a non-101 HTTP
/// response (e.g. an auth or proxy challenge), returns that response so callers
/// can inspect its status and headers (for example, to detect a GCP IAP
/// challenge). Native-only: wasm websockets do not surface the handshake
/// response on error.
#[cfg(not(target_family = "wasm"))]
pub fn connect_error_http_response(
err: &anyhow::Error,
) -> Option<&tungstenite::http::Response<Option<Vec<u8>>>> {
err.chain()
.find_map(|cause| match cause.downcast_ref::<tungstenite::Error>() {
Some(tungstenite::Error::Http(response)) => Some(response),
_ => None,
})
}
/// Builds a native websocket client request for `url`, attaching the provided
/// extra request headers to the handshake.
#[cfg(not(target_family = "wasm"))]
fn build_request_with_headers(
url: &str,
headers: Vec<(&str, String)>,
) -> anyhow::Result<tungstenite::handshake::client::Request> {
let mut request = url.into_client_request()?;
let request_headers = request.headers_mut();
for (name, value) in headers {
let header_name = http::HeaderName::from_bytes(name.as_bytes())
.map_err(|err| anyhow!("invalid websocket header name `{name}`: {err}"))?;
let header_value = http::HeaderValue::from_str(&value)
.map_err(|err| anyhow!("invalid websocket header value: {err}"))?;
request_headers.insert(header_name, header_value);
}
Ok(request)
}
/// Trait that defines a [`Sink`] returned by the websocket.
pub trait Sink: futures::Sink<Message, Error = Error> + Send + Unpin + 'static {}
+4 -6
View File
@@ -2,13 +2,11 @@
use std::sync::Arc;
use async_tungstenite::{
tokio::{
client_async_tls_with_connector_and_config, connect_async_with_tls_connector, ClientStream,
},
tungstenite::client::IntoClientRequest,
WebSocketStream,
use async_tungstenite::tokio::{
client_async_tls_with_connector_and_config, connect_async_with_tls_connector, ClientStream,
};
use async_tungstenite::tungstenite::client::IntoClientRequest;
use async_tungstenite::WebSocketStream;
use futures::{Sink, Stream};
use futures_util::StreamExt as _;
use rustls_platform_verifier::ConfigVerifierExt;
+2 -1
View File
@@ -10,7 +10,8 @@ use std::env;
use std::time::Duration;
use anyhow::{bail, Context};
use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _};
use base64::engine::general_purpose::STANDARD as BASE64;
use base64::Engine as _;
use http_body_util::Empty;
use hyper::body::Bytes;
use hyper_util::rt::TokioIo;
+3 -2
View File
@@ -1,8 +1,9 @@
use core::pin::Pin;
use std::task::{Context, Poll};
use futures::{Sink, Stream};
use futures_util::stream::FusedStream;
use pin_project::pin_project;
use std::task::{Context, Poll};
/// Maps the error returned by the [`Sink`] using the provided `err` function.
pub fn map_err<S, I, E>(sink: S, err: impl FnMut(S::Error) -> E) -> impl Sink<I, Error = E>
@@ -13,7 +14,7 @@ where
}
/// Helper struct to map the [`Err`] of an underlying [`Sink`].
/// This is a fork of the the `SinkMapErr` defined within `futures-util`
/// This is a fork of the `SinkMapErr` defined within `futures-util`
/// (https://docs.rs/futures/latest/futures/sink/struct.SinkMapErr.html) except that it does _not_
/// panic if the caller tries to write to the sink after a previous attempt to write returned an
/// error. See <https://github.com/rust-lang/futures-rs/issues/2108> for more details about the
+2 -1
View File
@@ -1,8 +1,9 @@
use super::*;
use futures_test_sink::SinkMock;
use futures_util::SinkExt;
use thiserror::Error;
use super::*;
#[derive(Error, PartialEq, Debug, Copy, Clone)]
#[error("Unable to send to sink")]
struct UnmappedError(u8);
+1 -2
View File
@@ -1,8 +1,7 @@
use futures::{Sink, Stream, StreamExt};
use itertools::Itertools;
use ws_stream_wasm::{WsErr, WsMessage, WsMeta};
pub use ws_stream_wasm::WsMessage as Message;
use ws_stream_wasm::{WsErr, WsMessage, WsMeta};
use crate::WebsocketMessage;