Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build(http, gateway, lavalink): Update to rustls 0.22, hyper 1.0, tokio-websockets 0.5 #2302

Merged
merged 3 commits into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ anyhow = { default-features = false, features = ["std"], version = "1" }
ed25519-dalek = "2"
futures-util = { default-features = false, version = "0.3" }
hex = "0.4"
hyper = { features = ["client", "server", "http2", "runtime"], version = "0.14" }
http-body-util = "0.1"
hyper = { features = ["server"], version = "1" }
hyper-util = { features = ["http1", "client-legacy"], version = "0.1" }
log = { default-features = false, version = "0.4" }
once_cell = "1.4"
serde = { version = "1", features = ["derive"] }
Expand Down
13 changes: 10 additions & 3 deletions examples/gateway-queue-http.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use hyper::client::{Client, HttpConnector};
use http_body_util::Empty;
use hyper::body::Bytes;
use hyper_util::{
client::legacy::{connect::HttpConnector, Client},
rt::TokioExecutor,
};
use std::env;
use tokio::sync::oneshot;
use twilight_gateway::{queue::Queue, ConfigBuilder, Intents, Shard, ShardId};

#[derive(Debug)]
struct HttpQueue(Client<HttpConnector>);
struct HttpQueue(Client<HttpConnector, Empty<Bytes>>);

impl Queue for HttpQueue {
fn enqueue(&self, id: u32) -> oneshot::Receiver<()> {
Expand Down Expand Up @@ -36,7 +41,9 @@ async fn main() -> anyhow::Result<()> {
let intents = Intents::GUILDS | Intents::GUILD_VOICE_STATES;

let config = ConfigBuilder::new(token, intents)
.queue(HttpQueue(Client::new()))
.queue(HttpQueue(
Client::builder(TokioExecutor::new()).build_http(),
))
.build();

let mut shard = Shard::with_config(ShardId::ONE, config);
Expand Down
16 changes: 9 additions & 7 deletions examples/lavalink-basic-bot.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use hyper::{
client::{Client as HyperClient, HttpConnector},
Body, Request,
use http_body_util::{BodyExt, Full};
use hyper::{body::Bytes, Request};
use hyper_util::{
client::legacy::{connect::HttpConnector, Client as HyperClient},
rt::TokioExecutor,
};
use std::{env, future::Future, net::SocketAddr, str::FromStr, sync::Arc};
use twilight_gateway::{Event, Intents, MessageSender, Shard, ShardId};
Expand All @@ -22,7 +24,7 @@ type State = Arc<StateRef>;
struct StateRef {
http: HttpClient,
lavalink: Lavalink,
hyper: HyperClient<HttpConnector>,
hyper: HyperClient<HttpConnector, Full<Bytes>>,
sender: MessageSender,
standby: Standby,
}
Expand Down Expand Up @@ -62,7 +64,7 @@ async fn main() -> anyhow::Result<()> {
Arc::new(StateRef {
http,
lavalink,
hyper: HyperClient::new(),
hyper: HyperClient::builder(TokioExecutor::new()).build_http(),
sender,
standby: Standby::new(),
}),
Expand Down Expand Up @@ -191,9 +193,9 @@ async fn play(msg: Message, state: State) -> anyhow::Result<()> {
&player.node().config().authorization,
)?
.into_parts();
let req = Request::from_parts(parts, Body::from(body));
let req = Request::from_parts(parts, Full::from(body));
let res = state.hyper.request(req).await?;
let response_bytes = hyper::body::to_bytes(res.into_body()).await?;
let response_bytes = res.collect().await?.to_bytes();

let loaded = serde_json::from_slice::<LoadedTracks>(&response_bytes)?;

Expand Down
63 changes: 37 additions & 26 deletions examples/model-webhook-slash.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
use ed25519_dalek::{Verifier, VerifyingKey, PUBLIC_KEY_LENGTH};
use hex::FromHex;
use http_body_util::{BodyExt, Full};
use hyper::{
body::{Bytes, Incoming},
header::CONTENT_TYPE,
http::StatusCode,
service::{make_service_fn, service_fn},
Body, Method, Request, Response, Server,
server::conn::http1,
service::service_fn,
Method, Request, Response,
};
use hyper_util::rt::TokioIo;
use once_cell::sync::Lazy;
use std::future::Future;
use std::{future::Future, net::SocketAddr};
use tokio::net::TcpListener;
use twilight_model::{
application::interaction::{
application_command::CommandData, Interaction, InteractionData, InteractionType,
Expand All @@ -26,17 +31,17 @@ static PUB_KEY: Lazy<VerifyingKey> = Lazy::new(|| {
/// Responses are made by giving a function that takes a Interaction and returns
/// a InteractionResponse or a error.
async fn interaction_handler<F>(
req: Request<Body>,
req: Request<Incoming>,
f: impl Fn(Box<CommandData>) -> F,
) -> anyhow::Result<Response<Body>>
) -> anyhow::Result<Response<Full<Bytes>>>
where
F: Future<Output = anyhow::Result<InteractionResponse>>,
{
// Check that the method used is a POST, all other methods are not allowed.
if req.method() != Method::POST {
return Ok(Response::builder()
.status(StatusCode::METHOD_NOT_ALLOWED)
.body(Body::empty())?);
.body(Full::default())?);
}

// Check if the path the request is sent to is the root of the domain.
Expand All @@ -46,7 +51,7 @@ where
if req.uri().path() != "/" {
return Ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::empty())?);
.body(Full::default())?);
}

// Extract the timestamp header for use later to check the signature.
Expand All @@ -55,7 +60,7 @@ where
} else {
return Ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::empty())?);
.body(Full::default())?);
};

// Extract the signature to check against.
Expand All @@ -68,12 +73,12 @@ where
} else {
return Ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::empty())?);
.body(Full::default())?);
};

// Fetch the whole body of the request as that is needed to check the
// signature against.
let whole_body = hyper::body::to_bytes(req).await?;
let whole_body = req.collect().await?.to_bytes();

// Check if the signature matches and else return a error response.
if PUB_KEY
Expand All @@ -85,7 +90,7 @@ where
{
return Ok(Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body(Body::empty())?);
.body(Full::default())?);
}

// Deserialize the body into a interaction.
Expand Down Expand Up @@ -127,7 +132,7 @@ where
// Unhandled interaction types.
_ => Ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::empty())?),
.body(Full::default())?),
}
}

Expand Down Expand Up @@ -169,18 +174,24 @@ async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt::init();

// Local address to bind the service to.
let addr = "127.0.0.1:3030".parse().unwrap();

// Make the interaction handler into a service function.
let interaction_service = make_service_fn(|_| async {
Ok::<_, anyhow::Error>(service_fn(|req| interaction_handler(req, handler)))
});

// Construct the server and serve the interaction service.
let server = Server::bind(&addr).serve(interaction_service);

// Start the server.
server.await?;

Ok(())
let addr = SocketAddr::from(([127, 0, 0, 1], 3030));

// Bind the server and serve the interaction service.
let listener = TcpListener::bind(addr).await?;

loop {
let (conn, _) = listener.accept().await?;

tokio::spawn(async move {
if let Err(e) = http1::Builder::new()
.serve_connection(
TokioIo::new(conn),
service_fn(|req| interaction_handler(req, handler)),
)
.await
{
tracing::error!("Error handling HTTP request: {e}");
};
});
}
}
6 changes: 3 additions & 3 deletions twilight-gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ futures-util = { default-features = false, features = ["sink", "std"], version =
serde = { default-features = false, features = ["derive"], version = "1" }
serde_json = { default-features = false, features = ["std"], version = "1" }
tokio = { default-features = false, features = ["net", "rt", "sync", "time"], version = "1.19" }
tokio-websockets = { default-features = false, features = ["client", "fastrand", "sha1_smol", "simd"], version = "0.4" }
tokio-websockets = { default-features = false, features = ["client", "fastrand", "sha1_smol", "simd"], version = "0.5" }
tracing = { default-features = false, features = ["std", "attributes"], version = "0.1" }
twilight-gateway-queue = { default-features = false, path = "../twilight-gateway-queue", version = "0.15.4" }
twilight-model = { default-features = false, path = "../twilight-model", version = "0.15.4" }
Expand All @@ -45,8 +45,8 @@ tracing-subscriber = { default-features = false, features = ["fmt", "tracing-log
[features]
default = ["rustls-native-roots", "twilight-http", "zlib-stock"]
native = ["tokio-websockets/native-tls", "tokio-websockets/openssl"]
rustls-native-roots = ["tokio-websockets/rustls-native-roots"]
rustls-webpki-roots = ["tokio-websockets/rustls-webpki-roots"]
rustls-native-roots = ["tokio-websockets/ring", "tokio-websockets/rustls-native-roots"]
rustls-webpki-roots = ["tokio-websockets/ring", "tokio-websockets/rustls-webpki-roots"]
zlib-simd = ["dep:flate2", "flate2?/zlib-ng"]
zlib-stock = ["dep:flate2", "flate2?/zlib"]

Expand Down
4 changes: 2 additions & 2 deletions twilight-gateway/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
};
use std::fmt::{Display, Formatter, Result as FmtResult};
use tokio::net::TcpStream;
use tokio_websockets::{ClientBuilder, Connector, Limits, MaybeTlsStream, WebsocketStream};
use tokio_websockets::{ClientBuilder, Connector, Limits, MaybeTlsStream, WebSocketStream};

/// Query argument with zlib-stream enabled.
#[cfg(any(feature = "zlib-stock", feature = "zlib-simd"))]
Expand All @@ -24,7 +24,7 @@ const GATEWAY_URL: &str = "wss://gateway.discord.gg";
/// Connections are used by [`Shard`]s when reconnecting.
///
/// [`Shard`]: crate::Shard
pub type Connection = WebsocketStream<MaybeTlsStream<TcpStream>>;
pub type Connection = WebSocketStream<MaybeTlsStream<TcpStream>>;

/// Formatter for a gateway URL, with the API version and compression features
/// specified.
Expand Down
2 changes: 1 addition & 1 deletion twilight-http-ratelimiting/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ tracing = { default-features = false, features = ["std", "attributes"], version

[dev-dependencies]
criterion = { default-features = false, version = "0.4" }
http = { version = "0.2", default-features = false }
http = { version = "1", default-features = false }
static_assertions = { default-features = false, version = "1.1.0" }
tokio = { default-features = false, features = ["macros", "rt-multi-thread"], version = "1.0" }

Expand Down
11 changes: 7 additions & 4 deletions twilight-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ version = "0.15.4"

[dependencies]
fastrand = { default-features = false, features = ["std"], version = "2" }
hyper = { default-features = false, features = ["client", "http1", "http2", "runtime"], version = "0.14" }
hyper-rustls = { default-features = false, optional = true, features = ["http1", "http2"], version = "0.24" }
hyper-tls = { default-features = false, optional = true, version = "0.5" }
hyper-hickory = { default-features = false, optional = true, features = ["tokio"], version = "0.6" }
http = { default-features = false, version = "1" }
http-body-util = { default-features = false, version = "0.1" }
hyper = { default-features = false, version = "1" }
hyper-util = { default-features = false, features = ["client-legacy", "http1", "http2", "tokio"], version = "0.1.2" }
hyper-rustls = { default-features = false, optional = true, features = ["http1", "http2", "ring"], version = "0.26" }
hyper-tls = { default-features = false, optional = true, features = ["alpn"], version = "0.6" }
hyper-hickory = { default-features = false, optional = true, version = "0.7" }
percent-encoding = { default-features = false, version = "2" }
serde = { default-features = false, features = ["derive"], version = "1" }
serde_json = { default-features = false, features = ["std"], version = "1" }
Expand Down
6 changes: 4 additions & 2 deletions twilight-http/src/client/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::Token;
use crate::{client::connector, Client};
use hyper::header::HeaderMap;
use http::header::HeaderMap;
use hyper_util::rt::TokioExecutor;
use std::{
sync::{atomic::AtomicBool, Arc},
time::Duration,
Expand Down Expand Up @@ -32,7 +33,8 @@ impl ClientBuilder {
pub fn build(self) -> Client {
let connector = connector::create();

let http = hyper::Client::builder().build(connector);
let http =
hyper_util::client::legacy::Client::builder(TokioExecutor::new()).build(connector);

let token_invalidated = if self.remember_invalid_token {
Some(Arc::new(AtomicBool::new(false)))
Expand Down
5 changes: 3 additions & 2 deletions twilight-http/src/client/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type HttpsConnector<T> = hyper_tls::HttpsConnector<T>;
type HttpConnector = hyper_hickory::TokioHickoryHttpConnector;
/// HTTP connector.
#[cfg(not(feature = "hickory"))]
type HttpConnector = hyper::client::HttpConnector;
type HttpConnector = hyper_util::client::legacy::connect::HttpConnector;

/// Re-exported generic connector for use in the client.
#[cfg(any(
Expand All @@ -35,7 +35,7 @@ pub type Connector = HttpConnector;
/// Create a connector with the specified features.
pub fn create() -> Connector {
#[cfg(not(feature = "hickory"))]
let mut connector = hyper::client::HttpConnector::new();
let mut connector = HttpConnector::new();
#[cfg(feature = "hickory")]
let mut connector = hyper_hickory::TokioHickoryResolver::default().into_http_connector();

Expand All @@ -44,6 +44,7 @@ pub fn create() -> Connector {
#[cfg(feature = "rustls-native-roots")]
let connector = hyper_rustls::HttpsConnectorBuilder::new()
.with_native_roots()
.expect("no native root certificates found")
.https_or_http()
.enable_http1()
.enable_http2()
Expand Down
17 changes: 9 additions & 8 deletions twilight-http/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,12 @@ use crate::{
response::ResponseFuture,
API_VERSION,
};
use hyper::{
client::Client as HyperClient,
header::{HeaderMap, HeaderValue, AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, USER_AGENT},
Body,
use http::header::{
HeaderMap, HeaderValue, AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, USER_AGENT,
};
use http_body_util::Full;
use hyper::body::Bytes;
use hyper_util::client::legacy::Client as HyperClient;
use std::{
fmt::{Debug, Formatter, Result as FmtResult},
ops::Deref,
Expand Down Expand Up @@ -224,7 +225,7 @@ impl Deref for Token {
pub struct Client {
pub(crate) default_allowed_mentions: Option<AllowedMentions>,
default_headers: Option<HeaderMap>,
http: HyperClient<Connector>,
http: HyperClient<Connector, Full<Bytes>>,
proxy: Option<Box<str>>,
ratelimiter: Option<Box<dyn Ratelimiter>>,
timeout: Duration,
Expand Down Expand Up @@ -2657,11 +2658,11 @@ impl Client {
}

let try_req = if let Some(form) = form {
builder.body(Body::from(form.build()))
builder.body(Full::from(form.build()))
} else if let Some(bytes) = body {
builder.body(Body::from(bytes))
builder.body(Full::from(bytes))
} else {
builder.body(Body::empty())
builder.body(Full::default())
};

let inner = self.http.request(try_req.map_err(|source| Error {
Expand Down
5 changes: 3 additions & 2 deletions twilight-http/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{api_error::ApiError, json::JsonError, response::StatusCode};
use hyper::{Body, Response};
use http::Response;
use hyper::body::Incoming;
use std::{
error::Error as StdError,
fmt::{Debug, Display, Formatter, Result as FmtResult},
Expand Down Expand Up @@ -125,7 +126,7 @@ pub enum ErrorType {
///
/// This may occur during Discord API stability incidents.
ServiceUnavailable {
response: Response<Body>,
response: Response<Incoming>,
},
/// Token in use has become revoked or is otherwise invalid.
///
Expand Down
2 changes: 1 addition & 1 deletion twilight-http/src/request/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
error::Error,
routing::{Path, Route},
};
use hyper::header::{HeaderMap, HeaderName, HeaderValue};
use http::header::{HeaderMap, HeaderName, HeaderValue};
use serde::Serialize;

/// Builder to create a customized request.
Expand Down
Loading