Skip to content

Commit

Permalink
Switch to ureq 2.0
Browse files Browse the repository at this point in the history
- Remove redundant url field. This can now be found from ureq itself.
- Implement `From` now that the URL field is gone
  • Loading branch information
jyn514 authored and Joshua Nelson committed Jan 10, 2021
1 parent 021aca8 commit 58a972a
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 45 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@

* `CheckError` now has an `HttpForbidden` variant. [PR#138]
* The `check_http` field of `CheckContext` is now an enum instead of a boolean [PR#138]
* ureq has been upgraded to 2.0. This affects the public `CheckError` API, but should otherwise have no user-facing impact. [PR#134]

[PR#134]: https://github.com/deadlinks/cargo-deadlinks/pull/134
[PR#138]: https://github.com/deadlinks/cargo-deadlinks/pull/138

<a name="0.7.2"></a>
Expand Down
14 changes: 2 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ num_cpus = "1.8"
once_cell = "1.5.1"
rayon = "1.0"
regex = { version = "1", default-features = false, features = ["std", "perf"] }
ureq = { version = "1.5.4", features = ["tls"], default-features = false }
ureq = { version = "2.0.1", features = ["tls"], default-features = false }
serde = "1.0"
serde_derive = "1.0"
url = "2"
Expand Down
59 changes: 28 additions & 31 deletions src/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,21 @@ const PREFIX_BLACKLIST: [&str; 1] = ["https://doc.rust-lang.org"];

#[derive(Debug)]
pub enum IoError {
HttpUnexpectedStatus(Url, ureq::Response),
HttpFetch(Url, ureq::Error),
HttpUnexpectedStatus(ureq::Response),
HttpFetch(ureq::Transport),
FileIo(String, std::io::Error),
}

impl fmt::Display for IoError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
IoError::HttpUnexpectedStatus(url, resp) => write!(
IoError::HttpUnexpectedStatus(resp) => write!(
f,
"Unexpected HTTP status fetching {}: {}",
url,
resp.get_url(),
resp.status_text()
),
IoError::HttpFetch(url, e) => write!(f, "Error fetching {}: {}", url, e),
IoError::HttpFetch(e) => write!(f, "Error fetching {}", e),
IoError::FileIo(url, e) => write!(f, "Error fetching {}: {}", url, e),
}
}
Expand Down Expand Up @@ -89,6 +89,16 @@ pub enum CheckError {
Io(Box<IoError>),
}

impl From<ureq::Error> for CheckError {
fn from(err: ureq::Error) -> Self {
let io_err = match err {
ureq::Error::Status(_, response) => IoError::HttpUnexpectedStatus(response),
ureq::Error::Transport(err) => IoError::HttpFetch(err),
};
CheckError::Io(Box::new(io_err))
}
}

impl fmt::Display for CheckError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Expand Down Expand Up @@ -277,23 +287,7 @@ fn check_file_fragment(
is_fragment_available(&Link::File(path.to_path_buf()), fragment, fetch_html)
}

fn handle_response(url: &Url, resp: ureq::Response) -> Result<ureq::Response, CheckError> {
if resp.synthetic() {
Err(CheckError::Io(Box::new(IoError::HttpFetch(
url.clone(),
resp.into_synthetic_error().unwrap(),
))))
} else if resp.ok() {
Ok(resp)
} else {
Err(CheckError::Io(Box::new(IoError::HttpUnexpectedStatus(
url.clone(),
resp,
))))
}
}

/// Check a URL with "http" or "https" scheme for availability. Returns `false` if it is unavailable.
/// Check a URL with "http" or "https" scheme for availability. Returns `Err` if it is unavailable.
fn check_http_url(url: &Url, ctx: &CheckContext) -> Result<(), CheckError> {
if ctx.check_http == HttpCheck::Ignored {
warn!(
Expand All @@ -320,13 +314,15 @@ fn check_http_url(url: &Url, ctx: &CheckContext) -> Result<(), CheckError> {
// The URL might contain a fragment. In that case we need a full GET
// request to check if the fragment exists.
if url.fragment().is_none() || !ctx.check_fragments {
let mut resp = ureq::head(url.as_str()).call();
// If HEAD isn't allowed, try sending a GET instead
if resp.status() == 405 {
resp = ureq::get(url.as_str()).call();
match ureq::head(url.as_str()).call() {
Err(ureq::Error::Status(405, _)) => {
// If HEAD isn't allowed, try sending a GET instead
ureq::get(url.as_str()).call()?;
Ok(())
}
Err(other) => Err(other.into()),
Ok(_) => Ok(()),
}

handle_response(url, resp).map(|_: ureq::Response| ())
} else {
// the URL might contain a fragment, in that case we need to check if
// the fragment exists, this issues a GET request
Expand All @@ -338,8 +334,8 @@ fn check_http_fragment(url: &Url, fragment: &str) -> Result<(), CheckError> {
debug!("Checking fragment {} of URL {}.", fragment, url.as_str());

fn get_html(url: &Url) -> Result<String, CheckError> {
let resp = ureq::get(url.as_str()).call();
handle_response(&url, resp).map(|resp| resp.into_string().unwrap())
let resp = ureq::get(url.as_str()).call()?;
Ok(resp.into_string().unwrap())
}

let fetch_html = || {
Expand All @@ -359,7 +355,8 @@ fn check_http_fragment(url: &Url, fragment: &str) -> Result<(), CheckError> {
}
};

is_fragment_available(&Link::Http(url.clone()), fragment, fetch_html)
is_fragment_available(&Link::Http(url.clone()), fragment, fetch_html)?;
Ok(())
}

#[cfg(test)]
Expand Down
6 changes: 5 additions & 1 deletion tests/non_existent_http_link.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
extern crate assert_cmd;

use assert_cmd::prelude::*;
use predicates::str::contains;
use std::process::Command;

mod non_existent_http_link {
Expand Down Expand Up @@ -40,6 +41,9 @@ mod non_existent_http_link {
.args(&["deadlinks", "--check-http"])
.current_dir("./tests/non_existent_http_link")
.assert()
.failure();
.failure()
.stdout(contains(
"Unexpected HTTP status fetching http://example.com/this/does/not/exist: Not Found",
));
}
}

0 comments on commit 58a972a

Please sign in to comment.