add HTTP referer header for resource requests

This commit is contained in:
Andriy Rakhnin 2024-08-15 19:11:24 +02:00 committed by Sunshine
parent 64e84e4983
commit c10c78a27d
5 changed files with 110 additions and 3 deletions

View File

@ -79,6 +79,17 @@ pub fn parse_data_url(url: &Url) -> (String, String, Vec<u8>) {
(media_type, charset, blob)
}
pub fn referer_url(url: Url) -> Url {
let mut url = url.clone();
// https://httpwg.org/specs/rfc9110.html#field.referer
// MUST NOT include the fragment and userinfo components of the URI
url.set_fragment(None);
url.set_username(&"").unwrap();
url.set_password(None).unwrap();
url
}
pub fn resolve_url(from: &Url, to: &str) -> Url {
match Url::parse(&to) {
Ok(parsed_url) => parsed_url,

View File

@ -1,12 +1,12 @@
use reqwest::blocking::Client;
use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE, COOKIE};
use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE, COOKIE, REFERER};
use std::collections::HashMap;
use std::fs;
use std::path::{Path, PathBuf};
use url::Url;
use crate::opts::Options;
use crate::url::{clean_url, parse_data_url};
use crate::url::{clean_url, parse_data_url, referer_url};
const ANSI_COLOR_RED: &'static str = "\x1b[31m";
const ANSI_COLOR_RESET: &'static str = "\x1b[0m";
@ -298,6 +298,13 @@ pub fn retrieve_asset(
}
}
}
// Add referer header for page resource requests
if parent_url != url {
headers.insert(
REFERER,
HeaderValue::from_str(referer_url(parent_url.clone()).as_str()).unwrap(),
);
}
match client.get(url.as_str()).headers(headers).send() {
Ok(response) => {
if !options.ignore_errors && response.status() != reqwest::StatusCode::OK {

View File

@ -46,7 +46,7 @@ mod passing {
}
#[test]
fn removesempty_fragment_and_keeps_empty_query() {
fn removes_empty_fragment_and_keeps_query() {
assert_eq!(
url::clean_url(Url::parse("https://somewhere.com/font.eot?a=b&#").unwrap()).as_str(),
"https://somewhere.com/font.eot?a=b&"

View File

@ -2,4 +2,5 @@ mod clean_url;
mod create_data_url;
mod is_url_and_has_protocol;
mod parse_data_url;
mod referer_url;
mod resolve_url;

88
tests/url/referer_url.rs Normal file
View File

@ -0,0 +1,88 @@
// ██████╗ █████╗ ███████╗███████╗██╗███╗ ██╗ ██████╗
// ██╔══██╗██╔══██╗██╔════╝██╔════╝██║████╗ ██║██╔════╝
// ██████╔╝███████║███████╗███████╗██║██╔██╗ ██║██║ ███╗
// ██╔═══╝ ██╔══██║╚════██║╚════██║██║██║╚██╗██║██║ ██║
// ██║ ██║ ██║███████║███████║██║██║ ╚████║╚██████╔╝
// ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝╚═╝ ╚═══╝ ╚═════╝
#[cfg(test)]
mod passing {
use reqwest::Url;
use monolith::url;
#[test]
fn preserve_original() {
let u: Url = Url::parse("https://somewhere.com/font.eot#iefix").unwrap();
let referer_u: Url = url::referer_url(u.clone());
assert_eq!(referer_u.as_str(), "https://somewhere.com/font.eot");
assert_eq!(u.as_str(), "https://somewhere.com/font.eot#iefix");
}
#[test]
fn removes_fragment() {
assert_eq!(
url::referer_url(Url::parse("https://somewhere.com/font.eot#iefix").unwrap()).as_str(),
"https://somewhere.com/font.eot"
);
}
#[test]
fn removes_empty_fragment() {
assert_eq!(
url::referer_url(Url::parse("https://somewhere.com/font.eot#").unwrap()).as_str(),
"https://somewhere.com/font.eot"
);
}
#[test]
fn removes_empty_fragment_and_keeps_empty_query() {
assert_eq!(
url::referer_url(Url::parse("https://somewhere.com/font.eot?#").unwrap()).as_str(),
"https://somewhere.com/font.eot?"
);
}
#[test]
fn removes_empty_fragment_and_keeps_query() {
assert_eq!(
url::referer_url(Url::parse("https://somewhere.com/font.eot?a=b&#").unwrap()).as_str(),
"https://somewhere.com/font.eot?a=b&"
);
}
#[test]
fn removes_credentials() {
assert_eq!(
url::referer_url(Url::parse("https://cookie:monster@gibson.lan/path").unwrap())
.as_str(),
"https://gibson.lan/path"
);
}
#[test]
fn removes_empty_credentials() {
assert_eq!(
url::referer_url(Url::parse("https://@gibson.lan/path").unwrap()).as_str(),
"https://gibson.lan/path"
);
}
#[test]
fn removes_empty_username_credentials() {
assert_eq!(
url::referer_url(Url::parse("https://:monster@gibson.lan/path").unwrap()).as_str(),
"https://gibson.lan/path"
);
}
#[test]
fn removes_empty_password_credentials() {
assert_eq!(
url::referer_url(Url::parse("https://cookie@gibson.lan/path").unwrap()).as_str(),
"https://gibson.lan/path"
);
}
}