Skip to content

Commit 22f53f9

Browse files
committed
Upgrade hyper to 1.1
1 parent 2ee4d14 commit 22f53f9

File tree

10 files changed

+170
-245
lines changed

10 files changed

+170
-245
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 0.9.0
2+
3+
* upgrade to hyper 1.0
4+
15
# 0.8.0
26

37
* upgrade to tokio 1.0 and hyper 0.14 [#44](https://github.com/softprops/hyperlocal/pull/44)

Cargo.toml

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,53 @@
11
[package]
22
name = "hyperlocal"
3-
version = "0.8.0"
3+
version = "0.9.0-alpha"
44
authors = ["softprops <[email protected]>"]
55
description = "Hyper bindings for Unix domain sockets"
66
homepage = "https://github.com/softprops/hyperlocal"
77
repository = "https://github.com/softprops/hyperlocal"
88
keywords = ["hyper", "unix", "sockets", "http"]
99
license = "MIT"
1010
readme = "README.md"
11-
edition = "2018"
11+
edition = "2021"
1212

1313
[dependencies]
1414
hex = "0.4"
15-
hyper = "0.14"
16-
tokio = { version = "1.0", features = ["net"] }
15+
http-body-util = { version = "0.1", optional = true }
16+
hyper = "1.1"
17+
hyper-util = { version = "0.1.2", optional = true }
18+
tokio = { version = "1.35", default-features = false, features = ["net"] }
19+
tower-service = { version = "0.3", optional = true }
1720
pin-project-lite = "0.2"
1821

1922
[dev-dependencies]
20-
tokio = { version = "1.0", features = ["io-std", "io-util", "macros", "rt-multi-thread"] }
23+
thiserror = "1.0"
24+
tokio = { version = "1.35", features = ["io-std", "io-util", "macros", "rt-multi-thread"] }
2125

2226
[features]
23-
default = []
27+
default = ["client"]
2428
client = [
29+
"http-body-util",
2530
"hyper/client",
2631
"hyper/http1",
32+
"hyper-util/client-legacy",
33+
"hyper-util/http1",
34+
"hyper-util/tokio",
35+
"tower-service"
2736
]
2837
server = [
2938
"hyper/http1",
30-
"hyper/server"
39+
"hyper/server",
40+
"hyper-util/tokio",
3141
]
3242

3343
[[example]]
3444
name = "client"
35-
required-features = ["client", "hyper/runtime"]
45+
required-features = ["client"]
3646

3747
[[example]]
3848
name = "server"
39-
required-features = ["server", "hyper/runtime"]
49+
required-features = ["server"]
4050

4151
[[test]]
4252
name = "server_client"
43-
required-features = ["client", "server", "hyper/runtime"]
53+
required-features = ["client", "server"]

README.md

Lines changed: 10 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -47,47 +47,20 @@ Add the following to your `Cargo.toml` file
4747

4848
```toml
4949
[dependencies]
50-
hyperlocal = "0.8"
50+
hyperlocal = "0.9"
5151
```
5252

5353
## Usage
5454

5555
### Servers
5656

57-
A typical server can be built with `hyperlocal::server::UnixServerExt`.
57+
A typical server can be built by creating a `tokio::net::UnixListener` and accepting connections in a loop using
58+
`hyper::service::service_fn` to create a request/response processing function, and connecting the `UnixStream` to it
59+
using `hyper::server::conn::http1::Builder::new().serve_connection()`.
5860

59-
```rust
60-
use std::{error::Error, fs, path::Path};
61-
use hyper::{
62-
service::{make_service_fn, service_fn},
63-
Body, Response, Server,
64-
};
65-
use hyperlocal::UnixServerExt;
61+
An example is at [examples/server.rs](./examples/server.rs).
6662

67-
const PHRASE: &str = "It's a Unix system. I know this.";
68-
69-
#[tokio::main]
70-
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
71-
let path = Path::new("/tmp/hyperlocal.sock");
72-
73-
if path.exists() {
74-
fs::remove_file(path)?;
75-
}
76-
77-
let make_service = make_service_fn(|_| async {
78-
Ok::<_, hyper::Error>(service_fn(|_req| async {
79-
Ok::<_, hyper::Error>(Response::new(Body::from(PHRASE)))
80-
}))
81-
});
82-
83-
Server::bind_unix(path)?.serve(make_service).await?;
84-
85-
Ok(())
86-
}
87-
88-
```
89-
90-
To test that your server is working you can use an out of the box tool like `curl`
63+
To test that your server is working you can use an out-of-the-box tool like `curl`
9164

9265

9366
```sh
@@ -98,9 +71,10 @@ It's a Unix system. I know this.
9871
9972
### Clients
10073
101-
`hyperlocal` also provides bindings for writing unix domain socket based HTTP clients using `Hyper`'s native `Client` interface.
74+
`hyperlocal` also provides bindings for writing unix domain socket based HTTP clients the `Client` interface from the
75+
`hyper-utils` crate.
10276
103-
Configure your `Hyper` client using `hyper::Client::builder()`.
77+
An example is at [examples/client.rs](./examples/client.rs).
10478
10579
Hyper's client interface makes it easy to send typical HTTP methods like `GET`, `POST`, `DELETE` with factory
10680
methods, `get`, `post`, `delete`, etc. These require an argument that can be tranformed into a `hyper::Uri`.
@@ -109,27 +83,6 @@ Since Unix domain sockets aren't represented with hostnames that resolve to ip a
10983
your standard over the counter URL string won't do. Instead, use a `hyperlocal::Uri`, which represents both file path to the domain
11084
socket and the resource URI path and query string.
11185

112-
```rust
113-
use std::error::Error;
114-
use hyper::{body::HttpBody, Client};
115-
use hyperlocal::{UnixClientExt, Uri};
116-
use tokio::io::{self, AsyncWriteExt as _};
117-
118-
#[tokio::main]
119-
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
120-
let url = Uri::new("/tmp/hyperlocal.sock", "/").into();
121-
122-
let client = Client::unix();
123-
124-
let mut response = client.get(url).await?;
125-
126-
while let Some(next) = response.data().await {
127-
let chunk = next?;
128-
io::stdout().write_all(&chunk).await?;
129-
}
130-
131-
Ok(())
132-
}
133-
```
86+
---
13487

13588
Doug Tangren (softprops) 2015-2020

examples/client.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1-
use hyper::{body::HttpBody, Client};
2-
use hyperlocal::{UnixClientExt, Uri};
1+
use http_body_util::{BodyExt, Full};
2+
use hyper::body::Bytes;
3+
use hyper_util::client::legacy::Client;
4+
use hyperlocal::{UnixClientExt, UnixConnector, Uri};
35
use std::error::Error;
46
use tokio::io::{self, AsyncWriteExt as _};
57

68
#[tokio::main]
79
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
810
let url = Uri::new("/tmp/hyperlocal.sock", "/").into();
911

10-
let client = Client::unix();
12+
let client: Client<UnixConnector, Full<Bytes>> = Client::unix();
1113

1214
let mut response = client.get(url).await?;
1315

14-
while let Some(next) = response.data().await {
15-
let chunk = next?;
16-
io::stdout().write_all(&chunk).await?;
16+
while let Some(frame_result) = response.frame().await {
17+
let frame = frame_result?;
18+
19+
if let Some(segment) = frame.data_ref() {
20+
io::stdout().write_all(segment.iter().as_slice()).await?;
21+
}
1722
}
1823

1924
Ok(())

examples/server.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
use hyper::{
2-
service::{make_service_fn, service_fn},
3-
Body, Response, Server,
4-
};
5-
use hyperlocal::UnixServerExt;
1+
use hyper::{service::service_fn, Response};
2+
use hyper_util::rt::TokioIo;
63
use std::{error::Error, fs, path::Path};
4+
use tokio::net::UnixListener;
75

86
const PHRASE: &str = "It's a Unix system. I know this.";
97

8+
// Adapted from https://hyper.rs/guides/1/server/hello-world/
109
#[tokio::main]
1110
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
1211
let path = Path::new("/tmp/hyperlocal.sock");
@@ -15,13 +14,29 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
1514
fs::remove_file(path)?;
1615
}
1716

18-
let make_service = make_service_fn(|_| async {
19-
Ok::<_, hyper::Error>(service_fn(|_req| async {
20-
Ok::<_, hyper::Error>(Response::new(Body::from(PHRASE)))
21-
}))
22-
});
17+
let listener = UnixListener::bind(path)?;
2318

24-
Server::bind_unix(path)?.serve(make_service).await?;
19+
loop {
20+
let (stream, _) = listener.accept().await?;
21+
let io = TokioIo::new(stream);
2522

26-
Ok(())
23+
tokio::task::spawn(async move {
24+
let svc_fn = service_fn(|_req| async {
25+
let body = PHRASE.to_string();
26+
Ok::<_, hyper::Error>(Response::new(body))
27+
});
28+
29+
match hyper::server::conn::http1::Builder::new()
30+
.serve_connection(io, svc_fn)
31+
.await
32+
{
33+
Ok(()) => {
34+
println!("Accepted connection.");
35+
}
36+
Err(err) => {
37+
eprintln!("Failed to accept connection: {err:?}");
38+
}
39+
};
40+
});
41+
}
2742
}

src/client.rs

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
use hex::FromHex;
2-
use hyper::{
3-
client::connect::{Connected, Connection},
4-
service::Service,
5-
Body, Client, Uri,
2+
use hyper::{body::Body, rt::ReadBufCursor, Uri};
3+
use hyper_util::{
4+
client::legacy::{
5+
connect::{Connected, Connection},
6+
Client,
7+
},
8+
rt::{TokioExecutor, TokioIo},
69
};
710
use pin_project_lite::pin_project;
811
use std::{
912
future::Future,
1013
io,
14+
io::Error,
1115
path::{Path, PathBuf},
1216
pin::Pin,
1317
task::{Context, Poll},
1418
};
15-
use tokio::io::ReadBuf;
19+
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
20+
use tower_service::Service;
1621

1722
pin_project! {
1823
#[derive(Debug)]
@@ -29,7 +34,7 @@ impl UnixStream {
2934
}
3035
}
3136

32-
impl tokio::io::AsyncWrite for UnixStream {
37+
impl AsyncWrite for UnixStream {
3338
fn poll_write(
3439
self: Pin<&mut Self>,
3540
cx: &mut Context<'_>,
@@ -47,7 +52,25 @@ impl tokio::io::AsyncWrite for UnixStream {
4752
}
4853
}
4954

50-
impl tokio::io::AsyncRead for UnixStream {
55+
impl hyper::rt::Write for UnixStream {
56+
fn poll_write(
57+
self: Pin<&mut Self>,
58+
cx: &mut Context<'_>,
59+
buf: &[u8],
60+
) -> Poll<Result<usize, Error>> {
61+
self.project().unix_stream.poll_write(cx, buf)
62+
}
63+
64+
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
65+
self.project().unix_stream.poll_flush(cx)
66+
}
67+
68+
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
69+
self.project().unix_stream.poll_shutdown(cx)
70+
}
71+
}
72+
73+
impl AsyncRead for UnixStream {
5174
fn poll_read(
5275
self: Pin<&mut Self>,
5376
cx: &mut Context<'_>,
@@ -57,16 +80,30 @@ impl tokio::io::AsyncRead for UnixStream {
5780
}
5881
}
5982

83+
impl hyper::rt::Read for UnixStream {
84+
fn poll_read(
85+
self: Pin<&mut Self>,
86+
cx: &mut Context<'_>,
87+
buf: ReadBufCursor<'_>,
88+
) -> Poll<Result<(), Error>> {
89+
let mut t = TokioIo::new(self.project().unix_stream);
90+
Pin::new(&mut t).poll_read(cx, buf)
91+
}
92+
}
93+
6094
/// the `[UnixConnector]` can be used to construct a `[hyper::Client]` which can
6195
/// speak to a unix domain socket.
6296
///
6397
/// # Example
6498
/// ```
65-
/// use hyper::{Client, Body};
99+
/// use http_body_util::Full;
100+
/// use hyper::body::Bytes;
101+
/// use hyper_util::client::legacy::Client;
102+
/// use hyper_util::rt::TokioExecutor;
66103
/// use hyperlocal::UnixConnector;
67104
///
68105
/// let connector = UnixConnector;
69-
/// let client: Client<UnixConnector, Body> = Client::builder().build(connector);
106+
/// let client: Client<UnixConnector, Full<Bytes>> = Client::builder(TokioExecutor::new()).build(connector);
70107
/// ```
71108
///
72109
/// # Note
@@ -129,22 +166,27 @@ fn parse_socket_path(uri: &Uri) -> Result<PathBuf, io::Error> {
129166
}
130167
}
131168

132-
/// Extention trait for constructing a hyper HTTP client over a Unix domain
169+
/// Extension trait for constructing a hyper HTTP client over a Unix domain
133170
/// socket.
134-
pub trait UnixClientExt {
171+
pub trait UnixClientExt<B: Body + Send> {
135172
/// Construct a client which speaks HTTP over a Unix domain socket
136173
///
137174
/// # Example
138175
/// ```
139-
/// use hyper::Client;
140-
/// use hyperlocal::UnixClientExt;
176+
/// use http_body_util::Full;
177+
/// use hyper::body::Bytes;
178+
/// use hyper_util::client::legacy::Client;
179+
/// use hyperlocal::{UnixClientExt, UnixConnector};
141180
///
142-
/// let client = Client::unix();
181+
/// let client: Client<UnixConnector, Full<Bytes>> = Client::unix();
143182
/// ```
144183
#[must_use]
145-
fn unix() -> Client<UnixConnector, Body> {
146-
Client::builder().build(UnixConnector)
184+
fn unix() -> Client<UnixConnector, B>
185+
where
186+
B::Data: Send,
187+
{
188+
Client::builder(TokioExecutor::new()).build(UnixConnector)
147189
}
148190
}
149191

150-
impl UnixClientExt for Client<UnixConnector> {}
192+
impl<B: Body + Send> UnixClientExt<B> for Client<UnixConnector, B> {}

0 commit comments

Comments
 (0)