mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-09 23:55:10 -05:00
fix: add HTTP Range header forwarding for iOS clients
This commit is contained in:
@@ -41,7 +41,7 @@ builder.Services.AddSingleton<ILocalLibraryService, LocalLibraryService>();
|
||||
builder.Services.AddSingleton<SubsonicRequestParser>();
|
||||
builder.Services.AddSingleton<SubsonicResponseBuilder>();
|
||||
builder.Services.AddSingleton<SubsonicModelMapper>();
|
||||
builder.Services.AddSingleton<SubsonicProxyService>();
|
||||
builder.Services.AddScoped<SubsonicProxyService>();
|
||||
|
||||
// Register music service based on configuration
|
||||
if (musicService == MusicService.Qobuz)
|
||||
|
||||
@@ -10,16 +10,16 @@ public class SubsonicProxyService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly SubsonicSettings _subsonicSettings;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public SubsonicProxyService(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
Microsoft.Extensions.Options.IOptions<SubsonicSettings> subsonicSettings,
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_httpClient = httpClientFactory.CreateClient();
|
||||
_subsonicSettings = subsonicSettings.Value;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -69,33 +69,36 @@ public class SubsonicProxyService
|
||||
{
|
||||
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;
|
||||
// Get HTTP context for request/response forwarding
|
||||
var httpContext = _httpContextAccessor.HttpContext;
|
||||
if (httpContext == null)
|
||||
{
|
||||
return new ObjectResult(new { error = "HTTP context not available" })
|
||||
{
|
||||
StatusCode = 500
|
||||
};
|
||||
}
|
||||
|
||||
var incomingRequest = httpContext.Request;
|
||||
var outgoingResponse = httpContext.Response;
|
||||
|
||||
var query = string.Join("&", parameters.Select(kv =>
|
||||
$"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value)}"));
|
||||
var url = $"{_subsonicSettings.Url}/rest/stream?{query}";
|
||||
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
// Forward Range headers for progressive streaming support (iOS clients)
|
||||
if (incomingRequest.Headers.TryGetValue("Range", out var range))
|
||||
{
|
||||
request.Headers.TryAddWithoutValidation("Range", range.ToArray());
|
||||
}
|
||||
|
||||
if (incomingRequest.Headers.TryGetValue("If-Range", out var ifRange))
|
||||
{
|
||||
request.Headers.TryAddWithoutValidation("If-Range", ifRange.ToArray());
|
||||
}
|
||||
|
||||
var response = await _httpClient.SendAsync(
|
||||
request,
|
||||
HttpCompletionOption.ResponseHeadersRead,
|
||||
@@ -106,22 +109,25 @@ public class SubsonicProxyService
|
||||
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();
|
||||
}
|
||||
}
|
||||
// Forward HTTP status code (e.g., 206 Partial Content for range requests)
|
||||
outgoingResponse.StatusCode = (int)response.StatusCode;
|
||||
|
||||
// Forward streaming-required headers from upstream response
|
||||
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 contentType = response.Content.Headers.ContentType?.ToString() ?? "audio/mpeg";
|
||||
|
||||
Reference in New Issue
Block a user