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 } } } }