17

What is the easiest way to do an HTTPS POST request in Delphi? I'm not having problems with making HTTP POST requests, but how can I do it using SSL? I've googled around and haven't found anything that explains this well enough.

Here's the code I tried:

procedure TForm1.FormCreate(Sender: TObject);
var
  responseXML:TMemoryStream;
  responseFromServer:string;
begin
  responseXML := TMemoryStream.Create;
  IdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(self);
  with idSSLIOHandlerSocketOpenSSL1 do
    begin
      SSLOptions.Method := sslvSSLv2;
      SSLOptions.Mode := sslmUnassigned;
      SSLOptions.VerifyMode := [];
      SSLOptions.VerifyDepth := 0;
      host := '';
    end;

  IdHTTP1 := TIdHTTP.Create(Self);
  with IdHTTP1 do
    begin
      IOHandler := IdSSLIOHandlerSocketOpenSSL1;
      AllowCookies := True;
      ProxyParams.BasicAuthentication := False;
      ProxyParams.ProxyPort := 0;
      Request.ContentLength := -1;
      Request.ContentRangeEnd := 0;
      Request.ContentRangeStart := 0;
      Request.Accept := 'text/html, */*';
      Request.BasicAuthentication := False;
      Request.UserAgent := 'Mozilla/3.0 (compatible; Indy Library)';
      HTTPOptions := [hoForceEncodeParams];
    end;
  responsefromserver := IdHTTP1.Post('https://.../','name1=value1&name2=value2&....');
end;

When I try to run it I get the following error:

Project myProject.exe raised exception class EFOpenError with message 'Cannot open file "C:\...\Projects\Debug\Win32\name1=value1name2=value2 The system cannot find the file specified'.

I don't understand that. I sent parameters, though the errors sounds like I would have sent a file.

Also I have included libeay32.dll and ssleay32.dll within my myProject.exe folder.

Sebastian Zartner
  • 18,808
  • 10
  • 90
  • 132
Peacelyk
  • 1,126
  • 4
  • 24
  • 48

4 Answers4

3

You didn't specified your Delphi version or indy version, but I had some problems before with the bundled Indy with Delphi 2009 and HTTPS, and when I got the latest source from indy svn, the problem solved.

Mohammed Nasman
  • 10,992
  • 7
  • 43
  • 68
2

http://chee-yang.blogspot.com/2008/03/using-indy-https-client-to-consume.html

var S: TStringList;
   M: TStream;
begin
 S := TStringList.Create;
 M := TMemoryStream.Create;
 try
   S.Values['Email'] := 'your google account';
   S.Values['Passwd'] := 'your password';
   S.Values['source'] := 'estream-sqloffice-1.1.1.1';
   S.Values['service'] := 'cl';

   IdHTTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
   IdHTTP1.Request.ContentType := 'application/x-www-form-urlencoded';
   IdHTTP1.Post('https://www.google.com/accounts/ClientLogin', S, M);
   Memo1.Lines.Add(Format('Response Code: %d', [IdHTTP1.ResponseCode]));
   Memo1.Lines.Add(Format('Response Text: %s', [IdHTTP1.ResponseText]));

   M.Position := 0;
   S.LoadFromStream(M);
   Memo1.Lines.AddStrings(S);
 finally
   S.Free;
   M.Free;
 end;

end;

k.bon
  • 386
  • 2
  • 9
2

So the short answer is simple, use a COM-Object with flexible late binding, example of a translate service with language detection, implements in maXbox script:

function getPostTranslateLibre(feedstream: string): string;
var
  Url,API_KEY, source: string;
  jo, locate: TJSONObject;
  httpReq,hr: Olevariant;
  strm: TStringStream;
begin
  httpReq:= CreateOleObject('WinHttp.WinHttpRequest.5.1');
  // Open the HTTPs connection.  
  try              
    hr:= httpReq.Open('POST','https://libretranslate.pussthecat.org/detect', false);
    httpReq.setRequestheader('user-agent',
          'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0');
    httpReq.setRequestheader('content-type','application/x-www-form-urlencoded');  
    //httpReq.setRequestheader('X-RapidAPI-Host','nlp-translation.p.rapidapi.com');   
    //httpReq.setRequestheader('X-RapidAPI-Key','...333'); 
              
    if hr= S_OK then HttpReq.Send('q='+HTTPEncode(feedstream));
     /// Send HTTP Post Request & get Responses. 
    
    If HttpReq.Status = 200 Then
       result:= HttpReq.responseText
    Else result:= 'Failed at getting response:'+itoa(HttpReq.Status)+HttpReq.responseText;
    //writeln('debug response '+HttpReq.GetAllResponseHeaders);     
  finally
    httpreq:= unassigned;  
  end;                  
end; 

As early binding compiled we use LHttpClient: TALWininetHttpClient; https://github.com/infussolucoes/usercontrol-sd/blob/master/Source/Terceiros/Alcinoe/ALHttpClient.pas

Max Kleiner
  • 1,442
  • 1
  • 13
  • 14
0

Another alternative to Indy is Synapse.

This class library offers full control of the post, but also offers a simple one liner post method as well:

function HttpPostURL(const URL, URLData: string; const Data: TStream): Boolean;
Darian Miller
  • 7,808
  • 3
  • 43
  • 62