Skip to content

Commit e82d140

Browse files
authored
feat(volo-http): support http/2 for server (#573)
* feat(volo-http): support http2 for server * chore(volo-http): update Cargo.toml and test cases in CI script --------- Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
1 parent be8eccb commit e82d140

5 files changed

Lines changed: 310 additions & 58 deletions

File tree

Cargo.lock

Lines changed: 6 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/clippy-and-test.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ echo_command cargo clippy -p volo-grpc --no-default-features --features grpc-web
3232
echo_command cargo clippy -p volo-http --no-default-features -- --deny warnings
3333
echo_command cargo clippy -p volo-http --no-default-features --features default-client -- --deny warnings
3434
echo_command cargo clippy -p volo-http --no-default-features --features default-server -- --deny warnings
35-
echo_command cargo clippy -p volo-http --no-default-features --features client,server -- --deny warnings
35+
echo_command cargo clippy -p volo-http --no-default-features --features client,server,http1 -- --deny warnings
36+
echo_command cargo clippy -p volo-http --no-default-features --features client,server,http2 -- --deny warnings
3637
echo_command cargo clippy -p volo-http --no-default-features --features full -- --deny warnings
3738
echo_command cargo clippy -p volo -- --deny warnings
3839
echo_command cargo clippy -p volo --no-default-features --features rustls-aws-lc-rs -- --deny warnings

volo-http/Cargo.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,23 +97,26 @@ tokio-test.workspace = true
9797
default = []
9898

9999
default-client = ["client", "json"]
100-
default-server = ["server", "query", "form", "json", "multipart"]
100+
default-server = ["server", "http1", "http2", "query", "form", "json", "multipart"]
101101

102102
full = [
103103
"client", "server", # core
104+
"http1", "http2", # protocol
104105
"query", "form", "json", # serde
105106
"tls", # https
106107
"cookie", "multipart", "ws", # exts
107108
]
108109

109110
http1 = ["hyper/http1", "hyper-util/http1"]
111+
http2 = ["hyper/http2", "hyper-util/http2"]
110112

111113
client = [
112-
"http1", "hyper/client",
114+
"hyper/client",
115+
"http1", # to be removed
113116
"dep:async-broadcast", "dep:chrono", "dep:hickory-resolver",
114117
] # client core
115118
server = [
116-
"http1", "hyper-util/server",
119+
"hyper-util/server",
117120
"dep:ipnet", "dep:matchit", "dep:memchr", "dep:scopeguard", "dep:mime_guess",
118121
] # server core
119122

volo-http/src/server/mod.rs

Lines changed: 50 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub mod layer;
4747
pub mod middleware;
4848
pub mod panic_handler;
4949
pub mod param;
50+
pub mod protocol;
5051
pub mod response;
5152
pub mod route;
5253
#[cfg(test)]
@@ -198,54 +199,6 @@ impl<S, L> Server<S, L> {
198199
&mut self.config
199200
}
200201

201-
/// Set whether HTTP/1 connections should support half-closures.
202-
///
203-
/// Clients can chose to shutdown their write-side while waiting
204-
/// for the server to respond. Setting this to `true` will
205-
/// prevent closing the connection immediately if `read`
206-
/// detects an EOF in the middle of a request.
207-
///
208-
/// Default is `false`.
209-
pub fn set_half_close(&mut self, half_close: bool) -> &mut Self {
210-
self.server.http1().half_close(half_close);
211-
self
212-
}
213-
214-
/// Enables or disables HTTP/1 keep-alive.
215-
///
216-
/// Default is true.
217-
pub fn set_keep_alive(&mut self, keep_alive: bool) -> &mut Self {
218-
self.server.http1().keep_alive(keep_alive);
219-
self
220-
}
221-
222-
/// Set whether HTTP/1 connections will write header names as title case at
223-
/// the socket level.
224-
///
225-
/// Default is false.
226-
pub fn set_title_case_headers(&mut self, title_case_headers: bool) -> &mut Self {
227-
self.server.http1().title_case_headers(title_case_headers);
228-
self
229-
}
230-
231-
/// Set whether to support preserving original header cases.
232-
///
233-
/// Currently, this will record the original cases received, and store them
234-
/// in a private extension on the `Request`. It will also look for and use
235-
/// such an extension in any provided `Response`.
236-
///
237-
/// Since the relevant extension is still private, there is no way to
238-
/// interact with the original cases. The only effect this can have now is
239-
/// to forward the cases in a proxy-like fashion.
240-
///
241-
/// Default is false.
242-
pub fn set_preserve_header_case(&mut self, preserve_header_case: bool) -> &mut Self {
243-
self.server
244-
.http1()
245-
.preserve_header_case(preserve_header_case);
246-
self
247-
}
248-
249202
/// Set the maximum number of headers.
250203
///
251204
/// When a request is received, the parser will reserve a buffer to store headers for optimal
@@ -259,11 +212,60 @@ impl<S, L> Server<S, L> {
259212
/// allocation will occur for each request, and there will be a performance drop of about 5%.
260213
///
261214
/// Default is 100.
215+
#[deprecated(
216+
since = "0.4.0",
217+
note = "`set_max_headers` has been removed into `http1_config`"
218+
)]
219+
#[cfg(feature = "http1")]
262220
pub fn set_max_headers(&mut self, max_headers: usize) -> &mut Self {
263221
self.server.http1().max_headers(max_headers);
264222
self
265223
}
266224

225+
/// Get configuration for http1 part.
226+
#[cfg(feature = "http1")]
227+
pub fn http1_config(&mut self) -> self::protocol::Http1Config<'_> {
228+
self::protocol::Http1Config {
229+
inner: self.server.http1(),
230+
}
231+
}
232+
233+
/// Get configuration for http2 part.
234+
#[cfg(feature = "http2")]
235+
pub fn http2_config(&mut self) -> self::protocol::Http2Config<'_> {
236+
self::protocol::Http2Config {
237+
inner: self.server.http2(),
238+
}
239+
}
240+
241+
/// Make server accept only HTTP/1.
242+
#[cfg(feature = "http1")]
243+
pub fn http1_only(self) -> Self {
244+
Self {
245+
service: self.service,
246+
layer: self.layer,
247+
server: self.server.http1_only(),
248+
config: self.config,
249+
shutdown_hooks: self.shutdown_hooks,
250+
#[cfg(feature = "__tls")]
251+
tls_config: self.tls_config,
252+
}
253+
}
254+
255+
/// Make server accept only HTTP/2.
256+
#[cfg(feature = "http2")]
257+
pub fn http2_only(self) -> Self {
258+
Self {
259+
service: self.service,
260+
layer: self.layer,
261+
server: self.server.http2_only(),
262+
config: self.config,
263+
shutdown_hooks: self.shutdown_hooks,
264+
#[cfg(feature = "__tls")]
265+
tls_config: self.tls_config,
266+
}
267+
}
268+
267269
/// The main entry point for the server.
268270
pub async fn run<MI, B, E>(self, mk_incoming: MI) -> Result<(), BoxError>
269271
where
@@ -437,7 +439,6 @@ async fn serve_conn<S>(
437439
conn_cnt: Arc<AtomicUsize>,
438440
exit_notify: Arc<Notify>,
439441
) where
440-
// S: hyper::service::HttpService<hyper::body::Incoming, ResBody = Body>,
441442
S: hyper::service::Service<HyperRequest, Response = Response> + Unpin,
442443
S::Future: Send + 'static,
443444
S::Error: Error + Send + Sync + 'static,

0 commit comments

Comments
 (0)