This commit is contained in:
Radek Davidek 2026-03-04 14:30:34 +01:00
parent 43c46e266d
commit 4ea3d96496

View File

@ -245,42 +245,56 @@ public final class XtreamPlayerApplication {
} }
try { try {
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(target) List<URI> attempts = candidateUris(target);
.GET() HttpResponse<byte[]> response = null;
.timeout(Duration.ofSeconds(60)) URI usedTarget = target;
.header("User-Agent", firstNonBlank( for (URI candidate : attempts) {
exchange.getRequestHeaders().getFirst("User-Agent"), HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(candidate)
DEFAULT_BROWSER_UA .GET()
)) .timeout(Duration.ofSeconds(60))
.header("Accept", firstNonBlank( .header("User-Agent", firstNonBlank(
exchange.getRequestHeaders().getFirst("Accept"), exchange.getRequestHeaders().getFirst("User-Agent"),
"*/*" DEFAULT_BROWSER_UA
)); ))
copyRequestHeaderIfPresent(exchange, requestBuilder, "Range"); .header("Accept", firstNonBlank(
copyRequestHeaderIfPresent(exchange, requestBuilder, "If-Range"); exchange.getRequestHeaders().getFirst("Accept"),
if (!sourceUrl.isBlank()) { "*/*"
requestBuilder.header("Referer", sourceUrl); ));
String origin = originFromUrl(sourceUrl); copyRequestHeaderIfPresent(exchange, requestBuilder, "Range");
if (!origin.isBlank()) { copyRequestHeaderIfPresent(exchange, requestBuilder, "If-Range");
requestBuilder.header("Origin", origin); if (!sourceUrl.isBlank()) {
requestBuilder.header("Referer", sourceUrl);
String origin = originFromUrl(sourceUrl);
if (!origin.isBlank()) {
requestBuilder.header("Origin", origin);
}
}
HttpRequest request = requestBuilder.build();
HttpResponse<byte[]> candidateResponse = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofByteArray());
response = candidateResponse;
usedTarget = candidate;
if (candidateResponse.statusCode() < 400) {
break;
} }
} }
HttpRequest request = requestBuilder.build(); if (response == null) {
HttpResponse<byte[]> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofByteArray()); writeJson(exchange, 502, errorJson("Unable to proxy stream: empty upstream response."));
return;
}
String contentType = response.headers().firstValue("Content-Type").orElse("application/octet-stream"); String contentType = response.headers().firstValue("Content-Type").orElse("application/octet-stream");
byte[] body = response.body() == null ? new byte[0] : response.body(); byte[] body = response.body() == null ? new byte[0] : response.body();
if (response.statusCode() >= 400) { if (response.statusCode() >= 400) {
LOGGER.warn( LOGGER.warn(
"Stream proxy upstream returned status={} uri={} bytes={} contentType={}", "Stream proxy upstream returned status={} uri={} bytes={} contentType={}",
response.statusCode(), response.statusCode(),
maskUri(target), maskUri(usedTarget),
body.length, body.length,
contentType contentType
); );
} }
if (isHlsPlaylist(target, contentType)) { if (isHlsPlaylist(usedTarget, contentType)) {
String rewritten = rewritePlaylistForProxy(target, body); String rewritten = rewritePlaylistForProxy(usedTarget, body);
exchange.getResponseHeaders().set("Content-Type", "application/vnd.apple.mpegurl; charset=utf-8"); exchange.getResponseHeaders().set("Content-Type", "application/vnd.apple.mpegurl; charset=utf-8");
writeBytes(exchange, response.statusCode(), rewritten.getBytes(StandardCharsets.UTF_8), writeBytes(exchange, response.statusCode(), rewritten.getBytes(StandardCharsets.UTF_8),
"application/vnd.apple.mpegurl; charset=utf-8"); "application/vnd.apple.mpegurl; charset=utf-8");