refactor(inboundapi): pool the request audit buffer + reset Position in finally
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Buffers;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -279,14 +280,18 @@ public sealed class AuditWriteMiddleware
|
|||||||
return (null, false);
|
return (null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read AT MOST cap + 1 bytes — the extra byte tells us the body was
|
||||||
|
// over the cap without forcing us to allocate the whole payload. Rent
|
||||||
|
// the scratch buffer from the shared ArrayPool so we don't allocate
|
||||||
|
// (and immediately discard) `cap + 1` bytes per request — the pool
|
||||||
|
// may hand back a buffer LARGER than `limit`, so we treat `limit`
|
||||||
|
// (not `buffer.Length`) as the read ceiling.
|
||||||
|
var limit = capBytes + 1;
|
||||||
|
var buffer = ArrayPool<byte>.Shared.Rent(limit);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
request.Body.Position = 0;
|
request.Body.Position = 0;
|
||||||
|
|
||||||
// Read AT MOST cap + 1 bytes — the extra byte tells us the body was
|
|
||||||
// over the cap without forcing us to allocate the whole payload.
|
|
||||||
var limit = capBytes + 1;
|
|
||||||
var buffer = new byte[limit];
|
|
||||||
var total = 0;
|
var total = 0;
|
||||||
while (total < limit)
|
while (total < limit)
|
||||||
{
|
{
|
||||||
@@ -299,7 +304,6 @@ public sealed class AuditWriteMiddleware
|
|||||||
}
|
}
|
||||||
total += read;
|
total += read;
|
||||||
}
|
}
|
||||||
request.Body.Position = 0;
|
|
||||||
|
|
||||||
if (total == 0)
|
if (total == 0)
|
||||||
{
|
{
|
||||||
@@ -318,6 +322,15 @@ public sealed class AuditWriteMiddleware
|
|||||||
// outcome.
|
// outcome.
|
||||||
return (null, false);
|
return (null, false);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Even on a thrown read, the downstream handler must see the full
|
||||||
|
// body from position 0 — never let a failed audit copy leak a
|
||||||
|
// truncated view. A rewind failure is swallowed: best-effort,
|
||||||
|
// same philosophy as the rest of the file.
|
||||||
|
try { request.Body.Position = 0; } catch { /* swallow */ }
|
||||||
|
ArrayPool<byte>.Shared.Return(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user