mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-09 23:55:10 -05:00
#31 (upstream) Fix iOS client local streaming issues
This commit is contained in:
@@ -16,6 +16,7 @@ builder.Services.AddControllers();
|
|||||||
builder.Services.AddHttpClient();
|
builder.Services.AddHttpClient();
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen();
|
||||||
|
builder.Services.AddHttpContextAccessor();
|
||||||
|
|
||||||
// Exception handling
|
// Exception handling
|
||||||
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
|
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
|
||||||
|
|||||||
@@ -10,13 +10,16 @@ public class SubsonicProxyService
|
|||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private readonly SubsonicSettings _subsonicSettings;
|
private readonly SubsonicSettings _subsonicSettings;
|
||||||
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
|
||||||
public SubsonicProxyService(
|
public SubsonicProxyService(
|
||||||
IHttpClientFactory httpClientFactory,
|
IHttpClientFactory httpClientFactory,
|
||||||
Microsoft.Extensions.Options.IOptions<SubsonicSettings> subsonicSettings)
|
Microsoft.Extensions.Options.IOptions<SubsonicSettings> subsonicSettings,
|
||||||
|
IHttpContextAccessor httpContextAccessor)
|
||||||
{
|
{
|
||||||
_httpClient = httpClientFactory.CreateClient();
|
_httpClient = httpClientFactory.CreateClient();
|
||||||
_subsonicSettings = subsonicSettings.Value;
|
_subsonicSettings = subsonicSettings.Value;
|
||||||
|
_httpContextAccessor = httpContextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -66,11 +69,33 @@ public class SubsonicProxyService
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Get HTTP context for request/response forwarding
|
||||||
|
var httpContext = _httpContextAccessor.HttpContext;
|
||||||
|
if (httpContext == null)
|
||||||
|
{
|
||||||
|
return new StatusCodeResult(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
var incomingRequest = httpContext.Request;
|
||||||
|
var outgoingResponse = httpContext.Response;
|
||||||
|
|
||||||
var query = string.Join("&", parameters.Select(kv =>
|
var query = string.Join("&", parameters.Select(kv =>
|
||||||
$"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value)}"));
|
$"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value)}"));
|
||||||
var url = $"{_subsonicSettings.Url}/rest/stream?{query}";
|
var url = $"{_subsonicSettings.Url}/rest/stream?{query}";
|
||||||
|
|
||||||
using var request = new HttpRequestMessage(HttpMethod.Get, url);
|
using var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||||
|
|
||||||
|
// Forward Range headers (fix for iOS client)
|
||||||
|
if (incomingRequest.Headers.TryGetValue("Range", out var range))
|
||||||
|
{
|
||||||
|
request.Headers.TryAddWithoutValidation("Range", range.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (incomingRequest.Headers.TryGetValue("If-Range", out var ifRange))
|
||||||
|
{
|
||||||
|
request.Headers.TryAddWithoutValidation("If-Range", ifRange.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
var response = await _httpClient.SendAsync(
|
var response = await _httpClient.SendAsync(
|
||||||
request,
|
request,
|
||||||
HttpCompletionOption.ResponseHeadersRead,
|
HttpCompletionOption.ResponseHeadersRead,
|
||||||
@@ -81,6 +106,23 @@ public class SubsonicProxyService
|
|||||||
return new StatusCodeResult((int)response.StatusCode);
|
return new StatusCodeResult((int)response.StatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iterate over and forward streaming-required headers
|
||||||
|
foreach (var header in new[]
|
||||||
|
{
|
||||||
|
"Accept-Ranges",
|
||||||
|
"Content-Range",
|
||||||
|
"Content-Length",
|
||||||
|
"ETag",
|
||||||
|
"Last-Modified"
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if (response.Headers.TryGetValues(header, out var values) ||
|
||||||
|
response.Content.Headers.TryGetValues(header, out values))
|
||||||
|
{
|
||||||
|
outgoingResponse.Headers[header] = values.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||||
var contentType = response.Content.Headers.ContentType?.ToString() ?? "audio/mpeg";
|
var contentType = response.Content.Headers.ContentType?.ToString() ?? "audio/mpeg";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user