diff --git a/SpotifyAPI.Web.Examples/Example.TokenSwap/Client/Program.cs b/SpotifyAPI.Web.Examples/Example.TokenSwap/Client/Program.cs
index 8fe7cd54..3e69cac0 100644
--- a/SpotifyAPI.Web.Examples/Example.TokenSwap/Client/Program.cs
+++ b/SpotifyAPI.Web.Examples/Example.TokenSwap/Client/Program.cs
@@ -11,7 +11,7 @@ namespace Client
private static readonly string clientId = Environment.GetEnvironmentVariable("SPOTIFY_CLIENT_ID");
private static EmbedIOAuthServer _server;
- public static async Task Main(string[] args)
+ public static async Task Main()
{
_server = new EmbedIOAuthServer(new Uri("http://localhost:5000/callback"), 5000);
await _server.Start();
diff --git a/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs b/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs
index 7c490578..39816108 100644
--- a/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs
+++ b/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs
@@ -11,7 +11,7 @@ namespace SpotifyAPI.Web
/// Requests a new token using client_ids and client_secrets.
/// If the token is expired, simply call the funtion again to get a new token
///
- ///
+ /// The request-model which contains required and optional parameters.
///
/// https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow
///
@@ -21,7 +21,7 @@ namespace SpotifyAPI.Web
///
/// Refresh an already received token via Authorization Code Auth
///
- ///
+ /// The request-model which contains required and optional parameters.
///
/// https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
///
@@ -31,11 +31,31 @@ namespace SpotifyAPI.Web
///
/// Reequest an initial token via Authorization Code Auth
///
- ///
+ /// The request-model which contains required and optional parameters.
///
/// https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
///
///
Task RequestToken(AuthorizationCodeTokenRequest request);
+
+ ///
+ /// Swaps out a received code with a access token using a remote server
+ ///
+ /// The request-model which contains required and optional parameters.
+ ///
+ /// https://developer.spotify.com/documentation/ios/guides/token-swap-and-refresh/
+ ///
+ ///
+ Task RequestToken(TokenSwapTokenRequest request);
+
+ ///
+ /// Gets a refreshed access token using an already received refresh token using a remote server
+ ///
+ ///
+ ///
+ /// https://developer.spotify.com/documentation/ios/guides/token-swap-and-refresh/
+ ///
+ ///
+ Task RequestToken(TokenSwapRefreshRequest request);
}
}
diff --git a/SpotifyAPI.Web/Clients/OAuthClient.cs b/SpotifyAPI.Web/Clients/OAuthClient.cs
index 849e9b35..8176f368 100644
--- a/SpotifyAPI.Web/Clients/OAuthClient.cs
+++ b/SpotifyAPI.Web/Clients/OAuthClient.cs
@@ -15,26 +15,67 @@ namespace SpotifyAPI.Web
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062")]
public OAuthClient(SpotifyClientConfig config) : base(ValidateConfig(config)) { }
+ ///
+ /// Requests a new token using client_ids and client_secrets.
+ /// If the token is expired, simply call the funtion again to get a new token
+ ///
+ /// The request-model which contains required and optional parameters.
+ ///
+ /// https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow
+ ///
+ /// 1
public Task RequestToken(ClientCredentialsRequest request)
{
return RequestToken(request, API);
}
+ ///
+ /// Refresh an already received token via Authorization Code Auth
+ ///
+ /// The request-model which contains required and optional parameters.
+ ///
+ /// https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
+ ///
+ ///
public Task RequestToken(AuthorizationCodeRefreshRequest request)
{
return RequestToken(request, API);
}
+ ///
+ /// Reequest an initial token via Authorization Code Auth
+ ///
+ /// The request-model which contains required and optional parameters.
+ ///
+ /// https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
+ ///
+ ///
public Task RequestToken(AuthorizationCodeTokenRequest request)
{
return RequestToken(request, API);
}
+ ///
+ /// Swaps out a received code with a access token using a remote server
+ ///
+ /// The request-model which contains required and optional parameters.
+ ///
+ /// https://developer.spotify.com/documentation/ios/guides/token-swap-and-refresh/
+ ///
+ ///
public Task RequestToken(TokenSwapTokenRequest request)
{
return RequestToken(request, API);
}
+ ///
+ /// Gets a refreshed access token using an already received refresh token using a remote server
+ ///
+ ///
+ ///
+ /// https://developer.spotify.com/documentation/ios/guides/token-swap-and-refresh/
+ ///
+ ///
public Task RequestToken(TokenSwapRefreshRequest request)
{
return RequestToken(request, API);
diff --git a/SpotifyAPI.Web/Exceptions/APITooManyRequestsException.cs b/SpotifyAPI.Web/Exceptions/APITooManyRequestsException.cs
new file mode 100644
index 00000000..acfdac69
--- /dev/null
+++ b/SpotifyAPI.Web/Exceptions/APITooManyRequestsException.cs
@@ -0,0 +1,31 @@
+using System.Globalization;
+using System.Runtime.Serialization;
+using System;
+using SpotifyAPI.Web.Http;
+
+namespace SpotifyAPI.Web
+{
+ [Serializable]
+ public class APITooManyRequestsException : APIException
+ {
+ public TimeSpan RetryAfter { get; }
+
+ public APITooManyRequestsException(IResponse response) : base(response)
+ {
+ Ensure.ArgumentNotNull(response, nameof(response));
+
+ if (response.Headers.TryGetValue("Retry-After", out string retryAfter))
+ {
+ RetryAfter = TimeSpan.FromSeconds(int.Parse(retryAfter, CultureInfo.InvariantCulture));
+ }
+ }
+
+ public APITooManyRequestsException() { }
+
+ public APITooManyRequestsException(string message) : base(message) { }
+
+ public APITooManyRequestsException(string message, Exception innerException) : base(message, innerException) { }
+
+ protected APITooManyRequestsException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+ }
+}
diff --git a/SpotifyAPI.Web/Http/APIConnector.cs b/SpotifyAPI.Web/Http/APIConnector.cs
index 991cd5bd..3dfa7c76 100644
--- a/SpotifyAPI.Web/Http/APIConnector.cs
+++ b/SpotifyAPI.Web/Http/APIConnector.cs
@@ -283,6 +283,8 @@ namespace SpotifyAPI.Web.Http
{
case HttpStatusCode.Unauthorized:
throw new APIUnauthorizedException(response);
+ case HttpStatusCode.TooManyRequests:
+ throw new APITooManyRequestsException(response);
default:
throw new APIException(response);
}
diff --git a/SpotifyAPI.Web/Http/Authenticators/AuthorizationCodeAuthenticator.cs b/SpotifyAPI.Web/Http/Authenticators/AuthorizationCodeAuthenticator.cs
index e4059ebd..3c166c7f 100644
--- a/SpotifyAPI.Web/Http/Authenticators/AuthorizationCodeAuthenticator.cs
+++ b/SpotifyAPI.Web/Http/Authenticators/AuthorizationCodeAuthenticator.cs
@@ -9,8 +9,6 @@ namespace SpotifyAPI.Web.Http
///
public class AuthorizationCodeAuthenticator : IAuthenticator
{
- public event EventHandler? TokenRefreshed;
-
///
/// Initiate a new instance. The token will be refreshed once it expires.
/// The initialToken will be updated with the new values on refresh!
@@ -26,6 +24,12 @@ namespace SpotifyAPI.Web.Http
ClientSecret = clientSecret;
}
+ ///
+ /// This event is called once a new refreshed token was aquired
+ ///
+ public event EventHandler? TokenRefreshed;
+
+
///
/// The ClientID, defined in a spotify application in your Spotify Developer Dashboard
///