diff --git a/Pilz.Net/Api/ApiClient.cs b/Pilz.Net/Api/ApiClient.cs index 2844e45..eea248b 100644 --- a/Pilz.Net/Api/ApiClient.cs +++ b/Pilz.Net/Api/ApiClient.cs @@ -100,7 +100,17 @@ public class ApiClient(string apiUrl) : IApiClient Log.Debug("Create content"); - if (context.Message is not null) + if (context.Message is ApiRawByteMessage messageRawBytes) + { + content = new ByteArrayContent(messageRawBytes.Data); + content.Headers.ContentType = new("application/octet-stream"); + } + else if (context.Message is ApiRawStreamMessage messageRawStream) + { + content = new StreamContent(messageRawStream.Data); + content.Headers.ContentType = new("application/octet-stream"); + } + else if (context.Message is not null) content = new StringContent(context.Serializer.Serialize(context.Message)!, null, "application/json"); else content = new StringContent(string.Empty, null, "application/json"); diff --git a/Pilz.Net/Api/ApiRawStreamMessage.cs b/Pilz.Net/Api/ApiRawStreamMessage.cs index a28acb0..b232f2c 100644 --- a/Pilz.Net/Api/ApiRawStreamMessage.cs +++ b/Pilz.Net/Api/ApiRawStreamMessage.cs @@ -3,4 +3,10 @@ public class ApiRawStreamMessage(Stream data) : ApiRawMessage { public Stream Data { get; } = data; + public virtual long Length => Data.Length; +} + +public class ApiRawInputStreamMessage(Stream data, long length) : ApiRawStreamMessage(data) +{ + public override long Length => length; } diff --git a/Pilz.Net/Api/ApiServer.cs b/Pilz.Net/Api/ApiServer.cs index 8c2aed9..ef3332e 100644 --- a/Pilz.Net/Api/ApiServer.cs +++ b/Pilz.Net/Api/ApiServer.cs @@ -436,37 +436,9 @@ public class ApiServer : IApiServer if (context.Request.Headers.Get("API-AUTH-KEY") is not string authKey) authKey = null!; - // Read input content - Log.Debug("Read input content"); - string? contentJson; - if (context.Request.ContentType is string contentType - && contentType.Contains("application/json") - && context.Request.ContentLength64 > 0) - { - try - { - using StreamReader input = new(context.Request.InputStream); - contentJson = input.ReadToEnd(); - } - catch (OutOfMemoryException) - { - Log.Error("Error reading remote data due to missing memory"); - close(true); - return; - } - catch (Exception ex) - { - Log.Error("Error reading remote data", ex); - close(true); - return; - } - } - else - contentJson = null; - // Handle message Log.Debug("Handle mssage"); - if (HandleMessage(context, path, query, handler, contentJson, authKey) is not PrivateApiResult result) + if (HandleMessage(context, path, query, handler, authKey) is not PrivateApiResult result) { Log.Warn("Request couldn't be handled"); close(true); @@ -514,7 +486,7 @@ public class ApiServer : IApiServer return; } - protected virtual PrivateApiResult? HandleMessage(HttpListenerContext context, string url, string? query, PrivateMessageHandler handler, string? json, string? authKey) + protected virtual PrivateApiResult? HandleMessage(HttpListenerContext context, string url, string? query, PrivateMessageHandler handler, string? authKey) { // Check authentication Log.Debug("Check authentication"); @@ -530,13 +502,46 @@ public class ApiServer : IApiServer var targetType = handler.Handler.Method.GetParameters().FirstOrDefault(p => p.ParameterType.IsAssignableTo(typeof(ApiMessage)))?.ParameterType; var serializer = GetSerializer(handler.Attribute.Serializer); - // Deserialize - Log.Debug("Deserialize message"); - ApiMessage? message; - if (json != null && targetType != null) - message = serializer.Deserialize(json, targetType); - else - message = null; + // Read input content + Log.Debug("Read input content"); + ApiMessage? message = null; + switch (context.Request.ContentType) + { + case "application/json": + try + { + Log.Debug("Deserialize message"); + using StreamReader input = new(context.Request.InputStream); + var contentJson = input.ReadToEnd(); + if (targetType == null) + return null; + message = serializer.Deserialize(contentJson, targetType); + } + catch (OutOfMemoryException) + { + Log.Error("Error reading remote data due to missing memory"); + return null; + } + catch (Exception ex) + { + Log.Error("Error reading remote data", ex); + return null; + } + break; + case "application/octet-stream": + Log.Debug("Process raw message"); + if (targetType == null) + return null; + else if (targetType.IsAssignableTo(typeof(ApiRawByteMessage))) + { + var bytes = new byte[context.Request.ContentLength64]; + context.Request.InputStream.Read(bytes, 0, bytes.Length); + message = new ApiRawByteMessage(bytes); + } + else if (targetType.IsAssignableTo(typeof(ApiRawStreamMessage))) + message = new ApiRawInputStreamMessage(context.Request.InputStream, context.Request.ContentLength64); + break; + } // Invoke handler Log.Debug("Invoke handler"); diff --git a/Pilz.Net/Pilz.Net.csproj b/Pilz.Net/Pilz.Net.csproj index b4e3f77..277e119 100644 --- a/Pilz.Net/Pilz.Net.csproj +++ b/Pilz.Net/Pilz.Net.csproj @@ -8,7 +8,7 @@ - 2.10.4 + 2.11.0