diff --git a/src/NzbDrone.Host/Startup.cs b/src/NzbDrone.Host/Startup.cs index 2d80bf7fb..253e1abee 100644 --- a/src/NzbDrone.Host/Startup.cs +++ b/src/NzbDrone.Host/Startup.cs @@ -159,6 +159,8 @@ namespace NzbDrone.Host { { apikeyQuery, Array.Empty() } }); + + c.DescribeAllParametersInCamelCase(); }); services diff --git a/src/NzbDrone.Integration.Test/Client/ClientBase.cs b/src/NzbDrone.Integration.Test/Client/ClientBase.cs index 7adb2a758..6f4bb9011 100644 --- a/src/NzbDrone.Integration.Test/Client/ClientBase.cs +++ b/src/NzbDrone.Integration.Test/Client/ClientBase.cs @@ -102,7 +102,7 @@ namespace NzbDrone.Integration.Test.Client return Get>(request); } - public PagingResource GetPaged(int pageNumber, int pageSize, string sortKey, string sortDir, string filterKey = null, string filterValue = null) + public PagingResource GetPaged(int pageNumber, int pageSize, string sortKey, string sortDir, string filterKey = null, object filterValue = null) { var request = BuildRequest(); request.AddParameter("page", pageNumber); @@ -112,8 +112,7 @@ namespace NzbDrone.Integration.Test.Client if (filterKey != null && filterValue != null) { - request.AddParameter("filterKey", filterKey); - request.AddParameter("filterValue", filterValue); + request.AddParameter(filterKey, filterValue); } return Get>(request); diff --git a/src/Radarr.Api.V3/Blocklist/BlocklistController.cs b/src/Radarr.Api.V3/Blocklist/BlocklistController.cs index 54b0fe88c..3f65d40d9 100644 --- a/src/Radarr.Api.V3/Blocklist/BlocklistController.cs +++ b/src/Radarr.Api.V3/Blocklist/BlocklistController.cs @@ -25,9 +25,9 @@ namespace Radarr.Api.V3.Blocklist [HttpGet] [Produces("application/json")] - public PagingResource GetBlocklist() + public PagingResource GetBlocklist([FromQuery] PagingRequestResource paging) { - var pagingResource = Request.ReadPagingResourceFromRequest(); + var pagingResource = new PagingResource(paging); var pagingSpec = pagingResource.MapToPagingSpec("date", SortDirection.Descending); return pagingSpec.ApplyToPage(_blocklistService.Paged, model => BlocklistResourceMapper.MapToResource(model, _formatCalculator)); diff --git a/src/Radarr.Api.V3/History/HistoryController.cs b/src/Radarr.Api.V3/History/HistoryController.cs index 6e0091f9c..70ff758c1 100644 --- a/src/Radarr.Api.V3/History/HistoryController.cs +++ b/src/Radarr.Api.V3/History/HistoryController.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc; +using NzbDrone.Common.Extensions; using NzbDrone.Core.CustomFormats; using NzbDrone.Core.Datastore; using NzbDrone.Core.DecisionEngine.Specifications; @@ -59,23 +60,20 @@ namespace Radarr.Api.V3.History } [HttpGet] - public PagingResource GetHistory(bool includeMovie) + [Produces("application/json")] + public PagingResource GetHistory([FromQuery] PagingRequestResource paging, bool includeMovie, int? eventType, string downloadId) { - var pagingResource = Request.ReadPagingResourceFromRequest(); + var pagingResource = new PagingResource(paging); var pagingSpec = pagingResource.MapToPagingSpec("date", SortDirection.Descending); - var eventTypeFilter = pagingResource.Filters.FirstOrDefault(f => f.Key == "eventType"); - var downloadIdFilter = pagingResource.Filters.FirstOrDefault(f => f.Key == "downloadId"); - - if (eventTypeFilter != null) + if (eventType.HasValue) { - var filterValue = (MovieHistoryEventType)Convert.ToInt32(eventTypeFilter.Value); + var filterValue = (MovieHistoryEventType)eventType.Value; pagingSpec.FilterExpressions.Add(v => v.EventType == filterValue); } - if (downloadIdFilter != null) + if (downloadId.IsNotNullOrWhiteSpace()) { - var downloadId = downloadIdFilter.Value; pagingSpec.FilterExpressions.Add(h => h.DownloadId == downloadId); } diff --git a/src/Radarr.Api.V3/Logs/LogController.cs b/src/Radarr.Api.V3/Logs/LogController.cs index 33a1b8b90..a8ba1f14e 100644 --- a/src/Radarr.Api.V3/Logs/LogController.cs +++ b/src/Radarr.Api.V3/Logs/LogController.cs @@ -1,5 +1,5 @@ -using System.Linq; using Microsoft.AspNetCore.Mvc; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Instrumentation; using Radarr.Http; using Radarr.Http.Extensions; @@ -17,9 +17,10 @@ namespace Radarr.Api.V3.Logs } [HttpGet] - public PagingResource GetLogs() + [Produces("application/json")] + public PagingResource GetLogs([FromQuery] PagingRequestResource paging, string level) { - var pagingResource = Request.ReadPagingResourceFromRequest(); + var pagingResource = new PagingResource(paging); var pageSpec = pagingResource.MapToPagingSpec(); if (pageSpec.SortKey == "time") @@ -27,11 +28,9 @@ namespace Radarr.Api.V3.Logs pageSpec.SortKey = "id"; } - var levelFilter = pagingResource.Filters.FirstOrDefault(f => f.Key == "level"); - - if (levelFilter != null) + if (level.IsNotNullOrWhiteSpace()) { - switch (levelFilter.Value) + switch (level) { case "fatal": pageSpec.FilterExpressions.Add(h => h.Level == "Fatal"); diff --git a/src/Radarr.Api.V3/Queue/QueueController.cs b/src/Radarr.Api.V3/Queue/QueueController.cs index 275758b6b..10e5c0a52 100644 --- a/src/Radarr.Api.V3/Queue/QueueController.cs +++ b/src/Radarr.Api.V3/Queue/QueueController.cs @@ -129,9 +129,10 @@ namespace Radarr.Api.V3.Queue } [HttpGet] - public PagingResource GetQueue(bool includeUnknownMovieItems = false, bool includeMovie = false) + [Produces("application/json")] + public PagingResource GetQueue([FromQuery] PagingRequestResource paging, bool includeUnknownMovieItems = false, bool includeMovie = false) { - var pagingResource = Request.ReadPagingResourceFromRequest(); + var pagingResource = new PagingResource(paging); var pagingSpec = pagingResource.MapToPagingSpec("timeleft", SortDirection.Ascending); return pagingSpec.ApplyToPage((spec) => GetQueue(spec, includeUnknownMovieItems), (q) => MapToResource(q, includeMovie)); diff --git a/src/Radarr.Http/Extensions/RequestExtensions.cs b/src/Radarr.Http/Extensions/RequestExtensions.cs index f13712fb4..57260b012 100644 --- a/src/Radarr.Http/Extensions/RequestExtensions.cs +++ b/src/Radarr.Http/Extensions/RequestExtensions.cs @@ -4,7 +4,6 @@ using System.Linq; using Microsoft.AspNetCore.Http; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Core.Datastore; -using NzbDrone.Core.Exceptions; namespace Radarr.Http.Extensions { @@ -52,80 +51,6 @@ namespace Radarr.Http.Extensions return defaultValue; } - public static PagingResource ReadPagingResourceFromRequest(this HttpRequest request) - { - if (!int.TryParse(request.Query["PageSize"].ToString(), out var pageSize)) - { - pageSize = 10; - } - - if (!int.TryParse(request.Query["Page"].ToString(), out var page)) - { - page = 1; - } - - var pagingResource = new PagingResource - { - PageSize = pageSize, - Page = page, - Filters = new List() - }; - - if (request.Query["SortKey"].Any()) - { - var sortKey = request.Query["SortKey"].ToString(); - - if (!VALID_SORT_KEYS.Contains(sortKey) && - !TableMapping.Mapper.IsValidSortKey(sortKey)) - { - throw new BadRequestException($"Invalid sort key {sortKey}"); - } - - pagingResource.SortKey = sortKey; - - if (request.Query["SortDirection"].Any()) - { - pagingResource.SortDirection = request.Query["SortDirection"].ToString() - .Equals("ascending", StringComparison.InvariantCultureIgnoreCase) - ? SortDirection.Ascending - : SortDirection.Descending; - } - } - - // For backwards compatibility with v2 - if (request.Query["FilterKey"].Any()) - { - var filter = new PagingResourceFilter - { - Key = request.Query["FilterKey"].ToString() - }; - - if (request.Query["FilterValue"].Any()) - { - filter.Value = request.Query["FilterValue"].ToString(); - } - - pagingResource.Filters.Add(filter); - } - - // v3 uses filters in key=value format - foreach (var pair in request.Query) - { - if (EXCLUDED_KEYS.Contains(pair.Key)) - { - continue; - } - - pagingResource.Filters.Add(new PagingResourceFilter - { - Key = pair.Key, - Value = pair.Value.ToString() - }); - } - - return pagingResource; - } - public static PagingResource ApplyToPage(this PagingSpec pagingSpec, Func, PagingSpec> function, Converter mapper) { pagingSpec = function(pagingSpec); diff --git a/src/Radarr.Http/PagingResource.cs b/src/Radarr.Http/PagingResource.cs index 867ee6551..d1ddcaa54 100644 --- a/src/Radarr.Http/PagingResource.cs +++ b/src/Radarr.Http/PagingResource.cs @@ -1,17 +1,39 @@ using System.Collections.Generic; +using System.ComponentModel; using NzbDrone.Core.Datastore; namespace Radarr.Http { + public class PagingRequestResource + { + [DefaultValue(1)] + public int? Page { get; set; } + [DefaultValue(10)] + public int? PageSize { get; set; } + public string SortKey { get; set; } + public SortDirection? SortDirection { get; set; } + } + public class PagingResource { public int Page { get; set; } public int PageSize { get; set; } public string SortKey { get; set; } public SortDirection SortDirection { get; set; } - public List Filters { get; set; } public int TotalRecords { get; set; } public List Records { get; set; } + + public PagingResource() + { + } + + public PagingResource(PagingRequestResource requestResource) + { + Page = requestResource.Page ?? 1; + PageSize = requestResource.PageSize ?? 10; + SortKey = requestResource.SortKey; + SortDirection = requestResource.SortDirection ?? SortDirection.Descending; + } } public static class PagingResourceMapper