using Microsoft.AspNetCore.WebUtilities;
using System.Text.Json;
namespace octo_fiesta.Services.Subsonic;
///
/// Service responsible for parsing HTTP request parameters from various sources
/// (query string, form body, JSON body) for Subsonic API requests.
///
public class SubsonicRequestParser
{
///
/// Extracts all parameters from an HTTP request (query parameters + body parameters).
/// Supports multiple content types: application/x-www-form-urlencoded and application/json.
///
/// The HTTP request to parse
/// Dictionary containing all extracted parameters
public async Task> ExtractAllParametersAsync(HttpRequest request)
{
var parameters = new Dictionary();
// Get query parameters
foreach (var query in request.Query)
{
parameters[query.Key] = query.Value.ToString();
}
// Get body parameters
if (request.ContentLength > 0 || request.ContentType != null)
{
// Handle application/x-www-form-urlencoded (OpenSubsonic formPost extension)
if (request.HasFormContentType)
{
await ExtractFormParametersAsync(request, parameters);
}
// Handle application/json
else if (request.ContentType?.Contains("application/json") == true)
{
await ExtractJsonParametersAsync(request, parameters);
}
}
return parameters;
}
///
/// Extracts parameters from form-encoded request body.
///
private async Task ExtractFormParametersAsync(HttpRequest request, Dictionary parameters)
{
try
{
var form = await request.ReadFormAsync();
foreach (var field in form)
{
parameters[field.Key] = field.Value.ToString();
}
}
catch
{
// Fall back to manual parsing if ReadFormAsync fails
request.EnableBuffering();
using var reader = new StreamReader(request.Body, leaveOpen: true);
var body = await reader.ReadToEndAsync();
request.Body.Position = 0;
if (!string.IsNullOrEmpty(body))
{
var formParams = QueryHelpers.ParseQuery(body);
foreach (var param in formParams)
{
parameters[param.Key] = param.Value.ToString();
}
}
}
}
///
/// Extracts parameters from JSON request body.
///
private async Task ExtractJsonParametersAsync(HttpRequest request, Dictionary parameters)
{
using var reader = new StreamReader(request.Body);
var body = await reader.ReadToEndAsync();
if (!string.IsNullOrEmpty(body))
{
try
{
var bodyParams = JsonSerializer.Deserialize>(body);
if (bodyParams != null)
{
foreach (var param in bodyParams)
{
parameters[param.Key] = param.Value?.ToString() ?? "";
}
}
}
catch (JsonException)
{
// Ignore JSON parsing errors
}
}
}
}