Skip to content

Commit 5438346

Browse files
authored
Merge branch 'main' into improve/remove_fxhash
2 parents 90611f3 + ee2c2a2 commit 5438346

22 files changed

+569
-832
lines changed

Cargo.lock

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ROADMAP.md

+3-7
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ refused! We are always happy to receive patches for new cool features we haven't
99
or didn't judge to be a priority. Please however understand that such patches might take longer
1010
for us to review.
1111

12-
## Runtime
13-
14-
- [ ] #2 Use `monoio` as an opt-in runtime
15-
1612
## Service Governence
1713

1814
- [ ] Support OpenSergo
@@ -28,16 +24,16 @@ for us to review.
2824

2925
### Load Balancer
3026

31-
- [ ] #7 Support consistent hash load balancing
27+
- [x] #7 Support consistent hash load balancing
3228

3329
### Proxyless
3430

3531
- [ ] Support Proxyless mode
3632

3733
## TLS
3834

39-
- [ ] #6 Support TLS for `volo-grpc`
35+
- [x] #6 Support TLS for `volo-grpc`
4036

4137
## Cli
4238

43-
- [ ] #5 Support auto generate service code in lib.rs
39+
- [x] #5 Support auto generate service code in lib.rs

examples/src/http/simple.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ async fn conn_show(conn: ConnectionInfo) -> String {
114114
format!("{conn:?}\n")
115115
}
116116

117+
struct State {
118+
foo: String,
119+
bar: usize,
120+
}
121+
117122
async fn extension(Extension(state): Extension<Arc<State>>) -> String {
118123
format!("State {{ foo: {}, bar: {} }}\n", state.foo, state.bar)
119124
}
@@ -264,9 +269,15 @@ async fn headers_map_response(response: Response) -> impl IntoResponse {
264269
)
265270
}
266271

267-
struct State {
268-
foo: String,
269-
bar: usize,
272+
fn tracer(cx: &ServerContext) {
273+
tracing::info!(
274+
"process start at {:?}, end at {:?}, req size: {:?}, resp size: {:?}, resp status: {:?}",
275+
cx.stats.process_start_at().unwrap(),
276+
cx.stats.process_end_at().unwrap(),
277+
cx.common_stats.req_size().unwrap(),
278+
cx.common_stats.resp_size().unwrap(),
279+
cx.stats.status_code().unwrap(),
280+
);
270281
}
271282

272283
#[tokio::main(flavor = "multi_thread")]
@@ -297,5 +308,9 @@ async fn main() {
297308

298309
println!("Listening on {addr}");
299310

300-
Server::new(app).run(addr).await.unwrap();
311+
Server::new(app)
312+
.stat_tracer(tracer)
313+
.run(addr)
314+
.await
315+
.unwrap();
301316
}

examples/src/http/state.rs

-39
This file was deleted.

volo-grpc/src/transport/connect.rs

+47-50
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::{
88
use futures_util::future::BoxFuture;
99
use hyper::rt::ReadBufCursor;
1010
use hyper_util::client::legacy::connect::{Connected, Connection};
11+
use motore::{make::MakeConnection, service::UnaryService};
1112
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
1213
use volo::net::{
1314
conn::Conn,
@@ -55,6 +56,19 @@ impl Default for Connector {
5556
}
5657
}
5758

59+
impl UnaryService<Address> for Connector {
60+
type Response = Conn;
61+
type Error = io::Error;
62+
63+
async fn call(&self, addr: Address) -> Result<Self::Response, Self::Error> {
64+
match self {
65+
Self::Default(mkt) => mkt.make_connection(addr).await,
66+
#[cfg(any(feature = "rustls", feature = "native-tls"))]
67+
Self::Tls(mkt) => mkt.make_connection(addr).await,
68+
}
69+
}
70+
}
71+
5872
impl tower::Service<hyper::Uri> for Connector {
5973
type Response = ConnectionWrapper;
6074

@@ -67,61 +81,44 @@ impl tower::Service<hyper::Uri> for Connector {
6781
}
6882

6983
fn call(&mut self, uri: hyper::Uri) -> Self::Future {
70-
macro_rules! box_pin_call {
71-
($mk_conn:ident) => {
72-
Box::pin(async move {
73-
let authority = uri.authority().expect("authority required").as_str();
74-
let target: Address = match uri.scheme_str() {
75-
Some("http") => {
76-
Address::Ip(authority.parse::<SocketAddr>().map_err(|_| {
77-
io::Error::new(
78-
io::ErrorKind::InvalidInput,
79-
"authority must be valid SocketAddr",
80-
)
81-
})?)
82-
}
83-
#[cfg(target_family = "unix")]
84-
Some("http+unix") => {
85-
use hex::FromHex;
86-
87-
let bytes = Vec::from_hex(authority).map_err(|_| {
84+
let connector = self.clone();
85+
Box::pin(async move {
86+
let authority = uri.authority().expect("authority required").as_str();
87+
let target: Address = match uri.scheme_str() {
88+
Some("http") => Address::Ip(authority.parse::<SocketAddr>().map_err(|_| {
89+
io::Error::new(
90+
io::ErrorKind::InvalidInput,
91+
"authority must be valid SocketAddr",
92+
)
93+
})?),
94+
#[cfg(target_family = "unix")]
95+
Some("http+unix") => {
96+
use hex::FromHex;
97+
98+
let bytes = Vec::from_hex(authority).map_err(|_| {
99+
io::Error::new(
100+
io::ErrorKind::InvalidInput,
101+
"authority must be hex-encoded path",
102+
)
103+
})?;
104+
Address::Unix(std::borrow::Cow::Owned(
105+
String::from_utf8(bytes)
106+
.map_err(|_| {
88107
io::Error::new(
89108
io::ErrorKind::InvalidInput,
90-
"authority must be hex-encoded path",
109+
"authority must be valid UTF-8",
91110
)
92-
})?;
93-
Address::Unix(std::borrow::Cow::Owned(
94-
String::from_utf8(bytes)
95-
.map_err(|_| {
96-
io::Error::new(
97-
io::ErrorKind::InvalidInput,
98-
"authority must be valid UTF-8",
99-
)
100-
})?
101-
.into(),
102-
))
103-
}
104-
_ => unimplemented!(),
105-
};
106-
107-
Ok(ConnectionWrapper {
108-
inner: $mk_conn.make_connection(target).await?,
109-
})
110-
})
111+
})?
112+
.into(),
113+
))
114+
}
115+
_ => unimplemented!(),
111116
};
112-
}
113117

114-
match self {
115-
Self::Default(mk_conn) => {
116-
let mk_conn = *mk_conn;
117-
box_pin_call!(mk_conn)
118-
}
119-
#[cfg(any(feature = "rustls", feature = "native-tls"))]
120-
Self::Tls(mk_conn) => {
121-
let mk_conn = mk_conn.clone();
122-
box_pin_call!(mk_conn)
123-
}
124-
}
118+
Ok(ConnectionWrapper {
119+
inner: connector.make_connection(target).await?,
120+
})
121+
})
125122
}
126123
}
127124

volo-http/Cargo.toml

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "volo-http"
3-
version = "0.1.14"
3+
version = "0.1.17"
44
edition.workspace = true
55
homepage.workspace = true
66
repository.workspace = true
@@ -20,18 +20,20 @@ maintenance = { status = "actively-developed" }
2020
[dependencies]
2121
volo = { version = "0.9", path = "../volo" }
2222

23-
http-body-util = "0.1"
24-
hyper = { version = "1", features = ["server", "http1", "http2"] }
25-
hyper-util = { version = "0.1", features = ["tokio"] }
26-
2723
ahash.workspace = true
2824
bytes.workspace = true
2925
chrono.workspace = true
3026
cookie = { workspace = true, optional = true, features = ["percent-encode"] }
3127
faststr.workspace = true
3228
futures.workspace = true
3329
futures-util.workspace = true
30+
http.workspace = true
31+
http-body.workspace = true
32+
http-body-util.workspace = true
33+
hyper = { workspace = true, features = ["server", "http1", "http2"] }
34+
hyper-util = { workspace = true, features = ["tokio"] }
3435
matchit.workspace = true
36+
metainfo.workspace = true
3537
mime.workspace = true
3638
motore.workspace = true
3739
parking_lot.workspace = true

volo-http/src/body.rs

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use std::{
2+
convert::Infallible,
3+
pin::Pin,
4+
task::{Context, Poll},
5+
};
6+
7+
use bytes::Bytes;
8+
use faststr::FastStr;
9+
use futures_util::ready;
10+
use http_body::{Frame, SizeHint};
11+
use http_body_util::Full;
12+
use pin_project::pin_project;
13+
14+
#[pin_project]
15+
pub struct Body {
16+
#[pin]
17+
inner: Full<Bytes>,
18+
}
19+
20+
impl http_body::Body for Body {
21+
type Data = Bytes;
22+
23+
type Error = Infallible;
24+
25+
fn poll_frame(
26+
self: Pin<&mut Self>,
27+
cx: &mut Context<'_>,
28+
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
29+
Poll::Ready(ready!(self.project().inner.poll_frame(cx)).map(|result| Ok(result.unwrap())))
30+
}
31+
32+
fn is_end_stream(&self) -> bool {
33+
self.inner.is_end_stream()
34+
}
35+
36+
fn size_hint(&self) -> SizeHint {
37+
self.inner.size_hint()
38+
}
39+
}
40+
41+
impl From<()> for Body {
42+
fn from(_: ()) -> Self {
43+
Self {
44+
inner: Full::new(Bytes::new()),
45+
}
46+
}
47+
}
48+
49+
impl From<&'static str> for Body {
50+
fn from(value: &'static str) -> Self {
51+
Self {
52+
inner: Full::new(value.into()),
53+
}
54+
}
55+
}
56+
57+
impl From<Vec<u8>> for Body {
58+
fn from(value: Vec<u8>) -> Self {
59+
Self {
60+
inner: Full::new(value.into()),
61+
}
62+
}
63+
}
64+
65+
impl From<Bytes> for Body {
66+
fn from(value: Bytes) -> Self {
67+
Self {
68+
inner: Full::new(value),
69+
}
70+
}
71+
}
72+
73+
impl From<FastStr> for Body {
74+
fn from(value: FastStr) -> Self {
75+
Self {
76+
inner: Full::new(value.into()),
77+
}
78+
}
79+
}
80+
81+
impl From<String> for Body {
82+
fn from(value: String) -> Self {
83+
Self {
84+
inner: Full::new(value.into()),
85+
}
86+
}
87+
}
88+
89+
impl From<Full<Bytes>> for Body {
90+
fn from(value: Full<Bytes>) -> Self {
91+
Self { inner: value }
92+
}
93+
}

0 commit comments

Comments
 (0)