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

upgrade to hyper v1.0 #1368

Merged
merged 23 commits into from
May 21, 2024
Merged

upgrade to hyper v1.0 #1368

merged 23 commits into from
May 21, 2024

Conversation

niklasad1
Copy link
Member

@niklasad1 niklasad1 commented May 10, 2024

Close #1257

Things that could be improved in this PR or in follow-up:

  • add helper function serve/serve_with_graceful_shutdown such that users of the low-level API doesn't have to implement their graceful shutdown stuff (I have repeated that a few times already now)
  • get rid of BoxBody if possible
  • add additional feature flags to support aws-lc-rs TLS crypto backend

@niklasad1 niklasad1 added the breaking change Breaking change in the public APIs label May 16, 2024
@niklasad1 niklasad1 changed the title [WIP]: upgrade to hyper v1.0 upgrade to hyper v1.0 May 17, 2024
@@ -34,8 +37,8 @@ tokio = { version = "1.16", features = ["net", "rt-multi-thread", "macros"] }

[features]
default = ["native-tls"]
native-tls = ["hyper-rustls/native-tokio", "__tls"]
webpki-tls = ["hyper-rustls/webpki-tokio", "__tls"]
native-tls = ["hyper-rustls/native-tokio", "hyper-rustls/ring", "__tls"]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's discuss whether we should support both crypto backends.

Rustls now supports both ring and aws-lc-rs but migrating to aws-lc-rs requires more dependencies such as cmake, NASM etc.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with not exposing it initially, and then as a non-breaking change we can always expose it later or whatever if there's demand :)

server/src/transport/ws.rs Outdated Show resolved Hide resolved
@niklasad1 niklasad1 marked this pull request as ready for review May 17, 2024 15:54
@niklasad1 niklasad1 requested a review from a team as a code owner May 17, 2024 15:54
@@ -46,3 +46,10 @@ mod tests;
pub use client::{HttpClient, HttpClientBuilder};
pub use hyper::http::{HeaderMap, HeaderValue};
pub use jsonrpsee_types as types;

/// Default HTTP body for the client.
pub type HttpBody = http_body_util::Full<hyper::body::Bytes>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this also be jsonrpsee_core::http_helpers::ResponseBody, since the below two things reference that?

(maybe rename RepsonseBody to HttpBody though?)

@@ -63,17 +66,17 @@ async fn main() -> anyhow::Result<()> {
println!("[main]: response: {:?}", response);

// Use hyper client to manually submit a `GET /health` request.
let http_client = Client::new();
let http_client = Client::builder(TokioExecutor::new()).build_http();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting way to be agnostic over runtime; I could imagine we might adopt a similar thing in subxt to hide the spawning stuff behind the scenes unless the user wants to override the executor or manually drive stuff

Comment on lines 419 to 425
let upgraded = match hyper::upgrade::on(req).await {
Ok(u) => u,
Err(e) => {
tracing::debug!(target: LOG_TARGET, "WS upgrade handshake failed: {}", e);
return Err(HttpResponse::new(HttpResponseBody::from(format!("WS upgrade handshake failed {e}"))));
}
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the thing that moved into that async block below not super long ago for a reason I can't remember (maybe something shutdown related)?

Wondering what the impact of moving it up is!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like, previously it would only be executed when the returned future is polled, but now it's executed in the connect(..).await and has to finish before the fut is returned

Copy link
Member Author

@niklasad1 niklasad1 May 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thus, it will be stuck until the response is returned but I can add a comment in the code because it confuses me as well

/// fn run_server() -> ServerHandle {
/// let addr = SocketAddr::from(([127, 0, 0, 1], 0));
/// async fn run_server() -> ServerHandle {
/// let listener = tokio::net::TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], 0))).await.unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this could move into the tokio::spawn and then run_server could be sync again (iirc this is in an example or two as well)?

Copy link
Collaborator

@jsdw jsdw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, nice one! Just a couple of small comments!

@niklasad1
Copy link
Member Author

@CodiumAI-Agent /review

@CodiumAI-Agent
Copy link

PR Review 🔍

⏱️ Estimated effort to review [1-5]

5, because the PR involves multiple files with significant changes including feature updates, refactoring, and dependency updates. The complexity and breadth of the changes require a thorough review to ensure compatibility, performance, and adherence to best practices.

🧪 Relevant tests

No

⚡ Possible issues

Possible Bug: The PR introduces changes across multiple files which could lead to integration issues if not properly tested. For example, updates in dependency versions and major refactoring could affect existing functionalities.

Performance Concern: The extensive use of new features and libraries might impact the performance. It is crucial to benchmark the new changes against the current implementation to ensure there is no performance degradation.

🔒 Security concerns

No

Code feedback:
relevant fileserver/src/server.rs
suggestion      

Consider adding integration tests to cover the new changes introduced in the server configuration and connection handling. This is important to ensure that the new configurations and the refactored connection handling work as expected under different scenarios. [important]

relevant lineuse hyper::body::Bytes;

relevant fileserver/src/server.rs
suggestion      

It's recommended to handle possible errors from the tokio::net::TcpListener::bind method to prevent the server from panicking at runtime if the address is already in use or if there are insufficient permissions to bind to the address. [important]

relevant linelet listener = tokio::net::TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], 0))).await.unwrap();

relevant fileserver/src/server.rs
suggestion      

For better error handling and to avoid potential data loss, consider implementing a backpressure mechanism or a way to handle backpressure from clients in the server implementation. This could prevent the server from being overwhelmed by too many requests or data at once. [medium]

relevant lineuse futures_util::future::{self, Either};

relevant fileserver/src/server.rs
suggestion      

To improve the modularity and readability of the server setup code, consider refactoring the large async block inside tokio::spawn into separate functions or methods. This would make the code easier to maintain and test. [medium]

relevant linetokio::spawn(async move {

@@ -960,32 +995,28 @@ impl<RpcMiddleware, HttpMiddleware> TowerService<RpcMiddleware, HttpMiddleware>
}
}

impl<RpcMiddleware, HttpMiddleware> hyper::service::Service<hyper::Request<hyper::Body>>
for TowerService<RpcMiddleware, HttpMiddleware>
impl<B, RpcMiddleware, HttpMiddleware> Service<HttpRequest<B>> for TowerService<RpcMiddleware, HttpMiddleware>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Maybe instead of B we can call this Body? To keep consistency with RpcMiddleware and HttpMiddleware?

@@ -461,6 +461,8 @@ fn assert_error_response(err: Error, exp: ErrorObjectOwned) {

#[tokio::test]
async fn redirections() {
init_logger();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is this indended?

Copy link
Contributor

@lexnv lexnv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@niklasad1 niklasad1 merged commit 257513e into master May 21, 2024
11 checks passed
@niklasad1 niklasad1 deleted the na-hyper-v1.0 branch May 21, 2024 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change Breaking change in the public APIs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[deps]: update hyper to v1.0
4 participants