mixed refactor
This commit is contained in:
@@ -40,6 +40,32 @@ public class StreamProxyController : ControllerBase
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds CORS headers to allow cross-origin requests from hls.js in browsers.
|
||||
/// </summary>
|
||||
private void AddCorsHeaders()
|
||||
{
|
||||
Response.Headers["Access-Control-Allow-Origin"] = "*";
|
||||
Response.Headers["Access-Control-Allow-Methods"] = "GET, HEAD, OPTIONS";
|
||||
Response.Headers["Access-Control-Allow-Headers"] = "Content-Type, Range, Accept, Origin";
|
||||
Response.Headers["Access-Control-Expose-Headers"] = "Content-Length, Content-Range, Accept-Ranges";
|
||||
Response.Headers["Access-Control-Max-Age"] = "86400"; // Cache preflight for 24 hours
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles CORS preflight OPTIONS requests for all proxy endpoints.
|
||||
/// </summary>
|
||||
/// <returns>Empty response with CORS headers.</returns>
|
||||
[HttpOptions("{itemId}/master.m3u8")]
|
||||
[HttpOptions("{itemId}/{manifestPath}.m3u8")]
|
||||
[HttpOptions("{itemId}/{*segmentPath}")]
|
||||
[AllowAnonymous]
|
||||
public IActionResult HandleOptions()
|
||||
{
|
||||
AddCorsHeaders();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Proxies HLS master manifest requests.
|
||||
/// </summary>
|
||||
@@ -54,6 +80,7 @@ public class StreamProxyController : ControllerBase
|
||||
[FromRoute] string itemId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
AddCorsHeaders();
|
||||
_logger.LogInformation("Proxy request for master manifest - Path ItemId: {PathItemId}, Query params: {QueryString}", itemId, Request.QueryString);
|
||||
|
||||
// Try to resolve the actual item ID (path ID might be a session ID during transcoding)
|
||||
@@ -119,6 +146,7 @@ public class StreamProxyController : ControllerBase
|
||||
[FromRoute] string manifestPath,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
AddCorsHeaders();
|
||||
var fullPath = $"{manifestPath}.m3u8";
|
||||
_logger.LogInformation("Proxy request for variant manifest - ItemId: {ItemId}, Path: {Path}", itemId, fullPath);
|
||||
|
||||
@@ -168,6 +196,7 @@ public class StreamProxyController : ControllerBase
|
||||
[FromRoute] string segmentPath,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
AddCorsHeaders();
|
||||
_logger.LogDebug("Proxy request for segment - ItemId: {ItemId}, Path: {SegmentPath}", itemId, segmentPath);
|
||||
|
||||
// Try to resolve the actual item ID
|
||||
@@ -244,8 +273,8 @@ public class StreamProxyController : ControllerBase
|
||||
return queryItemId.ToString();
|
||||
}
|
||||
|
||||
// No query parameters - use path ID as-is (TRANSCODING SESSION ID CASE)
|
||||
_logger.LogWarning("⚠️ No query parameters found, using path ID as-is: {PathItemId} (likely transcoding session ID)", pathItemId);
|
||||
// No query parameters - use path ID as-is (normal case for segments and transcoding sessions)
|
||||
_logger.LogDebug("No query parameters, using path ID as-is: {PathItemId}", pathItemId);
|
||||
return pathItemId;
|
||||
}
|
||||
|
||||
@@ -272,28 +301,52 @@ public class StreamProxyController : ControllerBase
|
||||
queryParams = string.Empty;
|
||||
}
|
||||
|
||||
// Helper function to rewrite a single URL
|
||||
string RewriteUrl(string url)
|
||||
{
|
||||
if (url.Contains("://", StringComparison.Ordinal))
|
||||
{
|
||||
// Absolute URL - extract filename and rewrite
|
||||
var uri = new Uri(url.Trim());
|
||||
var segments = uri.AbsolutePath.Split('/');
|
||||
var fileName = segments[^1];
|
||||
return $"{baseProxyUrl}/{fileName}{queryParams}";
|
||||
}
|
||||
|
||||
// Relative URL - rewrite to proxy
|
||||
return $"{baseProxyUrl}/{url.Trim()}{queryParams}";
|
||||
}
|
||||
|
||||
var lines = manifestContent.Split('\n');
|
||||
var result = new System.Text.StringBuilder();
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (line.StartsWith('#') || string.IsNullOrWhiteSpace(line))
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
// Keep metadata and blank lines as-is
|
||||
result.AppendLine(line);
|
||||
}
|
||||
else if (line.Contains("://", StringComparison.Ordinal))
|
||||
else if (line.StartsWith('#'))
|
||||
{
|
||||
// Absolute URL - extract the path and rewrite
|
||||
var uri = new Uri(line.Trim());
|
||||
var segments = uri.AbsolutePath.Split('/');
|
||||
var fileName = segments[^1];
|
||||
result.AppendLine(CultureInfo.InvariantCulture, $"{baseProxyUrl}/{fileName}{queryParams}");
|
||||
// HLS tag line - check for URI="..." attributes (e.g., #EXT-X-MAP:URI="init.mp4")
|
||||
if (line.Contains("URI=\"", StringComparison.Ordinal))
|
||||
{
|
||||
var rewrittenLine = System.Text.RegularExpressions.Regex.Replace(
|
||||
line,
|
||||
@"URI=""([^""]+)""",
|
||||
match => $"URI=\"{RewriteUrl(match.Groups[1].Value)}\"");
|
||||
result.AppendLine(rewrittenLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep other metadata lines as-is
|
||||
result.AppendLine(line);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Relative URL - rewrite to proxy
|
||||
result.AppendLine(CultureInfo.InvariantCulture, $"{baseProxyUrl}/{line.Trim()}{queryParams}");
|
||||
// Non-tag line with URL - rewrite it
|
||||
result.AppendLine(RewriteUrl(line));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user