linkcheck2/validation/
context.rs1use crate::{
2 validation::{Cache, Options},
3 Link,
4};
5use reqwest::{header::HeaderMap, Client, Url};
6use std::{
7 sync::{Mutex, MutexGuard},
8 time::Duration,
9};
10
11pub trait Context {
14 fn client(&self) -> &Client;
16
17 fn filesystem_options(&self) -> &Options;
19
20 fn url_specific_headers(&self, _url: &Url) -> HeaderMap { HeaderMap::new() }
22
23 fn cache(&self) -> Option<MutexGuard<'_, Cache>> { None }
31
32 fn concurrency(&self) -> usize { 64 }
34
35 fn cache_timeout(&self) -> Duration {
38 Duration::from_secs(24 * 60 * 60)
40 }
41
42 fn should_ignore(&self, _link: &Link) -> bool { false }
44}
45
46#[derive(Debug)]
48pub struct BasicContext {
49 pub options: Options,
51 client: Client,
52 cache: Mutex<Cache>,
53}
54
55impl BasicContext {
56 pub const USER_AGENT: &'static str =
58 concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
59
60 pub fn with_client(client: Client) -> Self {
62 BasicContext {
63 client,
64 options: Options::default(),
65 cache: Mutex::new(Cache::new()),
66 }
67 }
68
69 #[deprecated = "Access the field directly instead"]
72 pub fn options_mut(&mut self) -> &mut Options { &mut self.options }
73}
74
75impl Default for BasicContext {
76 fn default() -> Self {
77 let client = Client::builder()
78 .user_agent(BasicContext::USER_AGENT)
79 .build()
80 .expect("Unable to initialize the client");
81
82 BasicContext::with_client(client)
83 }
84}
85
86impl Context for BasicContext {
87 fn client(&self) -> &Client { &self.client }
88
89 fn filesystem_options(&self) -> &Options { &self.options }
90
91 fn cache(&self) -> Option<MutexGuard<'_, Cache>> {
92 Some(self.cache.lock().expect("Mutex was poisoned"))
93 }
94}