RemoteDB does not apply compression

When we are using the RemoteDB, compression is enabled. However, when looking at the data that is sent over the wire, we see that no compression is done from server to client. We looked at the server side code and see that a SameText is used that checks for 'deflate' in 'RemoteDB.Server.Module.pas' on line 517. When we look at the header value, we see that the value is 'deflate, gzip'.

When we changed this to be a 'Contains' instead of a 'SameText', the compression was performed and 'deflate' is present in the response content-encoding header. When reading the headers in the client, no content-encoding header is present. This results in an error on the client side. In short, compression does not work.

This lack of compression causes our customers to experience performance issues, so this has quite a high priority for us.

Hello @Beijloos_Robin, welcome to TMS Support Center!

I wonder why is that? RemoteDB client requests should always come from a TRemoteDBDatabase component - it doesn't make sense to have other clients invoking the server.

And the client clearly adds only the deflate value to the accept-encoding header, as we can see in line 1171 of RemoteDB.Client.Database unit:

  if FDB.Compress then
    Req.Headers.SetValue('accept-encoding', 'deflate');

So I fail to see why your accept-encoding header is coming as deflate, gzip?

Hi Wagner,

I have also been looking into this issue. You are right that the header is set differently in your code and for us it is also a surprise why it is received differently in the RemoteDB Server components. This should all be handled in the RemoteDB components and therefore we ask you they question why this is :slight_smile:

Here you see the traffic captured by Wireshark which clearly indicates the header we are talking about.

And here you see the response which is clearly not compressed.

To move on with this issue, we also added the compression middleware server side. To get this working we have to change some code in Sparkle.Middleware.Compress to make sure the response is compressed.

function TCompressMiddleware.IsCompressible(const MimeType: string): Boolean;
var
  LowerMime: string;
begin
  Result := True;

//  LowerMime := LowerCase(MimeType);
//  Result := StartsStr('text/', LowerMime) or EndsStr('+json', LowerMime) or EndsStr('+xml', LowerMime)
//    or (LowerMime = 'application/javascript')
//    or (LowerMime = 'application/json')
//    or (LowerMime = 'application/xml')
//    or (LowerMime = 'application/wasm');
end;

This seems to work fine if you look in the Wireshark response.

Our main goal is that the compression works; hopefully you can fix this. We have also some additional questions:

  1. Why is there a seperate way of compression in RemoteDB and are you not just using the compression middleware?
  2. What are our options to get the compression working without changing your code?

I don't know. Is this Wireshark detecting traffic in the client machine, or server machine? Do you have some kind of proxy, HTTP modifier anything that might be intercepting the call? Is the client just a regular, simple RemoteDB application?

We will.

The compression middleware is a generic one as you saw. It only compress data that is "compressible" (mostly text files and text formats like JSON, HTML, XML...). It can't keep compressing everything like JPG, PNG or any binary format it doesn't understand in advance. That's why RemoteDB server takes care of compressing its own response.

We first need to understand why the header is going with "deflate, gzip". That is wrong and is not being set by RemoteDB client. It should be working out of the box.

If you run the existing, default, RemoteDB demo that is provided in RemoteDB distribution, does the same thing happen in Wireshark?

If you run the existing, default, RemoteDB demo that is provided in RemoteDB distribution, does the same thing happen in Wireshark?

Of course, the same thing happens with the default RemoteDB demo (both running on the same machine, so Wireshark also runs on that machine). I have just tested it. Attached is the Wireshark output where you can clearly see that the header adds gzip and the output is not compressed.

Sorry, I used the default account that is logged in on my machine, but I replied to you :-)

Hi Laurens, I see that this is being added by WinHttp library itself.
The solution is just improve RemoteDB code indeed. In unit RemoteDB.Server.Module, function TCustomRemoteDBModule.ProvideResponse, you can change the very first line of the function to this:

  Compress := TSparkleUtils.AcceptsEncoding(Context.Request.Headers.Get('accept-encoding'), 'deflate');

This should solve the issue. Please confirm it's working for you there.
We will include such change in our official source code and next updates will already include it.

Hi Wagner,
When next update were released, will we need to compile Server and Client? or only Client?

@Fernandez_Diego, for this fix, only the server needs to be recompiled. Client stays the same.

Hi Wagner, we already tried that (before creating this thread ;-)) and this gives issues in the client, see below. This was of course tested with the default TMS example code to exclude other influences. It seems that the whole compression mechanism is just broken.

First chance exception at $758598B2. Exception class EWinHttpClientException with message
'Could not perform WinHttp operation. Error: (-2147467260) Operation aborted'.
Process RemoteDBClient.exe (472)
:758598b2 KERNELBASE.RaiseException + 0x62
Sparkle.WinHttp.Api.WinHttpCheck(False,'')
Sparkle.WinHttp.Engine.TWinHttpResponseStream.HttpRead((no value),4)
Sparkle.Http.Engine.THttpResponseStream.Read((no value),4)
RemoteDB.Client.Database.TRemoteDBProvider.ReadFieldDefs($3CECBC8)
RemoteDB.Client.Database.TRemoteDBProvider.Open($3CFA628)
RemoteDB.Client.Dataset.TBaseXDataset.OpenProvider(0,0)
RemoteDB.Client.Dataset.TBaseXDataset.InternalOpen
:00f21d14 TDataSet.DoInternalOpen + $14
:00f21c77 TDataSet.SetActive + $5B
:00f21ab6 TDataSet.Open + $A

Sorry, you're right. This was not as simple as it looked at first sight.
But we fixed the issue and in next RemoteDB release it will be resolved. Both client and server compilation will be required.

Hi Wagner,

I have some clients using RemoteDB technology. If I need to send a new EXE (client) release I will need to send a new RemoteDB server because an error will happen or simply will continue working with no compression?

@Fernandez_Diego,
The changes made won't break existing clients. If you are using an "old" RemoteDB Server and deploy a new client with the existing code, it will keep working.

Sorry if I take advantage, but is it the same error that I detected in Xdata?
Thanks

Can you please let me know exactly what are you referring to?

Hi Wagner, I refer to this post:

Thanks

It's unrelated.

Hi Wagner,

I suppose that this implementation will make a big difference in performance. Right? Do you have a date for the next release?

Kind regards,

Diego

Hi Diego,

Current plan is to provide an update in July. I don't know about performance as we didn't measure it.