Merge branch 'net5' into ghactions

This commit is contained in:
Jonas Dellinger 2020-11-14 09:43:08 +01:00
commit 6fc8b5a2f1
28 changed files with 111 additions and 90 deletions

View File

@ -2,7 +2,8 @@
"editor.detectIndentation": false,
"editor.insertSpaces": true,
"editor.tabSize": 2,
"omnisharp.enableEditorConfigSupport": true,
"files.associations": {
"*.md": "mdx"
},
}
}

View File

@ -3,7 +3,7 @@ namespace SpotifyAPI.Web.Auth
[System.Serializable]
public class AuthException : System.Exception
{
public AuthException(string error, string state)
public AuthException(string? error, string? state)
{
Error = error;
State = state;

View File

@ -35,16 +35,17 @@ namespace SpotifyAPI.Web.Auth
.WithModule(new ActionModule("/", HttpVerbs.Post, (ctx) =>
{
var query = ctx.Request.QueryString;
if (query["error"] != null)
var error = query["error"];
if (error != null)
{
throw new AuthException(query["error"], query["state"]);
throw new AuthException(error, query["state"]);
}
var requestType = query.Get("request_type");
if (requestType == "token")
{
ImplictGrantReceived?.Invoke(this, new ImplictGrantResponse(
query["access_token"], query["token_type"], int.Parse(query["expires_in"])
query["access_token"]!, query["token_type"]!, int.Parse(query["expires_in"]!)
)
{
State = query["state"]
@ -52,7 +53,7 @@ namespace SpotifyAPI.Web.Auth
}
if (requestType == "code")
{
AuthorizationCodeReceived?.Invoke(this, new AuthorizationCodeResponse(query["code"])
AuthorizationCodeReceived?.Invoke(this, new AuthorizationCodeResponse(query["code"]!)
{
State = query["state"]
});

View File

@ -10,6 +10,6 @@ namespace SpotifyAPI.Web.Auth
}
public string Code { get; set; } = default!;
public string State { get; set; } = default!;
public string? State { get; set; } = default!;
}
}

View File

@ -17,7 +17,7 @@ namespace SpotifyAPI.Web.Auth
public string AccessToken { get; set; } = default!;
public string TokenType { get; set; } = default!;
public int ExpiresIn { get; set; }
public string State { get; set; } = default!;
public string? State { get; set; } = default!;
/// <summary>
/// Auto-Initalized to UTC Now

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.1;netstandard2.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<TargetFrameworks>net5.0;netstandard2.1;netstandard2.0</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<PackageId>SpotifyAPI.Web.Auth</PackageId>
<Title>SpotifyAPI.Web.Auth</Title>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<UserSecretsId>da29eac4-4c22-4a7f-b393-379e83b60998</UserSecretsId>
</PropertyGroup>
<ItemGroup>

View File

@ -1,11 +1,10 @@

<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>

View File

@ -1,10 +1,10 @@
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
</PropertyGroup>

View File

@ -6,8 +6,8 @@
</ItemGroup>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>

View File

@ -6,8 +6,8 @@
</ItemGroup>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;netcoreapp2.2</TargetFrameworks>
<TargetFrameworks>net5.0;netcoreapp3.1;netcoreapp2.2</TargetFrameworks>
<IsPackable>false</IsPackable>
</PropertyGroup>

View File

@ -112,13 +112,13 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));
var form = new List<KeyValuePair<string, string>>
var form = new List<KeyValuePair<string?, string?>>
{
new KeyValuePair<string, string>("client_id", request.ClientId),
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", request.Code),
new KeyValuePair<string, string>("redirect_uri", request.RedirectUri.ToString()),
new KeyValuePair<string, string>("code_verifier", request.CodeVerifier),
new KeyValuePair<string?, string?>("client_id", request.ClientId),
new KeyValuePair<string?, string?>("grant_type", "authorization_code"),
new KeyValuePair<string?, string?>("code", request.Code),
new KeyValuePair<string?, string?>("redirect_uri", request.RedirectUri.ToString()),
new KeyValuePair<string?, string?>("code_verifier", request.CodeVerifier),
};
return SendOAuthRequest<PKCETokenResponse>(apiConnector, form, null, null);
@ -129,11 +129,11 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));
var form = new List<KeyValuePair<string, string>>
var form = new List<KeyValuePair<string?, string?>>
{
new KeyValuePair<string, string>("client_id", request.ClientId),
new KeyValuePair<string, string>("grant_type", "refresh_token"),
new KeyValuePair<string, string>("refresh_token", request.RefreshToken),
new KeyValuePair<string?, string?>("client_id", request.ClientId),
new KeyValuePair<string?, string?>("grant_type", "refresh_token"),
new KeyValuePair<string?, string?>("refresh_token", request.RefreshToken),
};
return SendOAuthRequest<PKCETokenResponse>(apiConnector, form, null, null);
@ -146,9 +146,9 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));
var form = new List<KeyValuePair<string, string>>
var form = new List<KeyValuePair<string?, string?>>
{
new KeyValuePair<string, string>("refresh_token", request.RefreshToken)
new KeyValuePair<string?, string?>("refresh_token", request.RefreshToken)
};
#pragma warning disable CA2000
return apiConnector.Post<AuthorizationCodeRefreshResponse>(
@ -164,9 +164,9 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));
var form = new List<KeyValuePair<string, string>>
var form = new List<KeyValuePair<string?, string?>>
{
new KeyValuePair<string, string>("code", request.Code)
new KeyValuePair<string?, string?>("code", request.Code)
};
#pragma warning disable CA2000
@ -183,9 +183,9 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));
var form = new List<KeyValuePair<string, string>>
var form = new List<KeyValuePair<string?, string?>>
{
new KeyValuePair<string, string>("grant_type", "client_credentials")
new KeyValuePair<string?, string?>("grant_type", "client_credentials")
};
return SendOAuthRequest<ClientCredentialsTokenResponse>(apiConnector, form, request.ClientId, request.ClientSecret);
@ -198,10 +198,10 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));
var form = new List<KeyValuePair<string, string>>
var form = new List<KeyValuePair<string?, string?>>
{
new KeyValuePair<string, string>("grant_type", "refresh_token"),
new KeyValuePair<string, string>("refresh_token", request.RefreshToken)
new KeyValuePair<string?, string?>("grant_type", "refresh_token"),
new KeyValuePair<string?, string?>("refresh_token", request.RefreshToken)
};
return SendOAuthRequest<AuthorizationCodeRefreshResponse>(apiConnector, form, request.ClientId, request.ClientSecret);
@ -214,11 +214,11 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));
var form = new List<KeyValuePair<string, string>>
var form = new List<KeyValuePair<string?, string?>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", request.Code),
new KeyValuePair<string, string>("redirect_uri", request.RedirectUri.ToString())
new KeyValuePair<string?, string?>("grant_type", "authorization_code"),
new KeyValuePair<string?, string?>("code", request.Code),
new KeyValuePair<string?, string?>("redirect_uri", request.RedirectUri.ToString())
};
return SendOAuthRequest<AuthorizationCodeTokenResponse>(apiConnector, form, request.ClientId, request.ClientSecret);
@ -226,7 +226,7 @@ namespace SpotifyAPI.Web
private static Task<T> SendOAuthRequest<T>(
IAPIConnector apiConnector,
List<KeyValuePair<string, string>> form,
List<KeyValuePair<string?, string?>> form,
string? clientId,
string? clientSecret)
{

View File

@ -25,11 +25,17 @@ namespace SpotifyAPI.Web
var page = firstPage;
var results = new List<T>();
results.AddRange(firstPage.Items);
if (page.Items != null)
{
results.AddRange(page.Items);
}
while (page.Next != null && await ShouldContinue(results, page).ConfigureAwait(false))
{
page = await connector.Get<Paging<T>>(new Uri(page.Next, UriKind.Absolute)).ConfigureAwait(false);
results.AddRange(page.Items);
if (page.Items != null)
{
results.AddRange(page.Items);
}
}
return results;
@ -45,12 +51,18 @@ namespace SpotifyAPI.Web
var page = firstPage;
var results = new List<T>();
results.AddRange(firstPage.Items);
if (page.Items != null)
{
results.AddRange(page.Items);
}
while (page.Next != null && await ShouldContinue(results, page).ConfigureAwait(false))
{
var next = await connector.Get<TNext>(new Uri(page.Next, UriKind.Absolute)).ConfigureAwait(false);
page = mapper(next);
results.AddRange(page.Items);
if (page.Items != null)
{
results.AddRange(page.Items);
}
}
return results;

View File

@ -191,7 +191,7 @@ namespace SpotifyAPI.Web
var firstPage = await getFirstPage().ConfigureAwait(false);
await foreach (var item in (paginator ?? DefaultPaginator)
.Paginate(firstPage, mapper, _apiConnector)
.Paginate(firstPage, mapper, _apiConnector, cancellationToken)
.WithCancellation(cancellationToken)
)
{
@ -223,7 +223,7 @@ namespace SpotifyAPI.Web
var firstPage = await firstPageTask.ConfigureAwait(false);
await foreach (var item in (paginator ?? DefaultPaginator)
.Paginate(firstPage, mapper, _apiConnector)
.Paginate(firstPage, mapper, _apiConnector, cancellationToken)
.WithCancellation(cancellationToken)
)
{

View File

@ -14,7 +14,7 @@ namespace SpotifyAPI.Web
{
Ensure.ArgumentNotNull(response, nameof(response));
if (response.Headers.TryGetValue("Retry-After", out string retryAfter))
if (response.Headers.TryGetValue("Retry-After", out string? retryAfter))
{
RetryAfter = TimeSpan.FromSeconds(int.Parse(retryAfter, CultureInfo.InvariantCulture));
}

View File

@ -254,7 +254,7 @@ namespace SpotifyAPI.Web.Http
{
var request = CreateRequest(uri, method, parameters, body, headers);
IAPIResponse<T> apiResponse = await DoSerializedRequest<T>(request).ConfigureAwait(false);
return apiResponse.Body;
return apiResponse.Body!;
}
public async Task<IResponse> SendAPIRequestDetailed(

View File

@ -2,7 +2,7 @@ namespace SpotifyAPI.Web.Http
{
public class APIResponse<T> : IAPIResponse<T>
{
public APIResponse(IResponse response, T body = default)
public APIResponse(IResponse response, T? body = default)
{
Ensure.ArgumentNotNull(response, nameof(response));
@ -10,7 +10,7 @@ namespace SpotifyAPI.Web.Http
Response = response;
}
public T Body { get; set; }
public T? Body { get; set; }
public IResponse Response { get; set; }
}

View File

@ -2,7 +2,7 @@ namespace SpotifyAPI.Web.Http
{
public interface IAPIResponse<out T>
{
T Body { get; }
T? Body { get; }
IResponse Response { get; }
}

View File

@ -15,7 +15,9 @@ namespace SpotifyAPI.Web.Http
string? parameters = null;
if (request.Parameters != null)
{
parameters = string.Join(",", request.Parameters?.Select(kv => kv.Key + "=" + kv.Value).ToArray());
parameters = string.Join(",",
request.Parameters?.Select(kv => kv.Key + "=" + kv.Value)?.ToArray() ?? Array.Empty<string>()
);
}
Console.WriteLine(OnRequestFormat, request.Method, request.Endpoint, parameters, request.Body);
@ -28,7 +30,7 @@ namespace SpotifyAPI.Web.Http
#if NETSTANDARD2_0
string? body = response.Body?.ToString().Replace("\n", "");
#else
string? body = response.Body?.ToString().Replace("\n", "", StringComparison.InvariantCulture);
string? body = response.Body?.ToString()?.Replace("\n", "", StringComparison.InvariantCulture);
#endif
body = body?.Substring(0, Math.Min(50, body?.Length ?? 0));

View File

@ -37,9 +37,12 @@ namespace SpotifyAPI.Web
_bodyParamsCache[type] = new List<(PropertyInfo, BodyParamAttribute)>();
foreach (var prop in bodyProps)
{
var attribute = (BodyParamAttribute)prop.GetCustomAttribute(typeof(BodyParamAttribute));
_bodyParamsCache[type].Add((prop, attribute));
AddBodyParam(body, prop, attribute);
var attribute = prop.GetCustomAttribute<BodyParamAttribute>();
if (attribute != null)
{
_bodyParamsCache[type].Add((prop, attribute));
AddBodyParam(body, prop, attribute);
}
}
}
@ -48,7 +51,7 @@ namespace SpotifyAPI.Web
private void AddBodyParam(JObject body, PropertyInfo prop, BodyParamAttribute attribute)
{
object value = prop.GetValue(this);
object? value = prop.GetValue(this);
if (value != null)
{
body[attribute.Key ?? prop.Name] = JToken.FromObject(value);
@ -81,9 +84,12 @@ namespace SpotifyAPI.Web
_queryParamsCache[type] = new List<(PropertyInfo, QueryParamAttribute)>();
foreach (var prop in queryProps)
{
var attribute = (QueryParamAttribute)prop.GetCustomAttribute(typeof(QueryParamAttribute));
_queryParamsCache[type].Add((prop, attribute));
AddQueryParam(queryParams, prop, attribute);
var attribute = prop.GetCustomAttribute<QueryParamAttribute>();
if (attribute != null)
{
_queryParamsCache[type].Add((prop, attribute));
AddQueryParam(queryParams, prop, attribute);
}
}
}
@ -94,7 +100,7 @@ namespace SpotifyAPI.Web
private void AddQueryParam(Dictionary<string, string> queryParams, PropertyInfo prop, QueryParamAttribute attribute)
{
object value = prop.GetValue(this);
object? value = prop.GetValue(this);
if (value != null)
{
if (value is IList<string> list)
@ -140,7 +146,7 @@ namespace SpotifyAPI.Web
}
else
{
queryParams.Add(attribute.Key ?? prop.Name, value.ToString());
queryParams.Add(attribute.Key ?? prop.Name, value.ToString() ?? throw new Exception("ToString was null on a value"));
}
}
}

View File

@ -70,6 +70,7 @@ namespace SpotifyAPI.Web
public Task<IResponse> HandleRetry(IRequest request, IResponse response, IRetryHandler.RetryFunc retry)
{
Ensure.ArgumentNotNull(response, nameof(response));
Ensure.ArgumentNotNull(retry, nameof(retry));
return HandleRetryInternally(request, response, retry, RetryTimes);
}

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.1;netstandard2.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<TargetFrameworks>net5.0;netstandard2.1;netstandard2.0</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<PackageId>SpotifyAPI.Web</PackageId>
<Title>SpotifyAPI.Web</Title>

View File

@ -15,11 +15,10 @@ namespace SpotifyAPI.Web
public string Value { get; set; }
#if NETSTANDARD2_1
public static bool GetValue(Type enumType, Enum enumValue, [NotNullWhen(true)] out string? result)
#endif
#if NETSTANDARD2_0
public static bool GetValue(Type enumType, Enum enumValue, out string? result)
#else
public static bool GetValue(Type enumType, Enum enumValue, [NotNullWhen(true)] out string? result)
#endif
{
Ensure.ArgumentNotNull(enumType, nameof(enumType));

View File

@ -19,9 +19,9 @@ namespace SpotifyAPI.Web
var newParameters = new Dictionary<string, string>();
NameValueCollection existingParameters = HttpUtility.ParseQueryString(uri.Query);
foreach (string key in existingParameters.AllKeys)
foreach (string key in existingParameters)
{
newParameters.Add(key, existingParameters[key]);
newParameters.Add(key, existingParameters[key]!);
}
foreach (KeyValuePair<string, string> parameter in parameters)
{

View File

@ -11,16 +11,16 @@ namespace SpotifyAPI.Web
_formatter = new URIParameterFormatter();
}
public object? GetFormat(Type formatType)
public object? GetFormat(Type? formatType)
{
return formatType == typeof(ICustomFormatter) ? _formatter : null;
}
private class URIParameterFormatter : ICustomFormatter
{
public string Format(string format, object arg, IFormatProvider formatProvider)
public string Format(string? format, object? arg, IFormatProvider? formatProvider)
{
return HttpUtility.UrlEncode(arg.ToString());
return HttpUtility.UrlEncode(arg?.ToString()) ?? string.Empty;
}
}
}