Skip to content

Commit

Permalink
add HTTP referer header for resource requests
Browse files Browse the repository at this point in the history
  • Loading branch information
rakhnin committed Aug 15, 2024
1 parent 64e84e4 commit 2735008
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 3 deletions.
11 changes: 11 additions & 0 deletions src/url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 9 additions & 2 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion tests/url/clean_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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&"
Expand Down
1 change: 1 addition & 0 deletions tests/url/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 88 additions & 0 deletions tests/url/referer_url.rs
Original file line number Diff line number Diff line change
@@ -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:[email protected]/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://:[email protected]/path").unwrap()).as_str(),
"https://gibson.lan/path"
);
}

#[test]
fn removes_empty_password_credentials() {
assert_eq!(
url::referer_url(Url::parse("https://[email protected]/path").unwrap()).as_str(),
"https://gibson.lan/path"
);
}
}

0 comments on commit 2735008

Please sign in to comment.