recently I noticed that gzip does not work with TIdHTTP anymore. It just returns garbage.
Your test code works fine for me on Windows, at least (I'm not a Linux user).
//{$DEFINE STATICLOAD_ZLIB}
//{$UNDEF STATICLOAD_ZLIB}
(Un)defining that in your own code has no effect on Indy. It needs to be (un)defined in Indy's
IdCompilerDefines.inc file instead, and then recompile Indy.
//Request.AcceptEncoding := 'gzip';
Request.AcceptEncoding := 'deflate';
Note that you cannot
force TIdHTTP to use
only deflate when a
Compressor is assigned. If the
Compressor is loaded successfully (its
IsReady property is true),
TIdHTTP will automatically add
gzip and/or
deflate as needed to the
Request.AcceptEncoding if they are not already present, thus allowing the server to choose between them.
Because
TIdHTTP auto-sets the
Request.AcceptEncoding if the
Compressor is ready, you should
not set the
AcceptEncoding manually
at all, or at least not for
gzip/
deflate specifically. You should let
TIdHTTP enable
gzip/
deflate for you only if the
Compressor is able to handle them.
That is likely the root cause of your problem. The
Compressor is not ready (for whatever reason), so
TIdHTTP does not update the
Request.AcceptEncoding, so your
manual setting gets passed as-is to the server, which then sends back a compressed response (not garbage) that
TIdHTTP does not auto-decompress for you.
So, either figure out why the
Compressor is not loading correctly, or else leave the
Compressor set to
nil, set the
Request.AcceptEncodings as needed, and then handle the decompression manually after the compressed response is returned to you.
PS: Will Indy support brotli sooner or later?
Probably not, at least not anytime soon. But there is nothing stopping you from implementing your own
Compressor class for it, and then use it with
TIdHTTP. And if you get something working, you can always submit it for review for a possible future inclusion.
Does the static linking also work with FPC?
I don't know. It was designed for Delphi.
If yes, how do I do that? Static linking only works on Windows, no?
I suppose as long as FPC can consume Indy's ZLIB obj files, then it should work, at least on Windows.
How can I see if it's static or dynamic linked?
There is nothing readily exposed to check that at runtime. But, at compile-time, you can probably use
{$IF DECLARED(...)} to check if the
IdZlibHeaders.pas unit declares the
EIdZLibStubError class or not. It is declared only when dynamic linking.
But the issue on linux still exist, maybe it's related to the change of SSLDLLVers, Bug fix for HackLoad() and Updating various DLL related functions
It should not be related, since those changes do not affect how Indy uses Zlib.
where the last one says // TODO: setup this array more like the SSLDLLVers arrays in the IdSSLOpenSSLHeaders unit...
The changes I made for handling OpenSSL DLLs do not apply to ZLib DLLs. So, if ZLib was loading correctly before, it should still load OK now, I did not change that logic.
Why does TIdCompressorZLib.Create
not raise an exception?
Because it is not supposed to, in part because the constructor is not what loads ZLib at runtime, the
TIdCompressorZLib.IsReady property getter procedure does.
Otherwise, you can pre-load ZLib by calling
IdZLibHeaders.Load() manually before using
TIdHTTP, similar to how you are calling
IdSSLOpenSSLHeaders.Load().
However, note that both
IdSSLOpenSSLHeaders.Load() and
IdZLibHeaders.Load() do not raise an exception on load failure, they return
Boolean values instead, eg:
if not IdSSLOpenSSLHeaders.Load then
begin
writeln(Format('Loading OpenSSL failed: %s', [IdSSLOpenSSLHeaders.WhichFailedToLoad]));
exit;
end;
writeln('OpenSSL loaded!');
if not IdZLibHeaders.Load then
begin
writeln('Loading ZLib failed');
// there is no WhichFailedToLoad() function for ZLib! Individual ZLib functions will
// raise an EIdZLibStubError if they cannot be loaded from the DLL when called...
exit;
end;
writeln('ZLib loaded!');
when using gzip, the internal check does only check if Compressor is not nil which is also true if loading zlib failed -> returning garbage.
TIdHTTP checks the
Compressor.IsReady property before updating the
Request.AcceptEncoding, or decompressing a compressed response.