Skip to content

Commit ca806bc

Browse files
authored
update repo to fit the current status of rust development (#11)
* update repo to fit the current status of rust development 1, use url crate as a replacement of former one 2, upgrade version of rustls_pemfile to make test run 3, upgrade version of webpki-roots to make test run 4, add no_std build test of no_std target in prepush script * PR fix: 1) add HttpUrl struct to avoid using unwrap and to make things simpler 2) in the examples, use old url with url.set_path instead of use format macro 3) remove extra lines and add comment for the #[allow(dead_code)] * PR fix: 1) use != instead of ne 2) use certain result of host and port as we know the scheme must be http or https 3) add some tests * add ci file * PR fix: fix comments
1 parent eb9b5c1 commit ca806bc

File tree

12 files changed

+217
-450
lines changed

12 files changed

+217
-450
lines changed

.github/workflows/ci.yml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: CI
2+
3+
on: [push, pull_request]
4+
defaults:
5+
run:
6+
shell: bash
7+
8+
jobs:
9+
prepush:
10+
runs-on: ubuntu-latest
11+
container: rust:latest
12+
steps:
13+
- name: Checkout repository
14+
uses: actions/checkout@v2
15+
- name: Install target
16+
run: rustup target add thumbv7m-none-eabi
17+
- name: Run
18+
run: ./prepush

Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ ssl = []
2626
hashbrown = "*"
2727
openssl = { version = "*", optional = true }
2828
rustls = { version = "^0.20.8", optional = true }
29-
webpki-roots = { version = "*", optional = true }
30-
rustls-pemfile = { version = "*", optional = true }
29+
webpki-roots = { version = "^0.26.0", optional = true }
30+
rustls-pemfile = { version = "^2.0.0", optional = true }
3131
native-tls = { version = "*", optional = true }
32+
url = { version = "2.5.3", default-features = false }
3233

3334
[dev-dependencies]
3435
clap = { version = "*", features = ["derive"] }

examples/advance_client.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ use std::net;
33

44
use http_io::client::HttpRequestBuilder;
55
use http_io::error::Result;
6-
use http_io::url::Url;
6+
use http_io::url::HttpUrl;
77

88
fn main() -> Result<()> {
99
let args = std::env::args();
10-
let url: Url = args
10+
let url: HttpUrl = args
1111
.skip(1)
1212
.next()
1313
.unwrap_or("http://www.google.com".into())
1414
.parse()?;
1515

16-
let s = net::TcpStream::connect((url.authority.as_ref(), url.port()?))?;
16+
let s = net::TcpStream::connect((url.host(), url.port()))?;
1717
let mut response = HttpRequestBuilder::get(url)?.send(s)?.finish()?;
1818

1919
println!("{:#?}", response.headers);

examples/connection_reuse.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ use std::io;
55

66
fn main() -> Result<()> {
77
let args = std::env::args();
8-
let url: Url = args
8+
let host = args
99
.skip(1)
1010
.next()
11-
.unwrap_or("http://www.google.com".into())
12-
.parse()?;
11+
.unwrap_or("http://www.google.com".into());
12+
let url = Url::parse(&host)?;
1313

1414
let mut client = HttpClient::<std::net::TcpStream>::new();
1515
for path in &["/", "/favicon.ico", "/robots.txt"] {
1616
let mut url = url.clone();
17-
url.path = path.parse()?;
17+
url.set_path(&path);
1818
io::copy(&mut client.get(url)?.finish()?.body, &mut io::stdout())?;
1919
}
2020

examples/no_std.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ mod no_std {
2323
use http_io::error::{Error, Result};
2424
use http_io::io;
2525
use http_io::protocol::HttpMethod;
26-
use http_io::url::Url;
26+
use http_io::url::HttpUrl;
2727

2828
#[derive(Parser)]
2929
struct Options {
@@ -106,9 +106,9 @@ mod no_std {
106106

107107
// The clap parsing stuff relies on std::error::Error
108108
let method: HttpMethod = opts.method.parse()?;
109-
let url: Url = opts.url.parse()?;
109+
let url: HttpUrl = opts.url.parse()?;
110110

111-
let s = MyFakeTcpStream::connect(url.authority.as_ref(), url.port()?)?;
111+
let s = MyFakeTcpStream::connect(url.host(), url.port())?;
112112

113113
let mut body = match method {
114114
HttpMethod::Get => HttpRequestBuilder::get(url)?.send(s)?.finish()?.body,

prepush

+1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ cargo test --no-default-features --features std,ssl-rustls
1515
cargo run --example readme
1616
cargo run --example connection_reuse
1717
cargo run --example no_std --no-default-features -- http://fake.com
18+
cargo build --target thumbv7m-none-eabi --no-default-features
1819

1920
echo "All tests passed"

src/client.rs

+32-28
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@
2020
//! ```rust
2121
//! use http_io::client::HttpRequestBuilder;
2222
//! use http_io::error::Result;
23-
//! use http_io::url::Url;
23+
//! use http_io::url::HttpUrl;
2424
//! use std::io;
2525
//! use std::net::TcpStream;
2626
//!
2727
//! fn main() -> Result<()> {
28-
//! let url: Url = "http://www.google.com".parse()?;
29-
//! let s = TcpStream::connect((url.authority.as_ref(), url.port()?))?;
30-
//! let mut response = HttpRequestBuilder::get(url)?.send(s)?.finish()?;
28+
//! let http_url: HttpUrl = "http://www.google.com".parse()?;
29+
//! let s = TcpStream::connect((http_url.host(), http_url.port()))?;
30+
//! let mut response = HttpRequestBuilder::get(http_url)?.send(s)?.finish()?;
3131
//! println!("{:#?}", response.headers);
3232
//! io::copy(&mut response.body, &mut io::stdout())?;
3333
//! Ok(())
@@ -41,11 +41,11 @@
4141
//! use std::io;
4242
//!
4343
//! fn main() -> Result<()> {
44-
//! let url: Url = "http://www.google.com".parse()?;
44+
//! let url = Url::parse("http://www.google.com")?;
4545
//! let mut client = HttpClient::<std::net::TcpStream>::new();
4646
//! for path in &["/", "/favicon.ico", "/robots.txt"] {
4747
//! let mut url = url.clone();
48-
//! url.path = path.parse()?;
48+
//! url.set_path(&path);
4949
//! io::copy(&mut client.get(url)?.finish()?.body, &mut io::stdout())?;
5050
//! }
5151
//! Ok(())
@@ -59,7 +59,7 @@ use crate::protocol::{HttpBody, HttpStatus};
5959
use crate::protocol::{HttpMethod, HttpRequest, OutgoingRequest};
6060
#[cfg(feature = "std")]
6161
use crate::url::Scheme;
62-
use crate::url::Url;
62+
use crate::url::{HttpUrl, Url};
6363
#[cfg(not(feature = "std"))]
6464
use alloc::string::{String, ToString as _};
6565
use core::convert::TryInto;
@@ -74,63 +74,63 @@ pub struct HttpRequestBuilder {
7474

7575
impl HttpRequestBuilder {
7676
/// Create a `HttpRequestBuilder` to build a DELETE request
77-
pub fn delete<U: TryInto<Url>>(url: U) -> Result<Self>
77+
pub fn delete<U: TryInto<HttpUrl>>(url: U) -> Result<Self>
7878
where
79-
<U as TryInto<Url>>::Error: Display,
79+
<U as TryInto<HttpUrl>>::Error: Display,
8080
{
8181
HttpRequestBuilder::new(url, HttpMethod::Delete)
8282
}
8383

8484
/// Create a `HttpRequestBuilder` to build a GET request
85-
pub fn get<U: TryInto<Url>>(url: U) -> Result<Self>
85+
pub fn get<U: TryInto<HttpUrl>>(url: U) -> Result<Self>
8686
where
87-
<U as TryInto<Url>>::Error: Display,
87+
<U as TryInto<HttpUrl>>::Error: Display,
8888
{
8989
HttpRequestBuilder::new(url, HttpMethod::Get)
9090
}
9191

9292
/// Create a `HttpRequestBuilder` to build a HEAD request
93-
pub fn head<U: TryInto<Url>>(url: U) -> Result<Self>
93+
pub fn head<U: TryInto<HttpUrl>>(url: U) -> Result<Self>
9494
where
95-
<U as TryInto<Url>>::Error: Display,
95+
<U as TryInto<HttpUrl>>::Error: Display,
9696
{
9797
HttpRequestBuilder::new(url, HttpMethod::Head)
9898
}
9999

100100
/// Create a `HttpRequestBuilder` to build an OPTIONS request
101-
pub fn options<U: TryInto<Url>>(url: U) -> Result<Self>
101+
pub fn options<U: TryInto<HttpUrl>>(url: U) -> Result<Self>
102102
where
103-
<U as TryInto<Url>>::Error: Display,
103+
<U as TryInto<HttpUrl>>::Error: Display,
104104
{
105105
HttpRequestBuilder::new(url, HttpMethod::Options)
106106
}
107107

108108
/// Create a `HttpRequestBuilder` to build a POST request
109-
pub fn post<U: TryInto<Url>>(url: U) -> Result<Self>
109+
pub fn post<U: TryInto<HttpUrl>>(url: U) -> Result<Self>
110110
where
111-
<U as TryInto<Url>>::Error: Display,
111+
<U as TryInto<HttpUrl>>::Error: Display,
112112
{
113113
HttpRequestBuilder::new(url, HttpMethod::Post)
114114
}
115115

116116
/// Create a `HttpRequestBuilder` to build a PUT request
117-
pub fn put<U: TryInto<Url>>(url: U) -> Result<Self>
117+
pub fn put<U: TryInto<HttpUrl>>(url: U) -> Result<Self>
118118
where
119-
<U as TryInto<Url>>::Error: Display,
119+
<U as TryInto<HttpUrl>>::Error: Display,
120120
{
121121
HttpRequestBuilder::new(url, HttpMethod::Put)
122122
}
123123

124124
/// Create a `HttpRequestBuilder`. May fail if the given url does not parse.
125-
pub fn new<U: TryInto<Url>>(url: U, method: HttpMethod) -> Result<Self>
125+
pub fn new<U: TryInto<HttpUrl>>(url: U, method: HttpMethod) -> Result<Self>
126126
where
127-
<U as TryInto<Url>>::Error: Display,
127+
<U as TryInto<HttpUrl>>::Error: Display,
128128
{
129-
let url = url
129+
let url: HttpUrl = url
130130
.try_into()
131131
.map_err(|e| Error::ParseError(e.to_string()))?;
132-
let mut request = HttpRequest::new(method, url.path());
133-
request.add_header("Host", url.authority.clone());
132+
let mut request = HttpRequest::new(method, url.url().path());
133+
request.add_header("Host", url.host().to_string());
134134
request.add_header("User-Agent", "http_io");
135135
request.add_header("Accept", "*/*");
136136
if method.has_body() {
@@ -226,19 +226,23 @@ impl StreamConnector for std::net::TcpStream {
226226
}
227227

228228
fn to_stream_addr(url: Url) -> Result<Self::StreamAddr> {
229+
use core::convert::TryFrom;
230+
231+
let http_url = HttpUrl::try_from(url)?;
229232
let err = || {
230233
std::io::Error::new(
231234
std::io::ErrorKind::AddrNotAvailable,
232-
format!("Failed to lookup {}", &url.authority),
235+
format!("Failed to lookup {}", http_url.host()),
233236
)
234237
};
238+
235239
Ok(StreamId {
236-
addr: std::net::ToSocketAddrs::to_socket_addrs(&(url.authority.as_ref(), url.port()?))
240+
addr: std::net::ToSocketAddrs::to_socket_addrs(&(http_url.host(), http_url.port()))
237241
.map_err(|_| err())?
238242
.next()
239243
.ok_or_else(err)?,
240-
host: url.authority,
241-
secure: url.scheme == Scheme::Https,
244+
host: String::from(http_url.host()),
245+
secure: Scheme::Https.eq(&http_url.scheme()),
242246
})
243247
}
244248
}

src/error.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::protocol::{HttpMethod, HttpStatus};
22
#[cfg(not(feature = "std"))]
3-
use alloc::string::String;
3+
use alloc::string::{String, ToString};
44
use core::fmt;
55
use core::num;
66
use core::str;
@@ -80,3 +80,9 @@ impl From<crate::ssl::Error> for Error {
8080
Self::SslError(e)
8181
}
8282
}
83+
84+
impl From<url::ParseError> for Error {
85+
fn from(e: url::ParseError) -> Self {
86+
Self::ParseError(e.to_string())
87+
}
88+
}

src/server.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
//! Ok(())
6060
//! });
6161
//!
62-
//! let url = format!("http://localhost:{}/src/server.rs", port);
62+
//! let url = format!("http://127.0.0.1:{}/src/server.rs", port);
6363
//! let mut body = http_io::client::get(url.as_ref())?;
6464
//! io::copy(&mut body, &mut std::io::stdout())?;
6565
//! handle.join().unwrap()?;

src/ssl/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// disable false positive of not using the String, the dead code analysis
2+
// intentionally ignore we derive the Debug trait
3+
#[allow(dead_code)]
14
#[derive(Debug)]
25
pub struct Error(String);
36

src/ssl/rustls.rs

+16-20
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,8 @@ use super::{Error, Result};
22
use crate::io;
33
use crate::server::Listen;
44
use std::convert::TryInto as _;
5-
6-
#[cfg(feature = "std")]
75
use std::sync::Arc;
86

9-
#[cfg(not(feature = "std"))]
10-
use alloc::sync::Arc;
11-
127
#[cfg(test)]
138
fn read_test_cert(name: &str) -> Result<Vec<u8>> {
149
use io::Read as _;
@@ -23,20 +18,19 @@ fn read_test_cert(name: &str) -> Result<Vec<u8>> {
2318

2419
fn root_store() -> Result<rustls::RootCertStore> {
2520
let mut root_store = rustls::RootCertStore::empty();
26-
root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
21+
root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| {
2722
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
28-
ta.subject,
29-
ta.spki,
30-
ta.name_constraints,
23+
ta.subject.to_vec(),
24+
ta.subject_public_key_info.to_vec(),
25+
ta.name_constraints.as_ref().map(|c| c.to_vec()),
3126
)
3227
}));
3328

3429
#[cfg(test)]
35-
for c in rustls_pemfile::certs(&mut io::BufReader::new(&read_test_cert("test_ca.pem")?[..]))?
36-
.iter()
37-
.map(|v| rustls::Certificate(v.clone()))
38-
{
39-
root_store.add(&c).map_err(|e| Error(e.to_string()))?;
30+
for c in rustls_pemfile::certs(&mut io::BufReader::new(&read_test_cert("test_ca.pem")?[..])) {
31+
root_store
32+
.add(&rustls::Certificate(c?.to_vec()))
33+
.map_err(|e| Error(e.to_string()))?;
4034
}
4135

4236
Ok(root_store)
@@ -138,13 +132,15 @@ pub struct SslListener<L> {
138132
impl<L: Listen> SslListener<L> {
139133
pub fn new(private_key_pem: &[u8], cert_pem: &[u8], listener: L) -> Result<Self> {
140134
let private_key = rustls::PrivateKey(
141-
rustls_pemfile::pkcs8_private_keys(&mut io::BufReader::new(private_key_pem))?[0]
142-
.clone(),
135+
rustls_pemfile::private_key(&mut io::BufReader::new(private_key_pem))?
136+
.unwrap()
137+
.secret_der()
138+
.to_vec(),
143139
);
144-
let certs = rustls_pemfile::certs(&mut io::BufReader::new(cert_pem))?
145-
.iter()
146-
.map(|v| rustls::Certificate(v.clone()))
147-
.collect();
140+
let mut certs = Vec::new();
141+
for cert in rustls_pemfile::certs(&mut io::BufReader::new(cert_pem)) {
142+
certs.push(rustls::Certificate(cert?.to_vec()));
143+
}
148144

149145
let config = rustls::ServerConfig::builder()
150146
.with_safe_defaults()

0 commit comments

Comments
 (0)