I had this function that worked for HTTP. Now, with the wide spread of HTTPS it didn't work anymore. I was getting an "IOHandler value is not valid" error.
So, I created an SSLIOHandler object as shown below, but now I get a new error:
Exception class EIdOSSLUnderlyingCryptoError with message 'Error connecting with SSL. error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version'
How do I setup the SSLIOHandler object properly?
{ Only suitable for small files because the whole download will be saved to RAM before writing it to disk. }
function DownloadFile(CONST SourceURL, DestFileName: string; OUT ErrorMsg: String): Boolean;
VAR
Indy: TIDHTTP;
Stream: TFileStream;
IDAntiFreeze: TIDAntiFreeze;
IOHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
Indy:= TIDHTTP.Create(NIL);
IOHandler:= TIdSSLIOHandlerSocketOpenSSL.Create(NIL);
IDAntiFreeze:= TIDAntiFreeze.Create(NIL);
Stream:= TFileStream.Create(DestFileName, fmCreate);
TRY
IOHandler.Destination := SourceURL;
IOHandler.Host := SourceURL;
IOHandler.MaxLineAction := maException;
//IOHandler.Port := 587;
//IOHandler.DefaultPort := 0;
//IOHandler.OnStatusInfo := SSLIOHandlerStatusInfo;
Indy.ConnectTimeout := 0; { Indy default value: zero }
Indy.ReadTimeout := -1; { Indy default value: -1 }
Indy.HandleRedirects := TRUE; { http://stackoverflow.com/questions/4549809/indy-idhttp-how-to-handle-page-redirects }
Indy.AllowCookies := FALSE;
Indy.Request.UserAgent := 'Mozilla/4.0';
Indy.Request.Connection := 'Keep-Alive';
Indy.Request.ProxyConnection := 'Keep-Alive';
Indy.Request.CacheControl := 'no-cache';
Indy.IOHandler:= IOHandler;
// Indy.OnWork:= HttpWork;
TRY
Indy.Get(SourceURL, Stream);
Result:= TRUE;
EXCEPT
On E: Exception DO
begin
Result:= FALSE;
ErrorMsg := E.Message + ' (' + IntToStr(Indy.ResponseCode) + ')';
end;
END;
FINALLY
FreeAndNil(Stream);
FreeAndNil(IDAntiFreeze);
FreeAndNil(IOHandler);
FreeAndNil(Indy);
END;
end;
PS: The libeay32.dll
and ssleay32.dll
are present in the app's folder.
You are not configuring the TIdSSLIOHandlerSocketOpenSSL
's TLS settings in any way. By default, it enables only TLS 1.0 (known issue: https://github.com/IndySockets/Indy/issues/181), but chances are that the website in question requires TLS 1.1+ instead.
Try adding this:
IOHandler.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
Also, just on a side note, you DO NOT need to configure the IOHandler's Destination
, Host
, or Port
properties at all. TIdHTTP
will handle that internally for you.