Skip to content

Commit 2601cbb

Browse files
authored
Merge pull request #48 from yoshuawuyts/fix-warnings
Migrate to new error types
2 parents 8339bd6 + 876d996 commit 2601cbb

File tree

8 files changed

+82
-80
lines changed

8 files changed

+82
-80
lines changed

examples/client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use async_h1::client;
55
use async_std::io::{self, Read, Write};
66
use async_std::net::{self, TcpStream};
77
use async_std::task::{self, Context, Poll};
8-
use http_types::{Method, Request, Url};
8+
use http_types::{Error, Method, Request, Url};
99

10-
fn main() -> Result<(), async_h1::Exception> {
10+
fn main() -> Result<(), Error> {
1111
task::block_on(async {
1212
let stream = net::TcpStream::connect("127.0.0.1:8080").await?;
1313
let peer_addr = stream.peer_addr()?;

examples/server.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ use async_std::net::{self, TcpStream};
88
use async_std::prelude::*;
99
use async_std::task::{self, Context, Poll};
1010
use http_types::headers::{HeaderName, HeaderValue};
11-
use http_types::{Response, StatusCode};
11+
use http_types::{Error, Response, StatusCode};
1212

13-
async fn accept(addr: String, stream: TcpStream) -> Result<(), async_h1::Exception> {
13+
async fn accept(addr: String, stream: TcpStream) -> Result<(), Error> {
1414
// println!("starting new connection from {}", stream.peer_addr()?);
1515

1616
// TODO: Delete this line when we implement `Clone` for `TcpStream`.
@@ -35,7 +35,7 @@ async fn accept(addr: String, stream: TcpStream) -> Result<(), async_h1::Excepti
3535
.await
3636
}
3737

38-
fn main() -> Result<(), async_h1::Exception> {
38+
fn main() -> Result<(), Error> {
3939
task::block_on(async {
4040
let listener = net::TcpListener::bind(("127.0.0.1", 8080)).await?;
4141
let addr = format!("http://{}", listener.local_addr()?);

src/client.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ use http_types::{
88
headers::{HeaderName, HeaderValue, CONTENT_LENGTH, DATE, TRANSFER_ENCODING},
99
Body, Request, Response, StatusCode,
1010
};
11+
use http_types::{Error, ErrorKind};
1112

1213
use std::pin::Pin;
1314
use std::str::FromStr;
1415

1516
use crate::chunked::ChunkedDecoder;
1617
use crate::date::fmt_http_date;
17-
use crate::error::HttpError;
18-
use crate::{Exception, MAX_HEADERS};
18+
use crate::MAX_HEADERS;
1919

2020
/// An HTTP encoder.
2121
#[derive(Debug)]
@@ -98,7 +98,7 @@ pub async fn encode(req: Request) -> Result<Encoder, std::io::Error> {
9898
}
9999

100100
/// Decode an HTTP response on the client.
101-
pub async fn decode<R>(reader: R) -> Result<Response, Exception>
101+
pub async fn decode<R>(reader: R) -> Result<Response, Error>
102102
where
103103
R: Read + Unpin + Send + Sync + 'static,
104104
{
@@ -125,15 +125,34 @@ where
125125
// Convert our header buf into an httparse instance, and validate.
126126
let status = httparse_res.parse(&buf)?;
127127
if status.is_partial() {
128-
dbg!(String::from_utf8(buf).unwrap());
129-
return Err("Malformed HTTP head".into());
128+
return Err(Error::from_str(
129+
ErrorKind::InvalidData,
130+
"Malformed HTTP head",
131+
StatusCode::BadRequest,
132+
));
130133
}
131-
let code = httparse_res.code.ok_or_else(|| "No status code found")?;
134+
let code = httparse_res.code.ok_or_else(|| {
135+
Error::from_str(
136+
ErrorKind::InvalidData,
137+
"No status code found",
138+
StatusCode::BadRequest,
139+
)
140+
})?;
132141

133142
// Convert httparse headers + body into a `http::Response` type.
134-
let version = httparse_res.version.ok_or_else(|| "No version found")?;
143+
let version = httparse_res.version.ok_or_else(|| {
144+
Error::from_str(
145+
ErrorKind::InvalidData,
146+
"No version found",
147+
StatusCode::BadRequest,
148+
)
149+
})?;
135150
if version != 1 {
136-
return Err("Unsupported HTTP version".into());
151+
return Err(Error::from_str(
152+
ErrorKind::InvalidData,
153+
"Unsupported HTTP version",
154+
StatusCode::BadRequest,
155+
));
137156
}
138157
use std::convert::TryFrom;
139158
let mut res = Response::new(StatusCode::try_from(code)?);
@@ -153,7 +172,11 @@ where
153172

154173
if content_length.is_some() && transfer_encoding.is_some() {
155174
// This is always an error.
156-
return Err(HttpError::UnexpectedContentLengthHeader.into());
175+
return Err(Error::from_str(
176+
ErrorKind::InvalidData,
177+
"Unexpected Content-Length header",
178+
StatusCode::BadRequest,
179+
));
157180
}
158181

159182
// Check for Transfer-Encoding

src/date.rs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
use crate::Exception;
21
use std::fmt::{self, Display, Formatter};
32
use std::str::{from_utf8, FromStr};
43
use std::time::{Duration, SystemTime, UNIX_EPOCH};
54

5+
use http_types::{Error, ErrorKind, StatusCode};
6+
67
const IMF_FIXDATE_LENGTH: usize = 29;
78
const RFC850_MAX_LENGTH: usize = 23;
89
const ASCTIME_LENGTH: usize = 24;
@@ -37,7 +38,7 @@ pub struct HttpDate {
3738
/// Supports the preferred IMF-fixdate and the legacy RFC 805 and
3839
/// ascdate formats. Two digit years are mapped to dates between
3940
/// 1970 and 2069.
40-
pub(crate) fn parse_http_date(s: &str) -> Result<SystemTime, Exception> {
41+
pub(crate) fn parse_http_date(s: &str) -> Result<SystemTime, Error> {
4142
s.parse::<HttpDate>().map(|d| d.into())
4243
}
4344

@@ -64,15 +65,19 @@ impl HttpDate {
6465
}
6566
}
6667

67-
fn parse_imf_fixdate(s: &[u8]) -> Result<HttpDate, Exception> {
68+
fn err(msg: &'static str) -> Error {
69+
Error::from_str(ErrorKind::InvalidData, msg, StatusCode::BadRequest)
70+
}
71+
72+
fn parse_imf_fixdate(s: &[u8]) -> Result<HttpDate, Error> {
6873
// Example: `Sun, 06 Nov 1994 08:49:37 GMT`
6974
if s.len() != IMF_FIXDATE_LENGTH
7075
|| &s[25..] != b" GMT"
7176
|| s[16] != b' '
7277
|| s[19] != b':'
7378
|| s[22] != b':'
7479
{
75-
return Err("Date time not in imf fixdate format".into());
80+
return Err(err("Date time not in imf fixdate format"));
7681
}
7782
Ok(HttpDate {
7883
second: from_utf8(&s[23..25])?.parse()?,
@@ -92,7 +97,7 @@ fn parse_imf_fixdate(s: &[u8]) -> Result<HttpDate, Exception> {
9297
b" Oct " => 10,
9398
b" Nov " => 11,
9499
b" Dec " => 12,
95-
_ => return Err("Invalid Month".into()),
100+
_ => return Err(err("Invalid Month")),
96101
},
97102
year: from_utf8(&s[12..16])?.parse()?,
98103
week_day: match &s[..5] {
@@ -103,15 +108,15 @@ fn parse_imf_fixdate(s: &[u8]) -> Result<HttpDate, Exception> {
103108
b"Fri, " => 5,
104109
b"Sat, " => 6,
105110
b"Sun, " => 7,
106-
_ => return Err("Invalid Day".into()),
111+
_ => return Err(err("Invalid Day")),
107112
},
108113
})
109114
}
110115

111-
fn parse_rfc850_date(s: &[u8]) -> Result<HttpDate, Exception> {
116+
fn parse_rfc850_date(s: &[u8]) -> Result<HttpDate, Error> {
112117
// Example: `Sunday, 06-Nov-94 08:49:37 GMT`
113118
if s.len() < RFC850_MAX_LENGTH {
114-
return Err("Date time not in rfc850 format".into());
119+
return Err(err("Date time not in rfc850 format"));
115120
}
116121

117122
fn week_day<'a>(s: &'a [u8], week_day: u8, name: &'static [u8]) -> Option<(u8, &'a [u8])> {
@@ -127,9 +132,9 @@ fn parse_rfc850_date(s: &[u8]) -> Result<HttpDate, Exception> {
127132
.or_else(|| week_day(s, 5, b"Friday, "))
128133
.or_else(|| week_day(s, 6, b"Saturday, "))
129134
.or_else(|| week_day(s, 7, b"Sunday, "))
130-
.ok_or::<&'static str>("Invalid day")?;
135+
.ok_or_else(|| err("Invalid day"))?;
131136
if s.len() != 22 || s[12] != b':' || s[15] != b':' || &s[18..22] != b" GMT" {
132-
return Err("Date time not in rfc850 format".into());
137+
return Err(err("Date time not in rfc850 format"));
133138
}
134139
let mut year = from_utf8(&s[7..9])?.parse::<u16>()?;
135140
if year < 70 {
@@ -155,18 +160,18 @@ fn parse_rfc850_date(s: &[u8]) -> Result<HttpDate, Exception> {
155160
b"-Oct-" => 10,
156161
b"-Nov-" => 11,
157162
b"-Dec-" => 12,
158-
_ => return Err("Invalid month".into()),
163+
_ => return Err(err("Invalid month")),
159164
},
160165
year: year,
161166
week_day: week_day,
162167
})
163168
}
164169

165-
fn parse_asctime(s: &[u8]) -> Result<HttpDate, Exception> {
170+
fn parse_asctime(s: &[u8]) -> Result<HttpDate, Error> {
166171
// Example: `Sun Nov 6 08:49:37 1994`
167172
if s.len() != ASCTIME_LENGTH || s[10] != b' ' || s[13] != b':' || s[16] != b':' || s[19] != b' '
168173
{
169-
return Err("Date time not in asctime format".into());
174+
return Err(err("Date time not in asctime format"));
170175
}
171176
Ok(HttpDate {
172177
second: from_utf8(&s[17..19])?.parse()?,
@@ -189,7 +194,7 @@ fn parse_asctime(s: &[u8]) -> Result<HttpDate, Exception> {
189194
b"Oct " => 10,
190195
b"Nov " => 11,
191196
b"Dec " => 12,
192-
_ => return Err("Invalid month".into()),
197+
_ => return Err(err("Invalid month")),
193198
},
194199
year: from_utf8(&s[20..24])?.parse()?,
195200
week_day: match &s[0..4] {
@@ -200,7 +205,7 @@ fn parse_asctime(s: &[u8]) -> Result<HttpDate, Exception> {
200205
b"Fri " => 5,
201206
b"Sat " => 6,
202207
b"Sun " => 7,
203-
_ => return Err("Invalid day".into()),
208+
_ => return Err(err("Invalid day")),
204209
},
205210
})
206211
}
@@ -323,18 +328,18 @@ impl From<HttpDate> for SystemTime {
323328
}
324329

325330
impl FromStr for HttpDate {
326-
type Err = Exception;
331+
type Err = Error;
327332

328333
fn from_str(s: &str) -> Result<Self, Self::Err> {
329334
if !s.is_ascii() {
330-
return Err("Not ascii".into());
335+
return Err(err("Not ascii"));
331336
}
332337
let x = s.trim().as_bytes();
333338
let date = parse_imf_fixdate(x)
334339
.or_else(|_| parse_rfc850_date(x))
335340
.or_else(|_| parse_asctime(x))?;
336341
if !date.is_valid() {
337-
return Err("Invalid date time".into());
342+
return Err(err("Invalid date time"));
338343
}
339344
Ok(date)
340345
}

src/error.rs

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/lib.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,9 @@ const MAX_HEADERS: usize = 128;
3939
pub use check::check;
4040

4141
mod check;
42-
mod error;
43-
44-
pub use crate::error::HttpError;
4542

4643
pub mod client;
4744
pub mod server;
4845

4946
mod chunked;
5047
mod date;
51-
52-
/// A generic fallible type.
53-
pub type Exception = Box<dyn std::error::Error + Send + Sync + 'static>;

src/server.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,23 @@ use async_std::prelude::*;
1111
use async_std::task::{Context, Poll};
1212
use futures_core::ready;
1313
use http_types::headers::{HeaderName, HeaderValue, CONTENT_LENGTH, TRANSFER_ENCODING};
14-
use http_types::{Body, Method, Request, Response};
14+
use http_types::{Body, Error, ErrorKind, Method, Request, Response, StatusCode};
1515

1616
use crate::chunked::ChunkedDecoder;
1717
use crate::date::fmt_http_date;
18-
use crate::error::HttpError;
19-
use crate::{Exception, MAX_HEADERS};
18+
use crate::MAX_HEADERS;
2019

2120
const CR: u8 = b'\r';
2221
const LF: u8 = b'\n';
2322

2423
/// Parse an incoming HTTP connection.
2524
///
2625
/// Supports `KeepAlive` requests by default.
27-
pub async fn accept<RW, F, Fut>(addr: &str, mut io: RW, endpoint: F) -> Result<(), Exception>
26+
pub async fn accept<RW, F, Fut>(addr: &str, mut io: RW, endpoint: F) -> http_types::Result<()>
2827
where
2928
RW: Read + Write + Clone + Send + Sync + Unpin + 'static,
3029
F: Fn(Request) -> Fut,
31-
Fut: Future<Output = Result<Response, Exception>>,
30+
Fut: Future<Output = Result<Response, Error>>,
3231
{
3332
// TODO: make configurable
3433
let timeout_duration = Duration::from_secs(10);
@@ -56,7 +55,7 @@ where
5655
req = match timeout(timeout_duration, decode(addr, io.clone())).await {
5756
Ok(Ok(Some(r))) => r,
5857
Ok(Ok(None)) | Err(TimeoutError { .. }) => break, /* EOF or timeout */
59-
Ok(Err(e)) => return Err(e),
58+
Ok(Err(e)) => return Err(e).into(),
6059
};
6160
// Loop back with the new request and stream and start again
6261
}
@@ -336,7 +335,7 @@ impl Read for Encoder {
336335
const HTTP_1_1_VERSION: u8 = 1;
337336

338337
/// Decode an HTTP request on the server.
339-
async fn decode<R>(addr: &str, reader: R) -> Result<Option<Request>, Exception>
338+
async fn decode<R>(addr: &str, reader: R) -> Result<Option<Request>, Error>
340339
where
341340
R: Read + Unpin + Send + Sync + 'static,
342341
{
@@ -362,18 +361,23 @@ where
362361

363362
// Convert our header buf into an httparse instance, and validate.
364363
let status = httparse_req.parse(&buf)?;
364+
365+
let err = |msg| Error::from_str(ErrorKind::InvalidData, msg, StatusCode::BadRequest);
366+
365367
if status.is_partial() {
366-
return Err("Malformed HTTP head".into());
368+
return Err(err("Malformed HTTP head"));
367369
}
368370

369371
// Convert httparse headers + body into a `http::Request` type.
370-
let method = httparse_req.method.ok_or_else(|| "No method found")?;
371-
let uri = httparse_req.path.ok_or_else(|| "No uri found")?;
372+
let method = httparse_req.method.ok_or_else(|| err("No method found"))?;
373+
let uri = httparse_req.path.ok_or_else(|| err("No uri found"))?;
372374
let uri = url::Url::parse(&format!("{}{}", addr, uri))?;
373375

374-
let version = httparse_req.version.ok_or_else(|| "No version found")?;
376+
let version = httparse_req
377+
.version
378+
.ok_or_else(|| err("No version found"))?;
375379
if version != HTTP_1_1_VERSION {
376-
return Err("Unsupported HTTP version".into());
380+
return Err(err("Unsupported HTTP version"));
377381
}
378382

379383
let mut req = Request::new(Method::from_str(method)?, uri);
@@ -388,7 +392,11 @@ where
388392

389393
if content_length.is_some() && transfer_encoding.is_some() {
390394
// This is always an error.
391-
return Err(HttpError::UnexpectedContentLengthHeader.into());
395+
return Err(Error::from_str(
396+
ErrorKind::InvalidData,
397+
"Unexpected Content-Length header",
398+
StatusCode::BadRequest,
399+
));
392400
}
393401

394402
// Check for Transfer-Encoding

tests/common/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ impl TestCase {
6363
expected
6464
}
6565

66-
pub async fn assert(self) {
66+
pub(crate) async fn assert(self) {
6767
let mut actual = self.read_result().await;
6868
let mut expected = self.read_expected().await;
6969
assert!(!actual.is_empty(), "Received empty reply");

0 commit comments

Comments
 (0)