add logging & plish up

This commit is contained in:
Pilzinsel64
2024-08-16 07:22:29 +02:00
parent 2efb4f141c
commit e24e6e5bca
5 changed files with 54 additions and 6 deletions

View File

@@ -1,4 +1,6 @@
namespace Pilz.Net.Api; using Castle.Core.Logging;
namespace Pilz.Net.Api;
public class ApiClient(string apiUrl) : IApiClient public class ApiClient(string apiUrl) : IApiClient
{ {
@@ -10,10 +12,14 @@ public class ApiClient(string apiUrl) : IApiClient
public virtual IMessageSerializer Serializer { get; set; } = new DefaultMessageSerializer(); public virtual IMessageSerializer Serializer { get; set; } = new DefaultMessageSerializer();
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 url, ApiMessage message, IMessageSerializer? serializer)
{ {
serializer ??= Serializer; serializer ??= Serializer;
Log.InfoFormat("Send message to {0}", url);
var res = await Send(url, message, serializer); var res = await Send(url, message, serializer);
return new(res.StatusCode); return new(res.StatusCode);
@@ -23,6 +29,8 @@ public class ApiClient(string apiUrl) : IApiClient
{ {
serializer ??= Serializer; serializer ??= Serializer;
Log.InfoFormat("Send request to {0}", url);
var res = await Send(url, message, serializer); var res = await Send(url, message, serializer);
TResponse? result = null; TResponse? result = null;

View File

@@ -1,4 +1,5 @@
using Pilz.Extensions.Reflection; using Castle.Core.Logging;
using Pilz.Extensions.Reflection;
using System.Net; using System.Net;
using System.Reflection; using System.Reflection;
using static Pilz.Net.Api.IApiServer; using static Pilz.Net.Api.IApiServer;
@@ -21,8 +22,11 @@ public class ApiServer(string apiUrl) : IApiServer
public IMessageSerializer Serializer { get; set; } = new DefaultMessageSerializer(); public IMessageSerializer Serializer { get; set; } = new DefaultMessageSerializer();
public ILogger Log { get; set; } = NullLogger.Instance;
public virtual void Start() public virtual void Start()
{ {
Log.Info("Start listening");
httpListener.Start(); httpListener.Start();
Listen(); Listen();
} }
@@ -30,6 +34,7 @@ public class ApiServer(string apiUrl) : IApiServer
public virtual void Stop() public virtual void Stop()
{ {
httpListener.Stop(); httpListener.Stop();
Log.Info("Stopped listening");
} }
public virtual void RegisterHandler<T>(T instance) where T : class public virtual void RegisterHandler<T>(T instance) where T : class
@@ -54,7 +59,9 @@ public class ApiServer(string apiUrl) : IApiServer
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."); 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.");
// Add handler // Add handler
handlers.Add(ApiUrl + attribute.Route, handler); var fullUrl = ApiUrl + attribute.Route;
Log.InfoFormat("Added handler for {0}", fullUrl);
handlers.Add(fullUrl, handler);
} }
protected virtual void Listen() protected virtual void Listen()
@@ -66,85 +73,109 @@ public class ApiServer(string apiUrl) : IApiServer
protected virtual void CheckContext() protected virtual void CheckContext()
{ {
var context = httpListener.GetContext(); var context = httpListener.GetContext();
void close() => context.Response.OutputStream.Close(); void close()
{
Log.Info("End handling request.");
context.Response.OutputStream.Close();
}
Log.Debug("Sanity checks");
if (context.Request.HttpMethod != HttpMethod.Post.Method if (context.Request.HttpMethod != HttpMethod.Post.Method
|| context.Request.ContentType is not string contentType || context.Request.ContentType is not string contentType
|| !contentType.Contains("application/json")) || !contentType.Contains("application/json"))
{ {
Log.Info("Request has no json content");
close(); close();
return; return;
} }
// Parse url // Parse url
Log.Debug("Parse url");
var path = context.Request.Url?.PathAndQuery.Replace(ApiUrl, string.Empty); var path = context.Request.Url?.PathAndQuery.Replace(ApiUrl, string.Empty);
if (string.IsNullOrWhiteSpace(path) || context.Request.ContentLength64 <= 0) if (string.IsNullOrWhiteSpace(path) || context.Request.ContentLength64 <= 0)
{ {
Log.Info("Request has no content");
close(); close();
return; return;
} }
// Read input content // Read input content
Log.Debug("Read input content");
using StreamReader input = new(context.Request.InputStream); using StreamReader input = new(context.Request.InputStream);
var contentJson = input.ReadToEnd(); var contentJson = input.ReadToEnd();
// Get auth key // Get auth key
Log.Debug("Get auth key");
if (context.Request.Headers.Get("API-AUTH-KEY") is not string authKey) if (context.Request.Headers.Get("API-AUTH-KEY") is not string authKey)
authKey = null!; authKey = null!;
// Handle message // Handle message
Log.Debug("Handle mssage");
if (HandleMessage(path, contentJson, authKey) is not PrivateApiResult result) if (HandleMessage(path, contentJson, authKey) is not PrivateApiResult result)
{ {
Log.Warn("Request couldn't be handled");
close(); close();
return; return;
} }
// Set response parameters // Set response parameters
Log.Debug("Set response parameters");
context.Response.StatusCode = (int)result.Original.StatusCode; context.Response.StatusCode = (int)result.Original.StatusCode;
// Write response content // Write response content
Log.Debug("Write response");
if (result.ResultJson is not null) if (result.ResultJson is not null)
{ {
Log.Info("Write response");
context.Response.ContentType = "application/json"; context.Response.ContentType = "application/json";
using StreamWriter output = new(context.Response.OutputStream); using StreamWriter output = new(context.Response.OutputStream);
output.Write(result); output.Write(result);
} }
Log.Debug("Finish response");
close(); close();
} }
protected virtual PrivateApiResult? HandleMessage(string url, string json, string? authKey) protected virtual PrivateApiResult? HandleMessage(string url, string json, string? authKey)
{ {
// Get handler // Get handler
Log.Debug("Find handler");
if (!handlers.TryGetValue(url, out var handler) if (!handlers.TryGetValue(url, out var handler)
|| handler.Method.GetCustomAttribute<MessageHandlerAttribute>() is not MessageHandlerAttribute attribute) || handler.Method.GetCustomAttribute<MessageHandlerAttribute>() is not MessageHandlerAttribute attribute)
return null; return null;
// Check authentication // Check authentication
Log.Debug("Check authentication");
if (attribute.RequiesAuth && (string.IsNullOrWhiteSpace(authKey) || !CheckAuthentication(authKey))) if (attribute.RequiesAuth && (string.IsNullOrWhiteSpace(authKey) || !CheckAuthentication(authKey)))
return null; return null;
// Get required infos // Get required infos
Log.Debug("Find other infos");
var targetType = handler.Method.GetParameters().First().ParameterType; var targetType = handler.Method.GetParameters().First().ParameterType;
var serializer = GetSerializer(attribute.Serializer); var serializer = GetSerializer(attribute.Serializer);
// Deserialize // Deserialize
Log.Debug("Deserialize message");
if (serializer.Deserialize(json, targetType) is not ApiMessage message) if (serializer.Deserialize(json, targetType) is not ApiMessage message)
return null; return null;
// Invoke handler // Invoke handler
Log.Debug("Invoke handler");
if (handler.DynamicInvoke(message) is not ApiResult result) if (handler.DynamicInvoke(message) is not ApiResult result)
return null; return null;
// Return result without message // Return result without message
Log.Debug("Check message");
if (result.Message is null) if (result.Message is null)
return new(result, null); return new(result, null);
// Serializer // Serializer
Log.Debug("Serialize message");
if (serializer.Serialize(result.Message) is not string resultStr) if (serializer.Serialize(result.Message) is not string resultStr)
return null; return null;
// Return result with message // Return result with message
Log.Debug("Finish result");
return new(result, resultStr); return new(result, resultStr);
} }

View File

@@ -1,4 +1,6 @@
namespace Pilz.Net.Api; using Castle.Core.Logging;
namespace Pilz.Net.Api;
public interface IApiClient public interface IApiClient
{ {
@@ -8,6 +10,8 @@ public interface IApiClient
IMessageSerializer Serializer { get; } IMessageSerializer Serializer { get; }
ILogger Log { get; set; }
Task<ApiResponse> SendMessage<TResponse>(string url, ApiMessage message, IMessageSerializer? serializer = null); Task<ApiResponse> SendMessage<TResponse>(string url, 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 url, ApiMessage message, IMessageSerializer? serializer = null) where TResponse : ApiMessage;

View File

@@ -1,4 +1,6 @@
namespace Pilz.Net.Api; using Castle.Core.Logging;
namespace Pilz.Net.Api;
public interface IApiServer public interface IApiServer
{ {
@@ -12,6 +14,8 @@ public interface IApiServer
IMessageSerializer Serializer { get; } IMessageSerializer Serializer { get; }
ILogger Log { get; set; }
void Start(); void Start();
void Stop(); void Stop();

View File

@@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Castle.Core" Version="5.1.1" />
<PackageReference Include="Microsoft.VisualBasic" Version="10.3.0" /> <PackageReference Include="Microsoft.VisualBasic" Version="10.3.0" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" /> <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" /> <PackageReference Include="System.Net.Http" Version="4.3.4" />