ensure proxy urls have a host in front and not simple "/" path
This commit is contained in:
15
src/api.rs
15
src/api.rs
@@ -610,6 +610,12 @@ async fn videos_post(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(base) = options.public_url_base.as_deref() {
|
||||
for video in video_items.iter_mut() {
|
||||
video.ensure_proxy_host(base);
|
||||
}
|
||||
}
|
||||
|
||||
videos.pageInfo = PageInfo {
|
||||
hasNextPage: false,
|
||||
resultsPerPage: perPage as u32,
|
||||
@@ -659,6 +665,15 @@ async fn videos_post(
|
||||
video.id = format!("{}:{}", channel, video.id);
|
||||
}
|
||||
|
||||
// Cached items may have been built without a request host (e.g. by runtime
|
||||
// validation), leaving host-relative `/proxy/...` URLs. Re-apply the host
|
||||
// from this request so proxy URLs are always absolute.
|
||||
if let Some(base) = options.public_url_base.as_deref() {
|
||||
for video in video_items.iter_mut() {
|
||||
video.ensure_proxy_host(base);
|
||||
}
|
||||
}
|
||||
|
||||
// There is a bug in Hottub38 that makes the client error for a 403-url even though formats work fine
|
||||
if clientversion == ClientVersion::new(38, 0, "Hot%20Tub".to_string()) {
|
||||
// filter out videos without preview for old clients
|
||||
|
||||
@@ -671,6 +671,22 @@ pub fn build_proxy_url(options: &ServerOptions, proxy: &str, target: &str) -> St
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-applies the public host to a (possibly host-relative) proxy URL.
|
||||
///
|
||||
/// Provider results are cached as fully-rendered items, so the `public_url_base`
|
||||
/// in effect when an item is *first* built gets baked into its proxy URLs. Items
|
||||
/// first produced by runtime validation (which has no request, so
|
||||
/// `public_url_base` is `None`) therefore carry host-relative `/proxy/...` URLs.
|
||||
/// Response handlers call this with the host derived from the incoming request so
|
||||
/// every proxy URL is absolute, regardless of which context populated the cache.
|
||||
pub fn ensure_proxy_url_host(url: &str, public_url_base: &str) -> String {
|
||||
let base = public_url_base.trim_end_matches('/');
|
||||
if base.is_empty() || !url.starts_with("/proxy/") {
|
||||
return url.to_string();
|
||||
}
|
||||
format!("{base}{url}")
|
||||
}
|
||||
|
||||
fn channel_metadata_for(id: &str) -> Option<ProviderChannelMetadata> {
|
||||
include!(concat!(env!("OUT_DIR"), "/provider_metadata_fn.rs"))
|
||||
}
|
||||
@@ -1678,4 +1694,36 @@ mod tests {
|
||||
eprintln!("skipped providers:\n{}", skipped.join("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ensure_proxy_url_host_prepends_host_to_relative_proxy_urls() {
|
||||
// Host-relative proxy URL (as produced when public_url_base was None,
|
||||
// e.g. by runtime validation) gets the request host applied.
|
||||
assert_eq!(
|
||||
ensure_proxy_url_host("/proxy/sxyprn/post/abc", "http://hottub:18080"),
|
||||
"http://hottub:18080/proxy/sxyprn/post/abc"
|
||||
);
|
||||
// A trailing slash on the base is not duplicated.
|
||||
assert_eq!(
|
||||
ensure_proxy_url_host("/proxy/sxyprn/post/abc", "http://hottub:18080/"),
|
||||
"http://hottub:18080/proxy/sxyprn/post/abc"
|
||||
);
|
||||
// Already-absolute URLs are left untouched.
|
||||
assert_eq!(
|
||||
ensure_proxy_url_host("https://cdn.example/v.mp4", "http://hottub:18080"),
|
||||
"https://cdn.example/v.mp4"
|
||||
);
|
||||
assert_eq!(
|
||||
ensure_proxy_url_host(
|
||||
"http://other:18080/proxy/sxyprn/post/abc",
|
||||
"http://hottub:18080"
|
||||
),
|
||||
"http://other:18080/proxy/sxyprn/post/abc"
|
||||
);
|
||||
// Empty base leaves the URL as-is rather than producing a bare host.
|
||||
assert_eq!(
|
||||
ensure_proxy_url_host("/proxy/sxyprn/post/abc", ""),
|
||||
"/proxy/sxyprn/post/abc"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,6 +194,22 @@ impl VideoItem {
|
||||
self
|
||||
}
|
||||
|
||||
/// Re-applies the request host to every host-relative proxy URL on this item
|
||||
/// (its `url`, `preview`, and each format's `url`). Cached items may have been
|
||||
/// built without a host; see [`crate::providers::ensure_proxy_url_host`].
|
||||
pub fn ensure_proxy_host(&mut self, public_url_base: &str) {
|
||||
self.url = crate::providers::ensure_proxy_url_host(&self.url, public_url_base);
|
||||
if let Some(preview) = &self.preview {
|
||||
self.preview =
|
||||
Some(crate::providers::ensure_proxy_url_host(preview, public_url_base));
|
||||
}
|
||||
if let Some(formats) = &mut self.formats {
|
||||
for format in formats.iter_mut() {
|
||||
format.url = crate::providers::ensure_proxy_url_host(&format.url, public_url_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(hottub_single_provider),
|
||||
hottub_provider = "chaturbate",
|
||||
|
||||
Reference in New Issue
Block a user