diff --git a/fixtures/configs/smoketest.toml b/fixtures/configs/smoketest.toml index 73b6486..597674b 100644 --- a/fixtures/configs/smoketest.toml +++ b/fixtures/configs/smoketest.toml @@ -46,7 +46,7 @@ timeout = 20 retry_wait_time = 2 # Comma-separated list of accepted status codes for valid links. -accept = "403, 403" +accept = [200, 429] # Proceed for server connections considered insecure (invalid TLS). insecure = false diff --git a/lychee-bin/src/client.rs b/lychee-bin/src/client.rs index 6d1e5de..913fa27 100644 --- a/lychee-bin/src/client.rs +++ b/lychee-bin/src/client.rs @@ -1,9 +1,8 @@ use crate::options::Config; -use crate::parse::{ - parse_basic_auth, parse_duration_secs, parse_headers, parse_remaps, parse_statuscodes, -}; +use crate::parse::{parse_basic_auth, parse_duration_secs, parse_headers, parse_remaps}; use anyhow::{Context, Result}; use headers::HeaderMapExt; +use http::StatusCode; use lychee_lib::{Client, ClientBuilder}; use regex::RegexSet; use std::{collections::HashSet, str::FromStr}; @@ -16,7 +15,6 @@ pub(crate) fn create(cfg: &Config) -> Result { headers.typed_insert(auth_header); } - let accepted = cfg.accept.clone().and_then(|a| parse_statuscodes(&a).ok()); let timeout = parse_duration_secs(cfg.timeout); let retry_wait_time = parse_duration_secs(cfg.retry_wait_time); let method: reqwest::Method = reqwest::Method::from_str(&cfg.method.to_uppercase())?; @@ -32,6 +30,17 @@ pub(crate) fn create(cfg: &Config) -> Result { cfg.scheme.clone() }; + let accepted = match cfg.accept { + Some(ref accepted) => { + let accepted: Result, _> = accepted + .iter() + .map(|code| StatusCode::from_u16(*code)) + .collect(); + Some(accepted?) + } + None => None, + }; + ClientBuilder::builder() .remaps(remaps) .includes(includes) diff --git a/lychee-bin/src/options.rs b/lychee-bin/src/options.rs index f30b5a9..661e202 100644 --- a/lychee-bin/src/options.rs +++ b/lychee-bin/src/options.rs @@ -1,5 +1,4 @@ -use std::{convert::TryFrom, fs, io::ErrorKind, path::PathBuf, str::FromStr, time::Duration}; - +use crate::parse::{parse_base, parse_statuscodes}; use anyhow::{anyhow, Context, Error, Result}; use const_format::{concatcp, formatcp}; use lychee_lib::{ @@ -8,6 +7,7 @@ use lychee_lib::{ }; use secrecy::{ExposeSecret, SecretString}; use serde::Deserialize; +use std::{collections::HashSet, fs, io::ErrorKind, path::PathBuf, str::FromStr, time::Duration}; use structopt::StructOpt; pub(crate) const LYCHEE_IGNORE_FILE: &str = ".lycheeignore"; @@ -95,10 +95,6 @@ macro_rules! fold_in { }; } -fn parse_base(src: &str) -> Result { - Base::try_from(src) -} - #[derive(Debug, StructOpt)] #[structopt( name = "lychee", @@ -272,9 +268,9 @@ pub(crate) struct Config { pub(crate) headers: Vec, /// Comma-separated list of accepted status codes for valid links - #[structopt(short, long)] + #[structopt(short, long, parse(try_from_str = parse_statuscodes))] #[serde(default)] - pub(crate) accept: Option, + pub(crate) accept: Option>, /// Website timeout in seconds from connect to response finished #[structopt(short, long, default_value = &TIMEOUT_STR)] diff --git a/lychee-bin/src/parse.rs b/lychee-bin/src/parse.rs index cdfe73b..58b16df 100644 --- a/lychee-bin/src/parse.rs +++ b/lychee-bin/src/parse.rs @@ -1,7 +1,6 @@ use anyhow::{anyhow, Context, Result}; use headers::{authorization::Basic, Authorization, HeaderMap, HeaderName}; -use http::StatusCode; -use lychee_lib::remap::Remaps; +use lychee_lib::{remap::Remaps, Base}; use std::{collections::HashSet, time::Duration}; /// Split a single HTTP header into a (key, value) tuple @@ -31,16 +30,6 @@ pub(crate) fn parse_headers>(headers: &[T]) -> Result { Ok(out) } -/// Parse HTTP status codes into a set of `StatusCode` -pub(crate) fn parse_statuscodes>(accept: T) -> Result> { - let mut statuscodes = HashSet::new(); - for code in accept.as_ref().split(',') { - let code: StatusCode = StatusCode::from_bytes(code.as_bytes())?; - statuscodes.insert(code); - } - Ok(statuscodes) -} - /// Parse URI remaps pub(crate) fn parse_remaps(remaps: &[String]) -> Result { Remaps::try_from(remaps) @@ -59,12 +48,25 @@ pub(crate) fn parse_basic_auth(auth: &str) -> Result> { Ok(Authorization::basic(params[0], params[1])) } +pub(crate) fn parse_base(src: &str) -> Result { + Base::try_from(src) +} + +/// Parse HTTP status codes into a set of `StatusCode` +pub(crate) fn parse_statuscodes>(accept: T) -> Result> { + let mut statuscodes = HashSet::new(); + for code in accept.as_ref().split(',') { + let code: u16 = code.parse::()?; + statuscodes.insert(code); + } + Ok(statuscodes) +} + #[cfg(test)] mod test { use std::collections::HashSet; use headers::{HeaderMap, HeaderMapExt}; - use http::StatusCode; use regex::Regex; use reqwest::{header, Url}; @@ -80,13 +82,7 @@ mod test { #[test] fn test_parse_statuscodes() { let actual = parse_statuscodes("200,204,301").unwrap(); - let expected = IntoIterator::into_iter([ - StatusCode::OK, - StatusCode::NO_CONTENT, - StatusCode::MOVED_PERMANENTLY, - ]) - .collect::>(); - + let expected = IntoIterator::into_iter([200, 204, 301]).collect::>(); assert_eq!(actual, expected); } diff --git a/lychee.example.toml b/lychee.example.toml index 7792b70..88425d8 100644 --- a/lychee.example.toml +++ b/lychee.example.toml @@ -45,7 +45,7 @@ timeout = 20 retry_wait_time = 2 # Comma-separated list of accepted status codes for valid links. -accept = "403, 403" +accept = [200, 429] # Proceed for server connections considered insecure (invalid TLS). insecure = false