some more work on api
This commit is contained in:
10
Pilz.Extensions/Collections/IEnumerableExtensions.cs
Normal file
10
Pilz.Extensions/Collections/IEnumerableExtensions.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Pilz.Extensions.Collections;
|
||||
|
||||
public static class IEnumerableExtensions
|
||||
{
|
||||
public static void ForEach<T>(this IEnumerable<T> @this, Action<T> action)
|
||||
{
|
||||
foreach (var t in @this)
|
||||
action(t);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
namespace Pilz.Net.Api;
|
||||
|
||||
public record class ApiAuthCheckEventArgs(string AuthKey)
|
||||
public class ApiAuthCheckEventArgs(string authKey) : EventArgs
|
||||
{
|
||||
private bool hasDenyed;
|
||||
|
||||
public string AuthKey { get; } = authKey;
|
||||
|
||||
public bool Valid { get; set; }
|
||||
|
||||
public void Deny()
|
||||
|
||||
@@ -14,24 +14,24 @@ public class ApiClient(string apiUrl) : IApiClient
|
||||
|
||||
public ILogger Log { get; set; } = NullLogger.Instance;
|
||||
|
||||
public virtual async Task<ApiResponse> SendMessage<TResponse>(string url, ApiMessage message, IMessageSerializer? serializer)
|
||||
public virtual async Task<ApiResponse> SendMessage<TResponse>(string route, ApiMessage message, IMessageSerializer? serializer = null)
|
||||
{
|
||||
serializer ??= Serializer;
|
||||
|
||||
Log.InfoFormat("Send message to {0}", url);
|
||||
Log.InfoFormat("Send message to {0}", route);
|
||||
|
||||
var res = await Send(url, message, serializer);
|
||||
var res = await Send(route, message, serializer);
|
||||
|
||||
return new(res.StatusCode);
|
||||
}
|
||||
|
||||
public virtual async Task<ApiResponse<TResponse>> SendRequest<TResponse>(string url, ApiMessage message, IMessageSerializer? serializer) where TResponse : ApiMessage
|
||||
public virtual async Task<ApiResponse<TResponse>> SendRequest<TResponse>(string route, ApiMessage message, IMessageSerializer? serializer = null) where TResponse : ApiMessage
|
||||
{
|
||||
serializer ??= Serializer;
|
||||
|
||||
Log.InfoFormat("Send request to {0}", url);
|
||||
Log.InfoFormat("Send request to {0}", route);
|
||||
|
||||
var res = await Send(url, message, serializer);
|
||||
var res = await Send(route, message, serializer);
|
||||
TResponse? result = null;
|
||||
|
||||
if (res.IsSuccessStatusCode)
|
||||
@@ -40,11 +40,16 @@ public class ApiClient(string apiUrl) : IApiClient
|
||||
return new(res.StatusCode, result);
|
||||
}
|
||||
|
||||
protected virtual async Task<HttpResponseMessage> Send(string url, ApiMessage message, IMessageSerializer serializer)
|
||||
protected virtual async Task<HttpResponseMessage> Send(string route, ApiMessage message, IMessageSerializer serializer)
|
||||
{
|
||||
var fullRequestUrl = ApiUrl + url;
|
||||
var url = ApiUrl + route;
|
||||
var content = new StringContent(serializer.Serialize(message)!, null, "application/json");
|
||||
content.Headers.Add("API-AUTH-KEY", AuthKey);
|
||||
return await httpClient.PostAsync(fullRequestUrl, content);
|
||||
content.Headers.Add("API-AUTH-KEY", EncodeAuthKey());
|
||||
return await httpClient.PostAsync(url, content);
|
||||
}
|
||||
|
||||
protected virtual string? EncodeAuthKey()
|
||||
{
|
||||
return AuthKey;
|
||||
}
|
||||
}
|
||||
|
||||
9
Pilz.Net/Api/ApiRequestInfo.cs
Normal file
9
Pilz.Net/Api/ApiRequestInfo.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Pilz.Net.Api;
|
||||
|
||||
public record class ApiRequestInfo(
|
||||
ApiMessage Message,
|
||||
[property: MemberNotNullWhen(true, "AuthKey")]
|
||||
bool IsAuthenticated,
|
||||
string? AuthKey);
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Net;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net;
|
||||
|
||||
namespace Pilz.Net.Api;
|
||||
|
||||
@@ -7,9 +8,10 @@ public record class ApiResponse<T>(
|
||||
T? Message)
|
||||
where T : ApiMessage
|
||||
{
|
||||
[MemberNotNull(nameof(Message))]
|
||||
public void EnsureOk()
|
||||
{
|
||||
if (StatusCode != HttpStatusCode.OK)
|
||||
if (StatusCode != HttpStatusCode.OK || Message is null)
|
||||
throw new Exception("Api return is not ok!");
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,21 @@ public record class ApiResult(
|
||||
HttpStatusCode StatusCode,
|
||||
ApiMessage? Message = null)
|
||||
{
|
||||
public static ApiResult Ok()
|
||||
{
|
||||
return new(HttpStatusCode.OK);
|
||||
}
|
||||
public static ApiResult Ok() => new(HttpStatusCode.OK);
|
||||
|
||||
public static ApiResult Ok(ApiMessage message)
|
||||
{
|
||||
return new(HttpStatusCode.OK, message);
|
||||
}
|
||||
public static ApiResult Ok(ApiMessage message) => new(HttpStatusCode.OK, message);
|
||||
|
||||
public static ApiResult Unauthorized() => new(HttpStatusCode.Unauthorized);
|
||||
|
||||
public static ApiResult NotFound() => new(HttpStatusCode.NotFound);
|
||||
|
||||
public static ApiResult Forbidden() => new(HttpStatusCode.Forbidden);
|
||||
|
||||
public static ApiResult Locked() => new(HttpStatusCode.Locked);
|
||||
|
||||
public static ApiResult TooManyRequests() => new(HttpStatusCode.TooManyRequests);
|
||||
|
||||
public static ApiResult ServiceUnavailable() => new(HttpStatusCode.ServiceUnavailable);
|
||||
|
||||
public static ApiResult UnavailableForLegalReasons() => new(HttpStatusCode.UnavailableForLegalReasons);
|
||||
}
|
||||
@@ -54,7 +54,9 @@ public class ApiServer(string apiUrl) : IApiServer
|
||||
// Sanity checks
|
||||
if (method.GetCustomAttribute<MessageHandlerAttribute>() is not MessageHandlerAttribute attribute
|
||||
|| method.GetParameters().FirstOrDefault() is not ParameterInfo parameter
|
||||
|| !parameter.ParameterType.IsAssignableTo(typeof(ApiMessage))
|
||||
|| !parameter.ParameterType.IsGenericType
|
||||
|| parameter.ParameterType.GenericTypeArguments.Length != 1
|
||||
|| !parameter.ParameterType.GenericTypeArguments[0].IsAssignableTo(typeof(ApiMessage))
|
||||
|| !method.ReturnType.IsAssignableTo(typeof(ApiResult)))
|
||||
throw new NotSupportedException("The first parameter needs to be of type ApiMessage and must return an ApiResult object and the method must have the MessageHandlerAttribute.");
|
||||
|
||||
@@ -146,8 +148,11 @@ public class ApiServer(string apiUrl) : IApiServer
|
||||
|
||||
// Check authentication
|
||||
Log.Debug("Check authentication");
|
||||
if (attribute.RequiesAuth && (string.IsNullOrWhiteSpace(authKey) || !CheckAuthentication(authKey)))
|
||||
return null;
|
||||
var isAuthenticated = false;
|
||||
if (!string.IsNullOrWhiteSpace(authKey) && DecodeAuthKey(authKey) is string authKeyDecoded)
|
||||
isAuthenticated = CheckAuthentication(authKeyDecoded);
|
||||
else
|
||||
authKeyDecoded = null!;
|
||||
|
||||
// Get required infos
|
||||
Log.Debug("Find other infos");
|
||||
@@ -161,7 +166,8 @@ public class ApiServer(string apiUrl) : IApiServer
|
||||
|
||||
// Invoke handler
|
||||
Log.Debug("Invoke handler");
|
||||
if (handler.DynamicInvoke(message) is not ApiResult result)
|
||||
var parameters = BuildParameters(handler, () => message, () => new(message, isAuthenticated, authKeyDecoded));
|
||||
if (handler.DynamicInvoke(parameters) is not ApiResult result)
|
||||
return null;
|
||||
|
||||
// Return result without message
|
||||
@@ -179,6 +185,22 @@ public class ApiServer(string apiUrl) : IApiServer
|
||||
return new(result, resultStr);
|
||||
}
|
||||
|
||||
protected virtual object?[]? BuildParameters(Delegate handler, Func<ApiMessage> getMessage, Func<ApiRequestInfo> getRequestInfo)
|
||||
{
|
||||
var infos = handler.Method.GetParameters();
|
||||
var objs = new List<object?>();
|
||||
|
||||
foreach (var info in infos)
|
||||
{
|
||||
if (info.ParameterType.IsAssignableTo(typeof(ApiMessage)))
|
||||
objs.Add(getMessage());
|
||||
else if (info.ParameterType.IsAssignableTo(typeof(ApiRequestInfo)))
|
||||
objs.Add(getRequestInfo());
|
||||
}
|
||||
|
||||
return [.. objs];
|
||||
}
|
||||
|
||||
protected virtual IMessageSerializer GetSerializer(Type? t)
|
||||
{
|
||||
if (t is not null)
|
||||
@@ -204,4 +226,9 @@ public class ApiServer(string apiUrl) : IApiServer
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual string? DecodeAuthKey(string authKey)
|
||||
{
|
||||
return authKey;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ public interface IApiClient
|
||||
|
||||
ILogger Log { get; set; }
|
||||
|
||||
Task<ApiResponse> SendMessage<TResponse>(string url, ApiMessage message, IMessageSerializer? serializer = null);
|
||||
Task<ApiResponse> SendMessage<TResponse>(string route, ApiMessage message, IMessageSerializer? serializer = null);
|
||||
|
||||
Task<ApiResponse<TResponse>> SendRequest<TResponse>(string url, ApiMessage message, IMessageSerializer? serializer = null) where TResponse : ApiMessage;
|
||||
Task<ApiResponse<TResponse>> SendRequest<TResponse>(string route, ApiMessage message, IMessageSerializer? serializer = null) where TResponse : ApiMessage;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user