Added paginator and some more ConfigureAwaits

This commit is contained in:
Jonas Dellinger 2020-05-05 05:26:37 +02:00
parent d36f360232
commit 40397fa4f6
9 changed files with 134 additions and 20 deletions

View File

@ -44,7 +44,7 @@ namespace SpotifyAPI.Web.Tests
retryHandler.Object, retryHandler.Object,
null null
); );
await apiConnector.SendAPIRequest<string>(new Uri("/me", UriKind.Relative), HttpMethod.Get); await apiConnector.SendAPIRequest<string>(new Uri("/me", UriKind.Relative), HttpMethod.Get).ConfigureAwait(false);
authenticator.Verify(a => a.Apply(It.IsAny<IRequest>()), Times.Once); authenticator.Verify(a => a.Apply(It.IsAny<IRequest>()), Times.Once);
httpClient.Verify(h => h.DoRequest(It.IsAny<IRequest>()), Times.Once); httpClient.Verify(h => h.DoRequest(It.IsAny<IRequest>()), Times.Once);
@ -86,7 +86,7 @@ namespace SpotifyAPI.Web.Tests
retryHandler.Object, retryHandler.Object,
null null
); );
await apiConnector.SendAPIRequest<string>(new Uri("/me", UriKind.Relative), HttpMethod.Get); await apiConnector.SendAPIRequest<string>(new Uri("/me", UriKind.Relative), HttpMethod.Get).ConfigureAwait(false);
serializer.Verify(s => s.SerializeRequest(It.IsAny<IRequest>()), Times.Once); serializer.Verify(s => s.SerializeRequest(It.IsAny<IRequest>()), Times.Once);
authenticator.Verify(a => a.Apply(It.IsAny<IRequest>()), Times.Exactly(2)); authenticator.Verify(a => a.Apply(It.IsAny<IRequest>()), Times.Exactly(2));

View File

@ -29,7 +29,9 @@ namespace SpotifyAPI.Web
{ {
Ensure.ArgumentNotNull(request, nameof(request)); Ensure.ArgumentNotNull(request, nameof(request));
var statusCode = await API.Put(URLs.CurrentUserFollower(), request.BuildQueryParams(), request.BuildBodyParams()); var statusCode = await API
.Put(URLs.CurrentUserFollower(), request.BuildQueryParams(), request.BuildBodyParams())
.ConfigureAwait(false);
return statusCode == HttpStatusCode.OK; return statusCode == HttpStatusCode.OK;
} }
@ -37,7 +39,9 @@ namespace SpotifyAPI.Web
{ {
Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId)); Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId));
var statusCode = await API.Put(URLs.PlaylistFollowers(playlistId), null, null); var statusCode = await API
.Put(URLs.PlaylistFollowers(playlistId), null, null)
.ConfigureAwait(false);
return statusCode == HttpStatusCode.OK; return statusCode == HttpStatusCode.OK;
} }
@ -46,7 +50,9 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId)); Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId));
Ensure.ArgumentNotNull(request, nameof(request)); Ensure.ArgumentNotNull(request, nameof(request));
var statusCode = await API.Put(URLs.PlaylistFollowers(playlistId), null, request.BuildBodyParams()); var statusCode = await API
.Put(URLs.PlaylistFollowers(playlistId), null, request.BuildBodyParams())
.ConfigureAwait(false);
return statusCode == HttpStatusCode.OK; return statusCode == HttpStatusCode.OK;
} }
@ -68,7 +74,9 @@ namespace SpotifyAPI.Web
{ {
Ensure.ArgumentNotNull(request, nameof(request)); Ensure.ArgumentNotNull(request, nameof(request));
var statusCode = await API.Delete(URLs.CurrentUserFollower(), request.BuildQueryParams(), request.BuildBodyParams()); var statusCode = await API
.Delete(URLs.CurrentUserFollower(), request.BuildQueryParams(), request.BuildBodyParams())
.ConfigureAwait(false);
return statusCode == HttpStatusCode.NoContent; return statusCode == HttpStatusCode.NoContent;
} }
@ -76,7 +84,9 @@ namespace SpotifyAPI.Web
{ {
Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId)); Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId));
var statusCode = await API.Delete(URLs.PlaylistFollowers(playlistId), null, null); var statusCode = await API
.Delete(URLs.PlaylistFollowers(playlistId), null, null)
.ConfigureAwait(false);
return statusCode == HttpStatusCode.OK; return statusCode == HttpStatusCode.OK;
} }
} }

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using SpotifyAPI.Web.Http;
namespace SpotifyAPI.Web
{
public interface IPaginator
{
Task<List<T>> Paginate<T>(Paging<T> firstPage, IAPIConnector connector);
Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage, IAPIConnector connector);
}
}

View File

@ -1,7 +1,13 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SpotifyAPI.Web namespace SpotifyAPI.Web
{ {
public interface ISpotifyClient public interface ISpotifyClient
{ {
IPaginator DefaultPaginator { get; }
IUserProfileClient UserProfile { get; } IUserProfileClient UserProfile { get; }
IBrowseClient Browse { get; } IBrowseClient Browse { get; }
@ -15,5 +21,10 @@ namespace SpotifyAPI.Web
IFollowClient Follow { get; } IFollowClient Follow { get; }
ITracksClient Tracks { get; } ITracksClient Tracks { get; }
Task<List<T>> Paginate<T>(Paging<T> firstPage);
Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage);
Task<List<T>> Paginate<T>(Paging<T> firstPage, IPaginator paginator);
Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator paginator);
} }
} }

View File

@ -55,7 +55,7 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId)); Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId));
Ensure.ArgumentNotNullOrEmptyString(base64Jpg, nameof(base64Jpg)); Ensure.ArgumentNotNullOrEmptyString(base64Jpg, nameof(base64Jpg));
var statusCode = await API.PutRaw(URLs.PlaylistImages(playlistId), null, base64Jpg); var statusCode = await API.PutRaw(URLs.PlaylistImages(playlistId), null, base64Jpg).ConfigureAwait(false);
return statusCode == HttpStatusCode.Accepted; return statusCode == HttpStatusCode.Accepted;
} }
@ -102,7 +102,7 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId)); Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId));
Ensure.ArgumentNotNull(request, nameof(request)); Ensure.ArgumentNotNull(request, nameof(request));
var statusCode = await API.Put(URLs.PlaylistTracks(playlistId), null, request.BuildBodyParams()); var statusCode = await API.Put(URLs.PlaylistTracks(playlistId), null, request.BuildBodyParams()).ConfigureAwait(false);
return statusCode == HttpStatusCode.Created; return statusCode == HttpStatusCode.Created;
} }
@ -123,7 +123,7 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId)); Ensure.ArgumentNotNullOrEmptyString(playlistId, nameof(playlistId));
Ensure.ArgumentNotNull(request, nameof(request)); Ensure.ArgumentNotNull(request, nameof(request));
var statusCode = await API.Put(URLs.Playlist(playlistId), null, request.BuildBodyParams()); var statusCode = await API.Put(URLs.Playlist(playlistId), null, request.BuildBodyParams()).ConfigureAwait(false);
return statusCode == HttpStatusCode.OK; return statusCode == HttpStatusCode.OK;
} }

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using SpotifyAPI.Web.Http;
namespace SpotifyAPI.Web
{
public class SimplePaginator : IPaginator
{
protected bool ShouldContinue<T>(List<T> results, Paging<T> page)
{
return true;
}
public async Task<List<T>> Paginate<T>(Paging<T> firstPage, IAPIConnector connector)
{
var page = firstPage;
var results = new List<T>();
results.AddRange(firstPage.Items);
while (page.Next != null && ShouldContinue(results, page))
{
page = await connector.Get<Paging<T>>(new Uri(page.Next, UriKind.Absolute)).ConfigureAwait(false);
results.AddRange(page.Items);
}
return results;
}
public async Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage, IAPIConnector connector)
{
var firstPage = await getFirstPage().ConfigureAwait(false);
return await Paginate(firstPage, connector).ConfigureAwait(false);
}
}
}

View File

@ -1,3 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using SpotifyAPI.Web.Http; using SpotifyAPI.Web.Http;
namespace SpotifyAPI.Web namespace SpotifyAPI.Web
@ -15,6 +18,7 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNull(config, nameof(config)); Ensure.ArgumentNotNull(config, nameof(config));
_apiConnector = config.CreateAPIConnector(); _apiConnector = config.CreateAPIConnector();
DefaultPaginator = config.Paginator;
UserProfile = new UserProfileClient(_apiConnector); UserProfile = new UserProfileClient(_apiConnector);
Browse = new BrowseClient(_apiConnector); Browse = new BrowseClient(_apiConnector);
Shows = new ShowsClient(_apiConnector); Shows = new ShowsClient(_apiConnector);
@ -24,6 +28,8 @@ namespace SpotifyAPI.Web
Tracks = new TracksClient(_apiConnector); Tracks = new TracksClient(_apiConnector);
} }
public IPaginator DefaultPaginator { get; }
public IUserProfileClient UserProfile { get; } public IUserProfileClient UserProfile { get; }
public IBrowseClient Browse { get; } public IBrowseClient Browse { get; }
@ -37,5 +43,29 @@ namespace SpotifyAPI.Web
public IFollowClient Follow { get; } public IFollowClient Follow { get; }
public ITracksClient Tracks { get; } public ITracksClient Tracks { get; }
public Task<List<T>> Paginate<T>(Paging<T> firstPage)
{
return DefaultPaginator.Paginate(firstPage, _apiConnector);
}
public Task<List<T>> Paginate<T>(Paging<T> firstPage, IPaginator paginator)
{
Ensure.ArgumentNotNull(paginator, nameof(paginator));
return paginator.Paginate(firstPage, _apiConnector);
}
public Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage)
{
return DefaultPaginator.Paginate(getFirstPage, _apiConnector);
}
public Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator paginator)
{
Ensure.ArgumentNotNull(paginator, nameof(paginator));
return paginator.Paginate(getFirstPage, _apiConnector);
}
} }
} }

View File

@ -10,6 +10,8 @@ namespace SpotifyAPI.Web
public IJSONSerializer JSONSerializer { get; } public IJSONSerializer JSONSerializer { get; }
public IHTTPClient HTTPClient { get; } public IHTTPClient HTTPClient { get; }
public IHTTPLogger HTTPLogger { get; } public IHTTPLogger HTTPLogger { get; }
public IPaginator Paginator { get; set; }
public IRetryHandler RetryHandler { get; } public IRetryHandler RetryHandler { get; }
/// <summary> /// <summary>
@ -23,13 +25,15 @@ namespace SpotifyAPI.Web
/// <param name="httpClient"></param> /// <param name="httpClient"></param>
/// <param name="retryHandler"></param> /// <param name="retryHandler"></param>
/// <param name="httpLogger"></param> /// <param name="httpLogger"></param>
/// <param name="paginator"></param>
public SpotifyClientConfig( public SpotifyClientConfig(
Uri baseAddress, Uri baseAddress,
IAuthenticator authenticator, IAuthenticator authenticator,
IJSONSerializer jsonSerializer, IJSONSerializer jsonSerializer,
IHTTPClient httpClient, IHTTPClient httpClient,
IRetryHandler retryHandler, IRetryHandler retryHandler,
IHTTPLogger httpLogger IHTTPLogger httpLogger,
IPaginator paginator
) )
{ {
BaseAddress = baseAddress; BaseAddress = baseAddress;
@ -38,6 +42,7 @@ namespace SpotifyAPI.Web
HTTPClient = httpClient; HTTPClient = httpClient;
RetryHandler = retryHandler; RetryHandler = retryHandler;
HTTPLogger = httpLogger; HTTPLogger = httpLogger;
Paginator = paginator;
} }
internal IAPIConnector CreateAPIConnector() internal IAPIConnector CreateAPIConnector()
@ -59,17 +64,26 @@ namespace SpotifyAPI.Web
public SpotifyClientConfig WithRetryHandler(IRetryHandler retryHandler) public SpotifyClientConfig WithRetryHandler(IRetryHandler retryHandler)
{ {
return new SpotifyClientConfig(BaseAddress, Authenticator, JSONSerializer, HTTPClient, retryHandler, HTTPLogger); return new SpotifyClientConfig(
BaseAddress, Authenticator, JSONSerializer, HTTPClient, retryHandler, HTTPLogger, Paginator);
} }
public SpotifyClientConfig WithAuthenticator(IAuthenticator authenticator) public SpotifyClientConfig WithAuthenticator(IAuthenticator authenticator)
{ {
return new SpotifyClientConfig(BaseAddress, authenticator, JSONSerializer, HTTPClient, RetryHandler, HTTPLogger); return new SpotifyClientConfig(
BaseAddress, authenticator, JSONSerializer, HTTPClient, RetryHandler, HTTPLogger, Paginator);
} }
public SpotifyClientConfig WithHTTPLogger(IHTTPLogger httpLogger) public SpotifyClientConfig WithHTTPLogger(IHTTPLogger httpLogger)
{ {
return new SpotifyClientConfig(BaseAddress, Authenticator, JSONSerializer, HTTPClient, RetryHandler, httpLogger); return new SpotifyClientConfig(
BaseAddress, Authenticator, JSONSerializer, HTTPClient, RetryHandler, httpLogger, Paginator);
}
public SpotifyClientConfig WithPaginator(IPaginator paginator)
{
return new SpotifyClientConfig(
BaseAddress, Authenticator, JSONSerializer, HTTPClient, RetryHandler, HTTPLogger, paginator);
} }
public static SpotifyClientConfig CreateDefault(string token, string tokenType = "Bearer") public static SpotifyClientConfig CreateDefault(string token, string tokenType = "Bearer")
@ -96,7 +110,8 @@ namespace SpotifyAPI.Web
new NewtonsoftJSONSerializer(), new NewtonsoftJSONSerializer(),
new NetHttpClient(), new NetHttpClient(),
null, null,
null null,
new SimplePaginator()
); );
} }
} }

View File

@ -59,7 +59,7 @@ namespace SpotifyAPI.Web.Http
{ {
Ensure.ArgumentNotNull(uri, nameof(uri)); Ensure.ArgumentNotNull(uri, nameof(uri));
var response = await SendAPIRequestDetailed(uri, HttpMethod.Delete, parameters, body); var response = await SendAPIRequestDetailed(uri, HttpMethod.Delete, parameters, body).ConfigureAwait(false);
return response.StatusCode; return response.StatusCode;
} }
@ -102,7 +102,7 @@ namespace SpotifyAPI.Web.Http
{ {
Ensure.ArgumentNotNull(uri, nameof(uri)); Ensure.ArgumentNotNull(uri, nameof(uri));
var response = await SendAPIRequestDetailed(uri, HttpMethod.Post, parameters, body); var response = await SendAPIRequestDetailed(uri, HttpMethod.Post, parameters, body).ConfigureAwait(false);
return response.StatusCode; return response.StatusCode;
} }
@ -131,7 +131,7 @@ namespace SpotifyAPI.Web.Http
{ {
Ensure.ArgumentNotNull(uri, nameof(uri)); Ensure.ArgumentNotNull(uri, nameof(uri));
var response = await SendAPIRequestDetailed(uri, HttpMethod.Put, parameters, body); var response = await SendAPIRequestDetailed(uri, HttpMethod.Put, parameters, body).ConfigureAwait(false);
return response.StatusCode; return response.StatusCode;
} }
@ -139,7 +139,7 @@ namespace SpotifyAPI.Web.Http
{ {
Ensure.ArgumentNotNull(uri, nameof(uri)); Ensure.ArgumentNotNull(uri, nameof(uri));
var response = await SendRawRequest(uri, HttpMethod.Put, parameters, body); var response = await SendRawRequest(uri, HttpMethod.Put, parameters, body).ConfigureAwait(false);
return response.StatusCode; return response.StatusCode;
} }
@ -171,7 +171,7 @@ namespace SpotifyAPI.Web.Http
private async Task<IAPIResponse<T>> DoSerializedRequest<T>(IRequest request) private async Task<IAPIResponse<T>> DoSerializedRequest<T>(IRequest request)
{ {
_jsonSerializer.SerializeRequest(request); _jsonSerializer.SerializeRequest(request);
var response = await DoRequest(request); var response = await DoRequest(request).ConfigureAwait(false);
return _jsonSerializer.DeserializeResponse<T>(response); return _jsonSerializer.DeserializeResponse<T>(response);
} }