Add support for parsing list of status codes from config file (#636)

This commit is contained in:
Matthias 2022-06-02 18:53:04 +02:00 committed by GitHub
parent c321464ff3
commit a557cba0b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 35 additions and 34 deletions

View file

@ -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

View file

@ -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<Client> {
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<Client> {
cfg.scheme.clone()
};
let accepted = match cfg.accept {
Some(ref accepted) => {
let accepted: Result<HashSet<_>, _> = accepted
.iter()
.map(|code| StatusCode::from_u16(*code))
.collect();
Some(accepted?)
}
None => None,
};
ClientBuilder::builder()
.remaps(remaps)
.includes(includes)

View file

@ -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, lychee_lib::ErrorKind> {
Base::try_from(src)
}
#[derive(Debug, StructOpt)]
#[structopt(
name = "lychee",
@ -272,9 +268,9 @@ pub(crate) struct Config {
pub(crate) headers: Vec<String>,
/// 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<String>,
pub(crate) accept: Option<HashSet<u16>>,
/// Website timeout in seconds from connect to response finished
#[structopt(short, long, default_value = &TIMEOUT_STR)]

View file

@ -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<T: AsRef<str>>(headers: &[T]) -> Result<HeaderMap> {
Ok(out)
}
/// Parse HTTP status codes into a set of `StatusCode`
pub(crate) fn parse_statuscodes<T: AsRef<str>>(accept: T) -> Result<HashSet<StatusCode>> {
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> {
Remaps::try_from(remaps)
@ -59,12 +48,25 @@ pub(crate) fn parse_basic_auth(auth: &str) -> Result<Authorization<Basic>> {
Ok(Authorization::basic(params[0], params[1]))
}
pub(crate) fn parse_base(src: &str) -> Result<Base, lychee_lib::ErrorKind> {
Base::try_from(src)
}
/// Parse HTTP status codes into a set of `StatusCode`
pub(crate) fn parse_statuscodes<T: AsRef<str>>(accept: T) -> Result<HashSet<u16>> {
let mut statuscodes = HashSet::new();
for code in accept.as_ref().split(',') {
let code: u16 = code.parse::<u16>()?;
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::<HashSet<_>>();
let expected = IntoIterator::into_iter([200, 204, 301]).collect::<HashSet<_>>();
assert_eq!(actual, expected);
}

View file

@ -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