From b2bb37685366f18d2f49e6b62bf9e5f35b6e8972 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Thu, 4 Jan 2024 13:12:08 -0700 Subject: [PATCH] support axum instead of hyper --- Cargo.lock | 127 ++++++++++++++++++++++++++++++++- rpc-toolkit/Cargo.toml | 3 +- rpc-toolkit/src/lib.rs | 2 +- rpc-toolkit/src/server/http.rs | 69 ++++++++---------- 4 files changed, 158 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4f565aa..ab70355 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,6 +123,61 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "axum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d09dbe0e490df5da9d69b36dca48a76635288a82f92eca90024883a56202026d" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.1.0", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87c8503f93e6d144ee5690907ba22db7ba79ab001a932ab99034f0fe836b3df" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -604,7 +659,6 @@ dependencies = [ "itoa", "pin-project-lite", "tokio", - "want", ] [[package]] @@ -620,6 +674,24 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "hyper-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "hyper 1.1.0", + "pin-project-lite", + "socket2", + "tokio", + "tracing", +] + [[package]] name = "idna" version = "0.5.0" @@ -744,6 +816,12 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "memchr" version = "2.7.1" @@ -1026,11 +1104,11 @@ version = "0.2.3" dependencies = [ "async-stream", "async-trait", + "axum", "clap", "futures", "http 1.0.0", "http-body-util", - "hyper 1.1.0", "imbl-value", "itertools", "lazy_format", @@ -1087,6 +1165,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.16" @@ -1172,6 +1256,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" +dependencies = [ + "itoa", + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1246,6 +1340,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-configuration" version = "0.5.1" @@ -1380,6 +1480,28 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -1392,6 +1514,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-core", ] diff --git a/rpc-toolkit/Cargo.toml b/rpc-toolkit/Cargo.toml index 7ab144d..5604917 100644 --- a/rpc-toolkit/Cargo.toml +++ b/rpc-toolkit/Cargo.toml @@ -16,13 +16,14 @@ cbor = ["serde_cbor"] default = ["cbor"] [dependencies] +axum = "0.7.3" async-stream = "0.3" async-trait = "0.1" clap = { version = "4", features = ["derive"] } futures = "0.3" http = "1" http-body-util = "0.1" -hyper = { version = "1", features = ["server", "http1", "http2", "client"] } +# hyper = { version = "1", features = ["server", "http1", "http2", "client"] } itertools = "0.12" imbl-value = { git = "https://github.com/Start9Labs/imbl-value.git" } lazy_format = "2" diff --git a/rpc-toolkit/src/lib.rs b/rpc-toolkit/src/lib.rs index d1a60c2..ef404ef 100644 --- a/rpc-toolkit/src/lib.rs +++ b/rpc-toolkit/src/lib.rs @@ -25,7 +25,7 @@ pub use handler::*; /// See also: [arg](rpc_toolkit_macro::arg), [context](rpc_toolkit_macro::context) pub use rpc_toolkit_macro::command; pub use server::*; -pub use {clap, futures, hyper, reqwest, serde, serde_json, tokio, url, yajrc}; +pub use {clap, futures, reqwest, serde, serde_json, tokio, url, yajrc}; mod cli; pub mod command_helpers; diff --git a/rpc-toolkit/src/server/http.rs b/rpc-toolkit/src/server/http.rs index 2bb4171..f433825 100644 --- a/rpc-toolkit/src/server/http.rs +++ b/rpc-toolkit/src/server/http.rs @@ -1,12 +1,14 @@ use std::any::TypeId; +use axum::body::Body; +use axum::extract::Request; +use axum::handler::Handler; +use axum::response::Response; use futures::future::{join_all, BoxFuture}; use futures::FutureExt; use http::header::{CONTENT_LENGTH, CONTENT_TYPE}; use http_body_util::BodyExt; -use hyper::body::{Bytes, Incoming}; -use hyper::service::Service; -use hyper::{Request, Response}; +use imbl_value::imbl::Vector; use imbl_value::Value; use serde::de::DeserializeOwned; use serde::Serialize; @@ -18,15 +20,15 @@ use crate::{HandleAny, Server}; const FALLBACK_ERROR: &str = "{\"error\":{\"code\":-32603,\"message\":\"Internal error\",\"data\":\"Failed to serialize rpc response\"}}"; -pub fn fallback_rpc_error_response() -> Response { +pub fn fallback_rpc_error_response() -> Response { Response::builder() .header(CONTENT_TYPE, "application/json") .header(CONTENT_LENGTH, FALLBACK_ERROR.len()) - .body(Bytes::from_static(FALLBACK_ERROR.as_bytes())) + .body(Body::from(FALLBACK_ERROR.as_bytes())) .unwrap() } -pub fn json_http_response(t: &T) -> Response { +pub fn json_http_response(t: &T) -> Response { let body = match serde_json::to_vec(t) { Ok(a) => a, Err(_) => return fallback_rpc_error_response(), @@ -34,12 +36,10 @@ pub fn json_http_response(t: &T) -> Response { Response::builder() .header(CONTENT_TYPE, "application/json") .header(CONTENT_LENGTH, body.len()) - .body(Bytes::from(body)) + .body(Body::from(body)) .unwrap_or_else(|_| fallback_rpc_error_response()) } -pub type BoxBody = http_body_util::combinators::BoxBody; - #[async_trait::async_trait] pub trait Middleware: Clone + Send + Sync + 'static { type Metadata: DeserializeOwned + Send + 'static; @@ -47,8 +47,8 @@ pub trait Middleware: Clone + Send + Sync + 'static { async fn process_http_request( &mut self, context: &Context, - request: &mut Request, - ) -> Result<(), Response> { + request: &mut Request, + ) -> Result<(), Response> { Ok(()) } #[allow(unused_variables)] @@ -63,7 +63,7 @@ pub trait Middleware: Clone + Send + Sync + 'static { #[allow(unused_variables)] async fn process_rpc_response(&mut self, context: &Context, response: &mut RpcResponse) {} #[allow(unused_variables)] - async fn process_http_response(&mut self, context: &Context, response: &mut Response) {} + async fn process_http_response(&mut self, context: &Context, response: &mut Response) {} } #[allow(private_bounds)] @@ -72,8 +72,8 @@ trait _Middleware: Send + Sync { fn process_http_request<'a>( &'a mut self, context: &'a Context, - request: &'a mut Request, - ) -> BoxFuture<'a, Result<(), Response>>; + request: &'a mut Request, + ) -> BoxFuture<'a, Result<(), Response>>; fn process_rpc_request<'a>( &'a mut self, context: &'a Context, @@ -89,7 +89,7 @@ trait _Middleware: Send + Sync { fn process_http_response<'a>( &'a mut self, context: &'a Context, - response: &'a mut Response, + response: &'a mut Response, ) -> BoxFuture<'a, ()>; } impl + Send + Sync> _Middleware for T { @@ -99,8 +99,8 @@ impl + Send + Sync> _Middleware< fn process_http_request<'a>( &'a mut self, context: &'a Context, - request: &'a mut Request, - ) -> BoxFuture<'a, Result<(), Response>> { + request: &'a mut Request, + ) -> BoxFuture<'a, Result<(), Response>> { >::process_http_request(self, context, request) } fn process_rpc_request<'a>( @@ -129,7 +129,7 @@ impl + Send + Sync> _Middleware< fn process_http_response<'a>( &'a mut self, context: &'a Context, - response: &'a mut Response, + response: &'a mut Response, ) -> BoxFuture<'a, ()> { >::process_http_response(self, context, response) } @@ -144,7 +144,7 @@ impl Clone for DynMiddleware { pub struct HttpServer { inner: Server, - middleware: Vec>, + middleware: Vector>, } impl Clone for HttpServer { fn clone(&self) -> Self { @@ -158,7 +158,7 @@ impl Server { pub fn for_http(self) -> HttpServer { HttpServer { inner: self, - middleware: Vec::new(), + middleware: Vector::new(), } } pub fn middleware>(self, middleware: T) -> HttpServer { @@ -167,10 +167,11 @@ impl Server { } impl HttpServer { pub fn middleware>(mut self, middleware: T) -> Self { - self.middleware.push(DynMiddleware(Box::new(middleware))); + self.middleware + .push_back(DynMiddleware(Box::new(middleware))); self } - async fn process_http_request(&self, mut req: Request) -> Response { + async fn process_http_request(&self, mut req: Request) -> Response { let mut mid = self.middleware.clone(); match async { let ctx = (self.inner.make_ctx)().await?; @@ -234,7 +235,7 @@ impl HttpServer { async fn process_rpc_request( &self, ctx: &Context, - mid: &mut Vec>, + mid: &mut Vector>, mut req: RpcRequest, ) -> RpcResponse { let metadata = Value::Object( @@ -278,25 +279,15 @@ impl HttpServer { } res } - pub fn handle(&self, req: Request) -> BoxFuture<'static, Response> { + pub fn handle(&self, req: Request) -> BoxFuture<'static, Response> { let server = self.clone(); - async move { - server - .process_http_request(req.map(|b| BoxBody::new(b))) - .await - } - .boxed() + async move { server.process_http_request(req).await }.boxed() } } -impl Service> for HttpServer { - type Response = Response; - type Error = hyper::Error; - type Future = futures::future::Map< - BoxFuture<'static, Self::Response>, - fn(Self::Response) -> Result, - >; - fn call(&self, req: Request) -> Self::Future { - self.handle(req).map(Ok) +impl Handler<(), ()> for HttpServer { + type Future = BoxFuture<'static, Response>; + fn call(self, req: Request, _: ()) -> Self::Future { + self.handle(req) } }