mirror of
https://github.com/Hopiu/lychee.git
synced 2026-04-18 20:21:04 +00:00
Remaps allow mapping from a URI pattern to a different URI. The syntax is ``` lychee --remap 'https://example.com http://127.0.0.1' ``` Some use-cases are - Testing URIs prior to production deployment - Testing URIs behind a proxy Be careful when using this feature because checking every link against a large set of regular expressions has a performance impact. Also there are no constraints on the URI mapping, so the rules might contradict with each other. Remap rules get applied in order of definition to every input URI.
126 lines
3.5 KiB
Rust
126 lines
3.5 KiB
Rust
use std::ops::Index;
|
|
|
|
use crate::{ErrorKind, Result};
|
|
use regex::Regex;
|
|
use reqwest::Url;
|
|
|
|
use crate::Uri;
|
|
|
|
/// Remaps allow mapping from a URI pattern to a specified URI
|
|
///
|
|
/// Some use-cases are
|
|
/// - Testing URIs prior to production deployment
|
|
/// - Testing URIs behind a proxy
|
|
///
|
|
/// Be careful when using this feature because checking every link against a
|
|
/// large set of regular expressions has a performance impact. Also there are no
|
|
/// constraints on the URI mapping, so the rules might contradict each other.
|
|
#[derive(Debug, Clone)]
|
|
pub struct Remaps(Vec<(Regex, Url)>);
|
|
|
|
impl Remaps {
|
|
/// Create a new remapper
|
|
#[must_use]
|
|
pub fn new(patterns: Vec<(Regex, Url)>) -> Self {
|
|
Self(patterns)
|
|
}
|
|
|
|
/// Remap URI using the client-defined remap patterns
|
|
///
|
|
/// # Errors
|
|
///
|
|
/// Returns an error if the remapping value is not a valid URI
|
|
pub fn remap(&self, uri: Uri) -> Result<Uri> {
|
|
let mut uri = uri;
|
|
for (pattern, new_uri) in &self.0 {
|
|
if pattern.is_match(uri.as_str()) {
|
|
uri = Uri::try_from(new_uri.clone())?;
|
|
}
|
|
}
|
|
Ok(uri)
|
|
}
|
|
|
|
/// Returns `true` if there are no remappings defined.
|
|
#[must_use]
|
|
pub fn is_empty(&self) -> bool {
|
|
self.0.is_empty()
|
|
}
|
|
|
|
/// Get the number of defined remap rules
|
|
#[must_use]
|
|
pub fn len(&self) -> usize {
|
|
self.0.len()
|
|
}
|
|
}
|
|
|
|
impl Index<usize> for Remaps {
|
|
type Output = (Regex, Url);
|
|
|
|
fn index(&self, index: usize) -> &(regex::Regex, url::Url) {
|
|
&self.0[index]
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&[String]> for Remaps {
|
|
type Error = ErrorKind;
|
|
|
|
fn try_from(remaps: &[String]) -> std::result::Result<Self, Self::Error> {
|
|
let mut parsed = Vec::new();
|
|
|
|
for remap in remaps {
|
|
let params: Vec<_> = remap.split_whitespace().collect();
|
|
if params.len() != 2 {
|
|
return Err(ErrorKind::InvalidUriRemap(remap.to_string()));
|
|
}
|
|
|
|
let pattern = Regex::new(params[0])?;
|
|
let url = Url::try_from(params[1])
|
|
.map_err(|e| ErrorKind::ParseUrl(e, params[1].to_string()))?;
|
|
parsed.push((pattern, url));
|
|
}
|
|
|
|
Ok(Remaps::new(parsed))
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_remap() {
|
|
let pattern = Regex::new("https://example.com").unwrap();
|
|
let uri = Uri::try_from("http://127.0.0.1:8080").unwrap();
|
|
let remaps = Remaps::new(vec![(pattern, uri.clone().url)]);
|
|
|
|
let input = Uri::try_from("https://example.com").unwrap();
|
|
let remapped = remaps.remap(input).unwrap();
|
|
|
|
assert_eq!(remapped, uri);
|
|
}
|
|
|
|
#[test]
|
|
fn test_remap_path() {
|
|
let pattern = Regex::new("../../issues").unwrap();
|
|
let uri = Uri::try_from("https://example.com").unwrap();
|
|
let remaps = Remaps::new(vec![(pattern, uri.clone().url)]);
|
|
|
|
let input = Uri::try_from("file://../../issues").unwrap();
|
|
let remapped = remaps.remap(input).unwrap();
|
|
|
|
assert_eq!(remapped, uri);
|
|
}
|
|
|
|
#[test]
|
|
fn test_remap_skip() {
|
|
let pattern = Regex::new("https://example.com").unwrap();
|
|
let uri = Uri::try_from("http://127.0.0.1:8080").unwrap();
|
|
let remaps = Remaps::new(vec![(pattern, uri.url)]);
|
|
|
|
let input = Uri::try_from("https://unrelated.example.com").unwrap();
|
|
let remapped = remaps.remap(input.clone()).unwrap();
|
|
|
|
// URI was not modified
|
|
assert_eq!(remapped, input);
|
|
}
|
|
}
|