Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix printing of XML on parse failure #70

Merged
merged 3 commits into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 18 additions & 30 deletions Bunkum.Core/Endpoints/Middlewares/MainMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,47 +270,41 @@ private Response GenerateResponseFromEndpoint(object? val, EndpointAttribute att
return null;
}

private bool TryAddBodyToInvocation(EndpointAttribute attribute, Type paramType, MemoryStream body, ICollection<object?> invokeList)
private bool TryAddBodyToInvocation(EndpointAttribute attribute, Type paramType, MemoryStream bodyStream, ICollection<object?> invokeList)
{
if (paramType == typeof(Stream)) invokeList.Add(body);
else if (paramType == typeof(string))
{
TrimToToFirstNullByte(body);
invokeList.Add(Encoding.Default.GetString(body.ToArray()));
}
else if (paramType == typeof(byte[])) invokeList.Add(body.GetBuffer());
byte[] body = bodyStream.ToArray();

if (paramType == typeof(Stream)) invokeList.Add(new MemoryStream(body));
else if (paramType == typeof(string)) invokeList.Add(Encoding.UTF8.GetString(TrimToFirstNullByte(body)));
else if (paramType == typeof(byte[])) invokeList.Add(body);
else if (attribute.ContentType == ContentType.Xml)
{
TrimToToFirstNullByte(body);

XmlSerializer serializer = new(paramType);
try
{
object? obj = serializer.Deserialize(new StreamReader(body));
object? obj = serializer.Deserialize(new StringReader(Encoding.UTF8.GetString(TrimToFirstNullByte(body))));
if (obj == null) throw new Exception();
invokeList.Add(obj);
}
catch (Exception e)
{
this._logger.LogError(BunkumCategory.UserContent, $"Failed to parse object data: {e}\n\nXML: {body}");
this._logger.LogError(BunkumCategory.UserContent, $"Failed to parse object data: {e}\n\nXML: {Encoding.UTF8.GetString(body)}");
return false;
}
}
else if (attribute.ContentType == ContentType.Json)
{
TrimToToFirstNullByte(body);

try
{
JsonSerializer serializer = new();
using JsonReader reader = new JsonTextReader(new StreamReader(body, null, false, -1, true));
using JsonReader reader = new JsonTextReader(new StringReader(Encoding.UTF8.GetString(TrimToFirstNullByte(body))));
object? obj = serializer.Deserialize(reader, paramType);
if (obj == null) throw new Exception();
invokeList.Add(obj);
}
catch (Exception e)
{
this._logger.LogError(BunkumCategory.UserContent, $"Failed to parse object data: {e}\n\nJSON: {body}");
this._logger.LogError(BunkumCategory.UserContent, $"Failed to parse object data: {e}\n\nJSON: {Encoding.UTF8.GetString(body)}");
return false;
}
}
Expand All @@ -322,27 +316,21 @@ private bool TryAddBodyToInvocation(EndpointAttribute attribute, Type paramType,
return false;
}

body.Seek(0, SeekOrigin.Begin);
return true;
}

private static void TrimToToFirstNullByte(Stream body)
private static ReadOnlySpan<byte> TrimToFirstNullByte(ReadOnlySpan<byte> arr)
{
long i = 0;
body.Seek(0, SeekOrigin.Begin);
int b;
while ((b = body.ReadByte()) != -1)
{
if (b == 0) break;
//Find the first null byte
int idx = arr.IndexOf((byte)0);

i += 1;
//If theres no null byte, do not trim
if (idx == -1)
{
idx = arr.Length;
}

//Only call SetLength when necessary
if(i != body.Length)
body.SetLength(i);

body.Seek(0, SeekOrigin.Begin);
return arr[..idx];
}

private IBunkumSerializer? GetSerializerOrDefault(string contentType)
Expand Down
2 changes: 1 addition & 1 deletion BunkumTests.HttpServer/Endpoints/BodyEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ public string ByteArray(RequestContext context, byte[] body)
public string Stream(RequestContext context, Stream body)
{
MemoryStream stream = (MemoryStream)body;
return Encoding.Default.GetString(stream.GetBuffer());
return Encoding.Default.GetString(stream.ToArray());
}
}