Rewrite the Error type. (#234)

This adds a source field to keep track of upstream errors and allow
backtraces, plus a URL field to indicate what URL an error was
associated with.

The enum variants we used to use for Error are now part of a new
ErrorKind type. For convenience within ureq, ErrorKinds can be turned
into an Error with `.new()` or `.msg("some additional information")`.

Error acts as a builder, so additional information can be added after
initial construction. For instance, we return a DnsFailed error when
name resolution fails. When that error bubbles up to Request's
`do_call`, Request adds the URL.

Fixes #232.
This commit is contained in:
Jacob Hoffman-Andrews
2020-11-21 16:14:44 -08:00
committed by GitHub
parent dac517e30e
commit fade03b54e
13 changed files with 266 additions and 122 deletions

View File

@@ -1,4 +1,4 @@
use crate::error::Error;
use crate::error::{Error, ErrorKind};
use std::fmt;
use std::str::FromStr;
@@ -66,9 +66,10 @@ impl Header {
pub(crate) fn validate(&self) -> Result<(), Error> {
if !valid_name(self.name()) || !valid_value(&self.line.as_str()[self.index + 1..]) {
return Err(Error::BadHeader);
Err(ErrorKind::BadHeader.msg(&format!("invalid header '{}'", self.line)))
} else {
Ok(())
}
Ok(())
}
}
@@ -150,11 +151,13 @@ impl FromStr for Header {
fn from_str(s: &str) -> Result<Self, Self::Err> {
//
let line = s.to_string();
let index = s.find(':').ok_or_else(|| Error::BadHeader)?;
let index = s
.find(':')
.ok_or_else(|| ErrorKind::BadHeader.msg("no colon in header"))?;
// no value?
if index >= s.len() {
return Err(Error::BadHeader);
return Err(ErrorKind::BadHeader.msg("no value in header"));
}
let header = Header { line, index };
@@ -203,7 +206,7 @@ fn test_parse_invalid_name() {
for c in cases {
let result = c.parse::<Header>();
assert!(
matches!(result, Err(Error::BadHeader)),
matches!(result, Err(ref e) if e.kind() == ErrorKind::BadHeader),
"'{}'.parse(): expected BadHeader, got {:?}",
c,
result