Search code examples
delphiopensslindydelphi-2006

How to download a file over HTTPS using Indy 10 and OpenSSL?


I have the following task: download a file using HTTPS and authentication. Indy seems the way to go but for some reason it doesn't work so far. I have the following in place:

  • a TIdHTTP component which I use for downloading
  • a TIdURI component used to create the URL
  • a TIdSSLIOHandlerSocketOpenSSL component which should provide the secure connection. The required DLLs are in the binary folder.

The site also requires authentication and I included the user/pass in the URL as in the example below. In short this is the code:

URI := TIdURI.Create('https://test.example.com/');
URI.Username := ParamUserName;
URI.Password := ParamPassword;

HTTP := TIdHTTP.Create(nil);
if URI.Protocol = 'https' then
begin
  IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  IOHandler.SSLOptions.Method := sslvSSLv3;
  HTTP.IOHandler := IOHandler;
end;

HTTP.Get(URI.GetFullURI([ofAuthInfo]), FileStream);

Using this code I get a "Read Timeout" EIdReadTimeout exception very fast. Testing the URL in a browser works without problem. Any ideas on what's missing or what I did wrong?


Solution

  • I finally abandoned Indy and OpenSSL and used WinInet for downloading. This is the code that worked for me:

    function Download(URL, User, Pass, FileName: string): Boolean;
    const
      BufferSize = 1024;
    var
      hSession, hURL: HInternet;
      Buffer: array[1..BufferSize] of Byte;
      BufferLen: DWORD;
      F: File;
    begin
       Result := False;
       hSession := InternetOpen('', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0) ;
    
       // Establish the secure connection
       InternetConnect (
         hSession,
         PChar(FullURL),
         INTERNET_DEFAULT_HTTPS_PORT,
         PChar(User),
         PChar(Pass),
         INTERNET_SERVICE_HTTP,
         0,
         0
       );
    
      try
        hURL := InternetOpenURL(hSession, PChar(URL), nil, 0, 0, 0) ;
        try
          AssignFile(f, FileName);
          Rewrite(f,1);
          try
            repeat
              InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen) ;
              BlockWrite(f, Buffer, BufferLen)
            until BufferLen = 0;
          finally
            CloseFile(f) ;
            Result := True;
          end;
        finally
          InternetCloseHandle(hURL)
        end
      finally
        InternetCloseHandle(hSession)
      end;
    end;