From 45de5c763e962ffe4b96af5b3f8809b0b4989bc5 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 22 Mar 2022 13:15:11 +0100 Subject: [PATCH] Avoid reqwest panic on invalid URIs (#557) --- lychee-lib/src/client.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lychee-lib/src/client.rs b/lychee-lib/src/client.rs index eb75dd4..55b0ec5 100644 --- a/lychee-lib/src/client.rs +++ b/lychee-lib/src/client.rs @@ -22,7 +22,7 @@ use http::{ }; use octocrab::Octocrab; use regex::RegexSet; -use reqwest::header; +use reqwest::{header, Url}; use secrecy::{ExposeSecret, SecretString}; use tokio::time::sleep; use typed_builder::TypedBuilder; @@ -466,6 +466,11 @@ impl Client { /// Check a URI using [reqwest](https://github.com/seanmonstar/reqwest). async fn check_default(&self, uri: &Uri) -> Status { + // Workaround for upstream reqwest panic + if invalid(&uri.url) { + return Status::Error(ErrorKind::InvalidURI(uri.clone())); + } + let request = match self .reqwest_client .request(self.method.clone(), uri.as_str()) @@ -506,6 +511,14 @@ impl Client { } } +// Check if the given `Url` would cause `reqwest` to panic. +// This is a workaround for https://github.com/lycheeverse/lychee/issues/539 +// and can be removed once https://github.com/seanmonstar/reqwest/pull/1399 +// got merged. +fn invalid(url: &Url) -> bool { + url.as_str().parse::().is_err() +} + /// A convenience function to check a single URI. /// /// This provides the simplest link check utility without having to create a [`Client`]. @@ -711,4 +724,12 @@ mod test { let res = client.check(mock_server.uri()).await.unwrap(); assert!(res.status().is_timeout()); } + + #[tokio::test] + async fn test_avoid_reqwest_panic() { + let client = ClientBuilder::builder().build().client().unwrap(); + // This request will fail, but it won't panic + let res = client.check("http://\"").await.unwrap(); + assert!(res.status().is_failure()); + } }