feat: add WebSocket permessage-deflate compression
Implement WsCompression with Compress/Decompress methods per RFC 7692. Key .NET adaptation: Flush() without Dispose() on DeflateStream to produce the correct sync flush marker that can be stripped and re-appended.
This commit is contained in:
58
tests/NATS.Server.Tests/WebSocket/WsCompressionTests.cs
Normal file
58
tests/NATS.Server.Tests/WebSocket/WsCompressionTests.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using NATS.Server.WebSocket;
|
||||
using Shouldly;
|
||||
|
||||
namespace NATS.Server.Tests.WebSocket;
|
||||
|
||||
public class WsCompressionTests
|
||||
{
|
||||
[Fact]
|
||||
public void CompressDecompress_RoundTrip()
|
||||
{
|
||||
var original = "Hello, WebSocket compression test! This is long enough to compress."u8.ToArray();
|
||||
var compressed = WsCompression.Compress(original);
|
||||
compressed.ShouldNotBeNull();
|
||||
compressed.Length.ShouldBeGreaterThan(0);
|
||||
|
||||
var decompressed = WsCompression.Decompress([compressed], maxPayload: 4096);
|
||||
decompressed.ShouldBe(original);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Decompress_ExceedsMaxPayload_Throws()
|
||||
{
|
||||
var original = new byte[1000];
|
||||
Random.Shared.NextBytes(original);
|
||||
var compressed = WsCompression.Compress(original);
|
||||
|
||||
Should.Throw<InvalidOperationException>(() =>
|
||||
WsCompression.Decompress([compressed], maxPayload: 100));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compress_RemovesTrailing4Bytes()
|
||||
{
|
||||
var data = new byte[200];
|
||||
Random.Shared.NextBytes(data);
|
||||
var compressed = WsCompression.Compress(data);
|
||||
|
||||
// The compressed data should be valid for decompression when we add the trailer back
|
||||
var decompressed = WsCompression.Decompress([compressed], maxPayload: 4096);
|
||||
decompressed.ShouldBe(data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Decompress_MultipleBuffers()
|
||||
{
|
||||
var original = new byte[500];
|
||||
Random.Shared.NextBytes(original);
|
||||
var compressed = WsCompression.Compress(original);
|
||||
|
||||
// Split compressed data into multiple chunks
|
||||
int mid = compressed.Length / 2;
|
||||
var chunk1 = compressed[..mid];
|
||||
var chunk2 = compressed[mid..];
|
||||
|
||||
var decompressed = WsCompression.Decompress([chunk1, chunk2], maxPayload: 4096);
|
||||
decompressed.ShouldBe(original);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user