Skip to content

Commit 6279168

Browse files
committed
Upgrade to new http_types::Error type
1 parent 48aae50 commit 6279168

File tree

3 files changed

+52
-93
lines changed

3 files changed

+52
-93
lines changed

src/client.rs

Lines changed: 22 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ use async_std::io::{self, BufReader, Read, Write};
44
use async_std::prelude::*;
55
use async_std::task::{Context, Poll};
66
use futures_core::ready;
7+
use http_types::Error;
78
use http_types::{
89
headers::{HeaderName, HeaderValue, CONTENT_LENGTH, DATE, TRANSFER_ENCODING},
910
Body, Request, Response, StatusCode,
1011
};
11-
use http_types::{Error, ErrorKind};
1212

13+
use std::convert::TryFrom;
1314
use std::pin::Pin;
1415
use std::str::FromStr;
1516

@@ -50,7 +51,7 @@ impl Encoder {
5051
}
5152

5253
/// Opens an HTTP/1.1 connection to a remote host.
53-
pub async fn connect<RW>(mut stream: RW, req: Request) -> Result<Response, Error>
54+
pub async fn connect<RW>(mut stream: RW, req: Request) -> http_types::Result<Response>
5455
where
5556
RW: Read + Write + Send + Sync + Unpin + 'static,
5657
{
@@ -67,7 +68,7 @@ where
6768

6869
/// Encode an HTTP request on the client.
6970
#[doc(hidden)]
70-
async fn encode(req: Request) -> Result<Encoder, Error> {
71+
async fn encode(req: Request) -> http_types::Result<Encoder> {
7172
let mut buf: Vec<u8> = vec![];
7273

7374
let mut url = req.url().path().to_owned();
@@ -86,13 +87,10 @@ async fn encode(req: Request) -> Result<Encoder, Error> {
8687

8788
// Insert Host header
8889
// Insert host
89-
let host = req.url().host_str().ok_or_else(|| {
90-
Error::from_str(
91-
ErrorKind::InvalidInput,
92-
"missing hostname",
93-
StatusCode::BadRequest,
94-
)
95-
})?;
90+
let host = req
91+
.url()
92+
.host_str()
93+
.ok_or_else(|| http_types::format_err!("Missing hostname"))?;
9694
let val = if let Some(port) = req.url().port() {
9795
format!("host: {}:{}\r\n", host, port)
9896
} else {
@@ -148,9 +146,7 @@ where
148146
loop {
149147
let bytes_read = reader.read_until(b'\n', &mut buf).await?;
150148
// No more bytes are yielded from the stream.
151-
if bytes_read == 0 {
152-
panic!("empty response");
153-
}
149+
assert_eq!(bytes_read, 0, "Empty response"); // TODO: ensure_eq?
154150

155151
// We've hit the end delimiter of the stream.
156152
let idx = buf.len() - 1;
@@ -161,37 +157,17 @@ where
161157

162158
// Convert our header buf into an httparse instance, and validate.
163159
let status = httparse_res.parse(&buf)?;
164-
if status.is_partial() {
165-
return Err(Error::from_str(
166-
ErrorKind::InvalidData,
167-
"Malformed HTTP head",
168-
StatusCode::BadRequest,
169-
));
170-
}
171-
let code = httparse_res.code.ok_or_else(|| {
172-
Error::from_str(
173-
ErrorKind::InvalidData,
174-
"No status code found",
175-
StatusCode::BadRequest,
176-
)
177-
})?;
160+
http_types::ensure!(!status.is_partial(), "Malformed HTTP head");
161+
162+
let code = httparse_res.code;
163+
let code = code.ok_or_else(|| http_types::format_err!("No status code found"))?;
178164

179165
// Convert httparse headers + body into a `http::Response` type.
180-
let version = httparse_res.version.ok_or_else(|| {
181-
Error::from_str(
182-
ErrorKind::InvalidData,
183-
"No version found",
184-
StatusCode::BadRequest,
185-
)
186-
})?;
187-
if version != 1 {
188-
return Err(Error::from_str(
189-
ErrorKind::InvalidData,
190-
"Unsupported HTTP version",
191-
StatusCode::BadRequest,
192-
));
193-
}
194-
use std::convert::TryFrom;
166+
let version = httparse_res.version;
167+
let version = version.ok_or_else(|| http_types::format_err!("No version found"))?;
168+
169+
http_types::ensure!(version == 1, "Unsupported HTTP version");
170+
195171
let mut res = Response::new(StatusCode::try_from(code)?);
196172
for header in httparse_res.headers.iter() {
197173
let name = HeaderName::from_str(header.name)?;
@@ -207,14 +183,10 @@ where
207183
let content_length = res.header(&CONTENT_LENGTH);
208184
let transfer_encoding = res.header(&TRANSFER_ENCODING);
209185

210-
if content_length.is_some() && transfer_encoding.is_some() {
211-
// This is always an error.
212-
return Err(Error::from_str(
213-
ErrorKind::InvalidData,
214-
"Unexpected Content-Length header",
215-
StatusCode::BadRequest,
216-
));
217-
}
186+
http_types::ensure!(
187+
content_length.is_some() && transfer_encoding.is_some(),
188+
"Unexpected Content-Length header"
189+
);
218190

219191
// Check for Transfer-Encoding
220192
match transfer_encoding {

src/date.rs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::fmt::{self, Display, Formatter};
22
use std::str::{from_utf8, FromStr};
33
use std::time::{Duration, SystemTime, UNIX_EPOCH};
44

5-
use http_types::{Error, ErrorKind, StatusCode};
5+
use http_types::{bail, ensure, format_err, Error};
66

77
const IMF_FIXDATE_LENGTH: usize = 29;
88
const RFC850_MAX_LENGTH: usize = 23;
@@ -66,10 +66,6 @@ impl HttpDate {
6666
}
6767
}
6868

69-
fn err(msg: &'static str) -> Error {
70-
Error::from_str(ErrorKind::InvalidData, msg, StatusCode::BadRequest)
71-
}
72-
7369
fn parse_imf_fixdate(s: &[u8]) -> Result<HttpDate, Error> {
7470
// Example: `Sun, 06 Nov 1994 08:49:37 GMT`
7571
if s.len() != IMF_FIXDATE_LENGTH
@@ -78,7 +74,7 @@ fn parse_imf_fixdate(s: &[u8]) -> Result<HttpDate, Error> {
7874
|| s[19] != b':'
7975
|| s[22] != b':'
8076
{
81-
return Err(err("Date time not in imf fixdate format"));
77+
bail!("Date time not in imf fixdate format");
8278
}
8379
Ok(HttpDate {
8480
second: from_utf8(&s[23..25])?.parse()?,
@@ -98,7 +94,7 @@ fn parse_imf_fixdate(s: &[u8]) -> Result<HttpDate, Error> {
9894
b" Oct " => 10,
9995
b" Nov " => 11,
10096
b" Dec " => 12,
101-
_ => return Err(err("Invalid Month")),
97+
_ => bail!("Invalid Month"),
10298
},
10399
year: from_utf8(&s[12..16])?.parse()?,
104100
week_day: match &s[..5] {
@@ -109,16 +105,17 @@ fn parse_imf_fixdate(s: &[u8]) -> Result<HttpDate, Error> {
109105
b"Fri, " => 5,
110106
b"Sat, " => 6,
111107
b"Sun, " => 7,
112-
_ => return Err(err("Invalid Day")),
108+
_ => bail!("Invalid Day"),
113109
},
114110
})
115111
}
116112

117113
fn parse_rfc850_date(s: &[u8]) -> Result<HttpDate, Error> {
118114
// Example: `Sunday, 06-Nov-94 08:49:37 GMT`
119-
if s.len() < RFC850_MAX_LENGTH {
120-
return Err(err("Date time not in rfc850 format"));
121-
}
115+
ensure!(
116+
s.len() < RFC850_MAX_LENGTH,
117+
"Date time not in rfc850 format"
118+
);
122119

123120
fn week_day<'a>(s: &'a [u8], week_day: u8, name: &'static [u8]) -> Option<(u8, &'a [u8])> {
124121
if &s[0..name.len()] == name {
@@ -133,9 +130,9 @@ fn parse_rfc850_date(s: &[u8]) -> Result<HttpDate, Error> {
133130
.or_else(|| week_day(s, 5, b"Friday, "))
134131
.or_else(|| week_day(s, 6, b"Saturday, "))
135132
.or_else(|| week_day(s, 7, b"Sunday, "))
136-
.ok_or_else(|| err("Invalid day"))?;
133+
.ok_or_else(|| format_err!("Invalid day"))?;
137134
if s.len() != 22 || s[12] != b':' || s[15] != b':' || &s[18..22] != b" GMT" {
138-
return Err(err("Date time not in rfc850 format"));
135+
bail!("Date time not in rfc950 fmt");
139136
}
140137
let mut year = from_utf8(&s[7..9])?.parse::<u16>()?;
141138
if year < 70 {
@@ -161,7 +158,7 @@ fn parse_rfc850_date(s: &[u8]) -> Result<HttpDate, Error> {
161158
b"-Oct-" => 10,
162159
b"-Nov-" => 11,
163160
b"-Dec-" => 12,
164-
_ => return Err(err("Invalid month")),
161+
_ => bail!("Invalid month"),
165162
},
166163
year: year,
167164
week_day: week_day,
@@ -172,7 +169,7 @@ fn parse_asctime(s: &[u8]) -> Result<HttpDate, Error> {
172169
// Example: `Sun Nov 6 08:49:37 1994`
173170
if s.len() != ASCTIME_LENGTH || s[10] != b' ' || s[13] != b':' || s[16] != b':' || s[19] != b' '
174171
{
175-
return Err(err("Date time not in asctime format"));
172+
bail!("Date time not in asctime format");
176173
}
177174
Ok(HttpDate {
178175
second: from_utf8(&s[17..19])?.parse()?,
@@ -195,7 +192,7 @@ fn parse_asctime(s: &[u8]) -> Result<HttpDate, Error> {
195192
b"Oct " => 10,
196193
b"Nov " => 11,
197194
b"Dec " => 12,
198-
_ => return Err(err("Invalid month")),
195+
_ => bail!("Invalid month"),
199196
},
200197
year: from_utf8(&s[20..24])?.parse()?,
201198
week_day: match &s[0..4] {
@@ -206,7 +203,7 @@ fn parse_asctime(s: &[u8]) -> Result<HttpDate, Error> {
206203
b"Fri " => 5,
207204
b"Sat " => 6,
208205
b"Sun " => 7,
209-
_ => return Err(err("Invalid day")),
206+
_ => bail!("Invalid day"),
210207
},
211208
})
212209
}
@@ -332,16 +329,12 @@ impl FromStr for HttpDate {
332329
type Err = Error;
333330

334331
fn from_str(s: &str) -> Result<Self, Self::Err> {
335-
if !s.is_ascii() {
336-
return Err(err("Not ascii"));
337-
}
332+
ensure!(s.is_ascii(), "String slice is not valid ASCII");
338333
let x = s.trim().as_bytes();
339334
let date = parse_imf_fixdate(x)
340335
.or_else(|_| parse_rfc850_date(x))
341336
.or_else(|_| parse_asctime(x))?;
342-
if !date.is_valid() {
343-
return Err(err("Invalid date time"));
344-
}
337+
ensure!(date.is_valid(), "Invalid date time");
345338
Ok(date)
346339
}
347340
}

src/server.rs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ 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, Error, ErrorKind, Method, Request, Response, StatusCode};
14+
use http_types::{ensure, ensure_eq, format_err};
15+
use http_types::{Body, Error, Method, Request, Response};
1516

1617
use crate::chunked::ChunkedDecoder;
1718
use crate::date::fmt_http_date;
@@ -362,23 +363,20 @@ where
362363
// Convert our header buf into an httparse instance, and validate.
363364
let status = httparse_req.parse(&buf)?;
364365

365-
let err = |msg| Error::from_str(ErrorKind::InvalidData, msg, StatusCode::BadRequest);
366-
367-
if status.is_partial() {
368-
return Err(err("Malformed HTTP head"));
369-
}
366+
ensure!(status.is_partial(), "Malformed HTTP head");
370367

371368
// Convert httparse headers + body into a `http::Request` type.
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"))?;
369+
let method = httparse_req.method;
370+
let method = method.ok_or_else(|| format_err!("No method found"))?;
371+
372+
let uri = httparse_req.path;
373+
let uri = uri.ok_or_else(|| format_err!("No uri found"))?;
374374
let uri = url::Url::parse(&format!("{}{}", addr, uri))?;
375375

376376
let version = httparse_req
377377
.version
378-
.ok_or_else(|| err("No version found"))?;
379-
if version != HTTP_1_1_VERSION {
380-
return Err(err("Unsupported HTTP version"));
381-
}
378+
.ok_or_else(|| format_err!("No version found"))?;
379+
ensure_eq!(version, HTTP_1_1_VERSION, "Unsupported HTTP version");
382380

383381
let mut req = Request::new(Method::from_str(method)?, uri);
384382
for header in httparse_req.headers.iter() {
@@ -390,14 +388,10 @@ where
390388
let content_length = req.header(&CONTENT_LENGTH);
391389
let transfer_encoding = req.header(&TRANSFER_ENCODING);
392390

393-
if content_length.is_some() && transfer_encoding.is_some() {
394-
// This is always an error.
395-
return Err(Error::from_str(
396-
ErrorKind::InvalidData,
397-
"Unexpected Content-Length header",
398-
StatusCode::BadRequest,
399-
));
400-
}
391+
http_types::ensure!(
392+
content_length.is_some() && transfer_encoding.is_some(),
393+
"Unexpected Content-Length header"
394+
);
401395

402396
// Check for Transfer-Encoding
403397
match transfer_encoding {

0 commit comments

Comments
 (0)