From e13f7c9fef32923982d8eaac7111b199b5ce2196 Mon Sep 17 00:00:00 2001 From: "Hadrien G." Date: Mon, 31 Mar 2025 12:39:46 +0200 Subject: [PATCH] Fix accept/exclude range syntax and docs (#1668) --- README.md | 26 ++++++++++++++------------ lychee-bin/src/options.rs | 28 +++++++++++++++------------- lychee-lib/src/types/accept/range.rs | 25 ++++++++++++++++--------- 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 4691428..3d7e711 100644 --- a/README.md +++ b/README.md @@ -354,16 +354,18 @@ Options: --cache-exclude-status A list of status codes that will be ignored from the cache - The following accept range syntax is supported: [start]..[=]end|code. Some valid + The following exclude range syntax is supported: [start]..[[=]end]|code. Some valid examples are: - - 429 - - 500..=599 - - 500.. + - 429 (excludes the 429 status code only) + - 500.. (excludes any status code >= 500) + - ..100 (excludes any status code < 100) + - 500..=599 (excludes any status code from 500 to 599 inclusive) + - 500..600 (excludes any status code from 500 to 600 excluding 600, same as 500..=599) Use "lychee --cache-exclude-status '429, 500..502' ..." to provide a comma- separated - list of excluded status codes. This example will not cache results with a status code of 429, 500, - 501 and 502. + list of excluded status codes. This example will not cache results with a status code of 429, 500 + and 501. [default: ] @@ -460,14 +462,14 @@ Options: -a, --accept A List of accepted status codes for valid links - The following accept range syntax is supported: [start]..[=]end|code. Some valid + The following accept range syntax is supported: [start]..[[=]end]|code. Some valid examples are: - - 200..=204 - - 200..204 - - ..=204 - - ..204 - - 200 + - 200 (accepts the 200 status code only) + - ..204 (accepts any status code < 204) + - ..=204 (accepts any status code <= 204) + - 200..=204 (accepts any status code from 200 to 204 inclusive) + - 200..205 (accepts any status code from 200 to 205 excluding 205, same as 200..=204) Use "lychee --accept '200..=204, 429, 500' ..." to provide a comma- separated list of accepted status codes. This example will accept 200, 201, diff --git a/lychee-bin/src/options.rs b/lychee-bin/src/options.rs index c6e18ee..8eb038b 100644 --- a/lychee-bin/src/options.rs +++ b/lychee-bin/src/options.rs @@ -240,7 +240,7 @@ pub(crate) struct Config { long, default_value_t = FileExtensions::default(), long_help = "Test the specified file extensions for URIs when checking files locally. - + Multiple extensions can be separated by commas. Note that if you want to check filetypes, which have multiple extensions, e.g. HTML files with both .html and .htm extensions, you need to specify both extensions explicitly." @@ -269,16 +269,18 @@ specify both extensions explicitly." default_value_t, long_help = "A list of status codes that will be ignored from the cache -The following accept range syntax is supported: [start]..[=]end|code. Some valid +The following exclude range syntax is supported: [start]..[[=]end]|code. Some valid examples are: -- 429 -- 500..=599 -- 500.. +- 429 (excludes the 429 status code only) +- 500.. (excludes any status code >= 500) +- ..100 (excludes any status code < 100) +- 500..=599 (excludes any status code from 500 to 599 inclusive) +- 500..600 (excludes any status code from 500 to 600 excluding 600, same as 500..=599) Use \"lychee --cache-exclude-status '429, 500..502' ...\" to provide a comma- separated -list of excluded status codes. This example will not cache results with a status code of 429, 500, -501 and 502." +list of excluded status codes. This example will not cache results with a status code of 429, 500 +and 501." )] #[serde(default = "cache_exclude_selector")] pub(crate) cache_exclude_status: StatusCodeExcluder, @@ -432,14 +434,14 @@ Example: --fallback-extensions html,htm,php,asp,aspx,jsp,cgi" default_value_t, long_help = "A List of accepted status codes for valid links -The following accept range syntax is supported: [start]..[=]end|code. Some valid +The following accept range syntax is supported: [start]..[[=]end]|code. Some valid examples are: -- 200..=204 -- 200..204 -- ..=204 -- ..204 -- 200 +- 200 (accepts the 200 status code only) +- ..204 (accepts any status code < 204) +- ..=204 (accepts any status code <= 204) +- 200..=204 (accepts any status code from 200 to 204 inclusive) +- 200..205 (accepts any status code from 200 to 205 excluding 205, same as 200..=204) Use \"lychee --accept '200..=204, 429, 500' ...\" to provide a comma- separated list of accepted status codes. This example will accept 200, 201, diff --git a/lychee-lib/src/types/accept/range.rs b/lychee-lib/src/types/accept/range.rs index 3707404..dff721a 100644 --- a/lychee-lib/src/types/accept/range.rs +++ b/lychee-lib/src/types/accept/range.rs @@ -5,7 +5,7 @@ use regex::Regex; use thiserror::Error; static RANGE_PATTERN: Lazy = - Lazy::new(|| Regex::new(r"^([0-9]{3})?\.\.(=?)([0-9]{3})+$|^([0-9]{3})$").unwrap()); + Lazy::new(|| Regex::new(r"^([0-9]{3})?\.\.((=?)([0-9]{3}))?$|^([0-9]{3})$").unwrap()); /// Indicates that the parsing process of an [`AcceptRange`] from a string /// failed due to various underlying reasons. @@ -37,7 +37,7 @@ impl FromStr for AcceptRange { .captures(s) .ok_or(AcceptRangeError::NoRangePattern)?; - if let Some(value) = captures.get(4) { + if let Some(value) = captures.get(5) { let value: u16 = value.as_str().parse()?; Self::new_from(value, value) } else { @@ -45,9 +45,12 @@ impl FromStr for AcceptRange { Some(start) => start.as_str().parse().unwrap_or_default(), None => 0, }; + if captures.get(2).is_none() { + return Self::new_from(start, u16::MAX); + } - let inclusive = !captures[2].is_empty(); - let end: u16 = captures[3].parse()?; + let inclusive = !captures[3].is_empty(); + let end: u16 = captures[4].parse()?; if inclusive { Self::new_from(start, end) @@ -159,11 +162,13 @@ mod test { use rstest::rstest; #[rstest] - #[case("100..=200", vec![100, 150, 200], vec![250, 300])] - #[case("..=100", vec![0, 50, 100], vec![150, 200])] - #[case("100..200", vec![100, 150], vec![200, 250])] - #[case("..100", vec![0, 50], vec![100, 150])] - #[case("404", vec![404], vec![200, 304, 500])] + #[case("..", vec![0, 100, 150, 200, u16::MAX], vec![])] + #[case("100..", vec![100, 101, 150, 200, u16::MAX], vec![0, 50, 99])] + #[case("100..=200", vec![100, 150, 200], vec![0, 50, 99, 201, 250])] + #[case("..=100", vec![0, 50, 100], vec![101, 150, 200])] + #[case("100..200", vec![100, 150, 199], vec![99, 200, 250])] + #[case("..100", vec![0, 50, 99], vec![100, 150])] + #[case("404", vec![404], vec![200, 304, 403, 405, 500])] fn test_from_str( #[case] input: &str, #[case] valid_values: Vec, @@ -182,6 +187,8 @@ mod test { #[rstest] #[case("200..=100", AcceptRangeError::InvalidRangeIndices)] + #[case("..=", AcceptRangeError::NoRangePattern)] + #[case("100..=", AcceptRangeError::NoRangePattern)] #[case("-100..=100", AcceptRangeError::NoRangePattern)] #[case("-100..100", AcceptRangeError::NoRangePattern)] #[case("100..=-100", AcceptRangeError::NoRangePattern)]