From 0c4bea80742d6d816972acbd269256814f510ec7 Mon Sep 17 00:00:00 2001 From: Thomas Zahner Date: Mon, 11 Mar 2024 16:40:11 +0100 Subject: [PATCH] Create request chain with basic authentication --- lychee-lib/src/chain/mod.rs | 39 +++++++++++++++++++++++++++++++++++++ lychee-lib/src/client.rs | 31 ++++++++++++++++------------- lychee-lib/src/lib.rs | 1 + 3 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 lychee-lib/src/chain/mod.rs diff --git a/lychee-lib/src/chain/mod.rs b/lychee-lib/src/chain/mod.rs new file mode 100644 index 0000000..359983d --- /dev/null +++ b/lychee-lib/src/chain/mod.rs @@ -0,0 +1,39 @@ +use headers::authorization::Credentials; +use http::header::AUTHORIZATION; +use reqwest::Request; + +use crate::BasicAuthCredentials; + +pub(crate) type Chain = Vec + Send>>; + +pub(crate) fn traverse(chain: Chain, mut input: T) -> T { + for mut e in chain { + input = e.handle(input) + } + + input +} + +pub(crate) trait Chainable { + fn handle(&mut self, input: T) -> T; +} + +pub(crate) struct BasicAuth { + credentials: BasicAuthCredentials, +} + +impl BasicAuth { + pub(crate) fn new(credentials: BasicAuthCredentials) -> Self { + Self { credentials } + } +} + +impl Chainable for BasicAuth { + fn handle(&mut self, mut request: Request) -> Request { + request.headers_mut().append( + AUTHORIZATION, + self.credentials.to_authorization().0.encode(), + ); + request + } +} diff --git a/lychee-lib/src/client.rs b/lychee-lib/src/client.rs index 801d4e9..fa469d5 100644 --- a/lychee-lib/src/client.rs +++ b/lychee-lib/src/client.rs @@ -17,9 +17,8 @@ use std::{collections::HashSet, path::Path, sync::Arc, time::Duration}; #[cfg(all(feature = "email-check", feature = "native-tls"))] use check_if_email_exists::{check_email, CheckEmailInput, Reachable}; -use headers::authorization::Credentials; use http::{ - header::{HeaderMap, HeaderValue, AUTHORIZATION}, + header::{HeaderMap, HeaderValue}, StatusCode, }; use log::{debug, warn}; @@ -31,6 +30,7 @@ use secrecy::{ExposeSecret, SecretString}; use typed_builder::TypedBuilder; use crate::{ + chain::{traverse, BasicAuth, Chain}, filter::{Excludes, Filter, Includes}, quirks::Quirks, remap::Remaps, @@ -647,23 +647,28 @@ impl Client { /// Check a URI using [reqwest](https://github.com/seanmonstar/reqwest). async fn check_default(&self, uri: &Uri, credentials: &Option) -> Status { - let request = match credentials { - Some(credentials) => self - .reqwest_client - .request(self.method.clone(), uri.as_str()) - .header(AUTHORIZATION, credentials.to_authorization().0.encode()) - .build(), - None => self - .reqwest_client - .request(self.method.clone(), uri.as_str()) - .build(), - }; + // todo: middleware + + // todo: create credentials middleware + let request = self + .reqwest_client + .request(self.method.clone(), uri.as_str()) + .build(); let request = match request { Ok(r) => r, Err(e) => return e.into(), }; + let mut chain: Chain = vec![]; + + if let Some(c) = credentials { + chain.push(Box::new(BasicAuth::new(c.clone()))); + } + + let request = traverse(chain, request); + + // todo: quirks middleware let request = self.quirks.apply(request); match self.reqwest_client.execute(request).await { diff --git a/lychee-lib/src/lib.rs b/lychee-lib/src/lib.rs index a74b899..dd41386 100644 --- a/lychee-lib/src/lib.rs +++ b/lychee-lib/src/lib.rs @@ -54,6 +54,7 @@ mod basic_auth; mod client; /// A pool of clients, to handle concurrent checks pub mod collector; +mod chain; mod quirks; mod retry; mod types;