delphiindydelphi-11-alexandria

Delphi 11 TIdHTTP.Get results in Could not load SSL Library


On a blank Delphi 11 project I dropped a button and an TIdHTTP component.

The button attempts to get a .txt file.

procedure TForm1.Button1Click(Sender: TObject);
var
  Stream: TMemoryStream;

begin
  Stream := TMemoryStream.Create;

    try

      IdHTTPGetProgramUpdateFile.Get('https://www.bookup.com/cowupdates/build129.txt', 
                                     Stream);

    except

      on E: Exception do
        begin
          MessageDlg(E.Message,
                     TMsgDlgType.mtInformation,
                     [TMsgDlgBtn.mbOK],
                     E.HelpContext);
        end;
    end;

  Stream.SaveToFile('downloaded.txt');

  Stream.Free;
end;

If the Windows project requests the URL with https then the error is "Could not load SSL Library."

If the project on Windows or Macintosh requests the URL with http then the error is "301 Moved Permanently". (The file is on the web site.)

If the project is run on a Macintosh with https then the PAServer reports the project "is loading libcrypto in an unsafe way."

When running for Windows, the project throws an exception in IdSSLOpenSSL.pas with the source code comment:

an exception here probably means that you are using the wrong version of the openssl libraries. refer to comments at the top of this file.

The comments at the top of the file were not useful to me.

I'm trying to download the contents of a text file from a web site and I know very little about the internet protocols. What am I missing?


Solution

  • If the Windows project requests the URL with https then the error is "Could not load SSL Library."

    You are relying on TIdHTTP using Indy's default TIdSSLIOHandlerSocketOpenSSL component, which depends on OpenSSL 1.0.2 library files (ie, libeay32.dll and ssleay32.dll, etc), so make sure you deploy those files with your app, preferably in your app's installation folder. Or, if needed, Indy does have an IdOpenSSLSetLibPath() function you can call at app startup to specify an alternate folder path where the libs are located.

    If the project on Windows or Macintosh requests the URL with http then the error is "301 Moved Permanently". (The file is on the web site.)

    301 is a redirect response. The server is telling you that the URL you have requested is old and the resource is available at a different URL (in this case, it is probably redirecting you to the HTTPS url), which will be provided to you in the TIdHTTP.Response.Location property, and in the TIdHTTP.OnRedirect event.

    If you have TIdHTTP.HandleRedirects set to true (it is false by default) then TIdHTTP will automatically re-request the new URL for you. Otherwise, it will treat the 301 as an error condition, and you will have to manually request the new URL yourself.

    If the project is run on a Macintosh with https then the PAServer reports the project "is loading libcrypto in an unsafe way."

    By default, on 'Nix-based systems, Indy attempts to load the OpenSSL library files using unversioned symlinks, and if that fails then it falls back to loading specific versioned library files instead. Using symlinks is not safe because they may map to library versions you are not expecting. For instance, on modern systems, the OpenSSL unversioned symlinks may map to library files for OpenSSL 1.1.x or later, which TIdSSLIOHandlerSocketOpenSSL does not support (use this SSLIOHandler instead). Indy has IdOpenSSLSetCanLoadSymLinks() and IdOpenSSLSetLoadSymLinksFirst() functions that you can call at app startup to prevent Indy from attempting to load symlinks. Then you can deploy specific versioned library files with your app, or point Indy to a folder where they reside.

    When running for Windows, the project throws an exception in IdSSLOpenSSL.pas with the source code comment:

    an exception here probably means that you are using the wrong version of the openssl libraries. refer to comments at the top of this file.

    The comments at the top of the file were not useful to me.

    You can use Indy's WhichFailedToLoad() function after the error occurs to find out whether Indy failed to load OpenSSL because the library files failed or load, or they were missing required function exports.