(
response: &mut HttpResponseBuilder,
range_str: Option<&String>,
clen: Option<u64>,
resp: &reqwest::Response,
)
| 209 | } |
| 210 | |
| 211 | fn handle_range_response_correction( |
| 212 | response: &mut HttpResponseBuilder, |
| 213 | range_str: Option<&String>, |
| 214 | clen: Option<u64>, |
| 215 | resp: &reqwest::Response, |
| 216 | ) -> Option<()> { |
| 217 | // Check if this is a range request (either in headers or query string) |
| 218 | let has_range_request = resp.headers().contains_key("range") || range_str.is_some(); |
| 219 | |
| 220 | // Only apply correction if we have a range request and response is 200 (should be 206) |
| 221 | if !has_range_request |
| 222 | || !resp.status().is_success() |
| 223 | || resp.status() == reqwest::StatusCode::PARTIAL_CONTENT |
| 224 | { |
| 225 | return None; |
| 226 | } |
| 227 | |
| 228 | // total_size is the full file size from the videoplayback URL's `clen`. The |
| 229 | // upstream Content-Length is only the current chunk; using it as the total |
| 230 | // produced malformed Content-Range that broke itag-18 seek in Chromium. |
| 231 | let total_size = match clen { |
| 232 | Some(c) if c > 0 => c, |
| 233 | _ => resp |
| 234 | .headers() |
| 235 | .get("content-length")? |
| 236 | .to_str() |
| 237 | .ok()? |
| 238 | .parse::<u64>() |
| 239 | .ok()?, |
| 240 | }; |
| 241 | |
| 242 | if total_size == 0 { |
| 243 | return None; |
| 244 | } |
| 245 | |
| 246 | // Parse the range request into start/end positions |
| 247 | let range_request = parse_range(range_str?, total_size)?; |
| 248 | |
| 249 | // Apply proper HTTP range headers |
| 250 | apply_range_headers(response, &range_request); |
| 251 | |
| 252 | Some(()) |
| 253 | } |
| 254 | |
| 255 | fn apply_range_headers(response: &mut HttpResponseBuilder, range_request: &RangeRequest) { |
| 256 | let content_range_value = format!( |
no test coverage detected