Custom Compression Middleware

Hi,

¿How to implement a custom compressor server middleware?

I have done the decompressor with the following code:
...
if Context.Request.Headers.Get('content-encoding') = 'br' then
begin
TempStream := TMemoryStream.Create;
try
// copy stream
repeat
BytesRead := Context.Request.ContentStream.Read(Buffer[0], BufSize);
TempStream.Write(Buffer[0], BytesRead);
until BytesRead <> BufSize;
TempStream.Position := 0;
Context.Request.ContentStream.Free;
Context.Request.ContentStream := TBrotliDecompressionStream.Create(TempStream, true);
TempStream := nil;
Context.Request.Headers.SetValue('content-length', '-1');
except
TempStream.Free;
raise;
end;
end;

Now I want to send response compressed with Brotli compression.

Any hint?

Thanks in advance,

Omar Zelaya

Hi,

Also how to decompress con client side. :slight_smile:

thanks in advance,

Omar Zelaya

I've not tried implementing this directly as middleware, but if you've got your data compressed, setting the content-encoding header to 'br' should allow the browser to decompress it automatically. For example, in an XData service endpoint, it looks like this.

TXDataOperationContext.Current.Response.Headers.SetValue('content-encoding', 'br');

Hi,

I want my server to support brotli response compress just like gzip/deflate, thats why I want to implement it as middleware(just as the brotli decompress that I have allready done on server, when client send brotli compressed content).

On the client side I'm using TXDataClient.

Thanks in advance,

Omar Zelaya

The easiest way to accomplish this is to copy/paste the source code from Sparkle.Middleware.Compress. It's not trivial code, thus using what exists as base helps, as then you only need to change the part that actually uses the ZLib algorithm by your custom compression algorithm.

For non-web client-side decompression, you have to use event OnResponseReceived to process the raw response received and set the new response with the uncompressed value.

Hi,

I'm able to decompress de brotli compressed data on the OnResponseReceived, but still not able to set the response content with the uncompressed data.

Any hint?

Thanks in advance,

Omar Zelaya

So, what did you try? What code are you using? What errors do you get?

Hi, I'm triying with the following code with no success.

Result.HttpClient.OnResponseReceived :=
procedure(ARequest: THttpRequest; var AResponse: THttpResponse)
begin
if AResponse.Headers.Get('content-encoding') = 'br' then
begin
var NewContent : TBytes;

        NewContent := DescompressBrotli(AResponse.ContentAsBytes);
        AResponse.ContentAsStream.Position := 0; <<-- Get Exception "Http response stream cannot change position" 
        AResponse.ContentAsStream.Write(NewContent,Length(NewContent));
        AResponse.Headers.SetValue('content-encoding','');
    end;

end;

And actually didnt understand how to do the following from the documentation "The AResponse object is passed by reference meaning you can replace it by another one in case you want to alter the response for further processing of the framework..."

Thanks in advance,

Omar Zelaya.

You must create your own type inheriting from THttpResponse and setting it in AResponse object. Take a look at unit Sparkle.Encrypted.Response.