diff --git a/backend/src/api/endpoints/hls_api.rs b/backend/src/api/endpoints/hls_api.rs index de49bf755..827997fdb 100644 --- a/backend/src/api/endpoints/hls_api.rs +++ b/backend/src/api/endpoints/hls_api.rs @@ -1,4 +1,4 @@ -use crate::api::api_utils::{get_headers_from_request, try_option_bad_request}; +use crate::api::api_utils::{get_headers_from_request, try_option_bad_request, HeaderFilter}; use crate::api::api_utils::try_unwrap_body; use crate::api::api_utils::{ force_provider_stream_response, get_stream_alternative_url, is_seek_request, @@ -94,9 +94,10 @@ pub(in crate::api) async fn handle_hls_stream_request( }; - let filter_header = None; - let req_headers = get_headers_from_request(req_headers, &filter_header); - let headers = request::get_request_headers(None, Some(&req_headers)); + // Don't forward Range on playlist fetch; segments use original headers in provider path + let filter_header: HeaderFilter = Some(Box::new(|name: &str| !name.eq_ignore_ascii_case("range"))); + let forwarded = get_headers_from_request(req_headers, &filter_header); + let headers = request::get_request_headers(None, Some(&forwarded)); let input_source = InputSource::from(input).with_url(request_url); match request::download_text_content( Arc::clone(&app_state.http_client.load()), diff --git a/backend/src/api/endpoints/m3u_api.rs b/backend/src/api/endpoints/m3u_api.rs index 9581aaa70..b36f3fbd3 100644 --- a/backend/src/api/endpoints/m3u_api.rs +++ b/backend/src/api/endpoints/m3u_api.rs @@ -217,7 +217,7 @@ async fn m3u_api_stream( &pli.url, pli.virtual_id, &input, - &req_headers, + req_headers, connection_permission, ) .await diff --git a/backend/src/api/endpoints/xtream_api.rs b/backend/src/api/endpoints/xtream_api.rs index 25f3bd012..fd00ebc28 100644 --- a/backend/src/api/endpoints/xtream_api.rs +++ b/backend/src/api/endpoints/xtream_api.rs @@ -381,7 +381,7 @@ async fn xtream_player_api_stream( &stream_url, pli.virtual_id, &input, - &req_headers, + req_headers, connection_permission, ) .await @@ -484,7 +484,7 @@ async fn xtream_player_api_stream_with_token( &pli.url, pli.virtual_id, &input, - &req_headers, + req_headers, UserConnectionPermission::Allowed, ) .await diff --git a/backend/src/utils/network/request.rs b/backend/src/utils/network/request.rs index 26b4588d7..185171304 100644 --- a/backend/src/utils/network/request.rs +++ b/backend/src/utils/network/request.rs @@ -304,9 +304,11 @@ pub async fn get_remote_content_as_stream( async fn get_remote_content(client: Arc, input: &InputSource, headers: Option<&HeaderMap>, url: &Url) -> Result<(String, String), Error> { let start_time = Instant::now(); - let custom_headers: Option>> = headers.map(|h| h.iter().map(|(k, v)| (k.as_str().to_string(), v.as_bytes().to_vec())).collect()); - let headers = get_request_headers(Some(&input.headers), custom_headers.as_ref()); - let headers: HashMap = headers.iter().map(|(k, v)| (k.as_str().to_string(), String::from_utf8_lossy(&*v.as_bytes().to_vec()).to_string())).collect(); + + let custom_headers = headers.map(|h| { + h.iter().map(|(k, v)| (k.as_str().to_string(), v.as_bytes().to_vec())).collect::>()}); + let merged = get_request_headers(Some(&input.headers), custom_headers.as_ref()); + let headers: HashMap = merged.iter().map(|(k, v)| (k.as_str().to_string(), String::from_utf8_lossy(v.as_bytes()).to_string())).collect(); let (mut stream, response_url) = get_remote_content_as_stream(client.clone(), url, input.method, Some(&headers)).await.map_err(|e| str_to_io_error(&format!("Failed to read content: {e}")))?; let mut content = String::new();