Jump to content
amit

How to Convert curl command line to Delphi code using IndyHttp or THttpClient.

Recommended Posts

I want to use TIdHttp or THTTPClient to send this following curl command.

curl -X POST https://notify-api.line.me/api/notify -H "Authorization: Bearer U4314taadsffhjjjjykllFVissffdfssdfsdfsgfgz" -F "message=abcTest" -F "stickerPackageId=1" -F "stickerId=113" -F "imageFile=@D:/mypic.jpg"

Could you please help me convert this command to Delphi Code using indyhttp or THttpClient?

Edited by amit

Share this post


Link to post

Cannot test it from here, so something is probably still missing, but it might look like this one:

uses
  System.SysUtils,
  REST.Client,
  REST.Authenticator.OAuth,
  REST.Types;

procedure Main;
var
  auth: TOAuth2Authenticator;
  client: TRESTClient;
  request: TRESTRequest;
  response: TCustomRESTResponse;
begin
  client := TRESTClient.Create(nil);
  try
    client.BaseURL := 'https://notify-api.line.me';
    auth := TOAuth2Authenticator.Create(nil);
    try
      auth.TokenType := TOAuth2TokenType.ttBearer;
      auth.AccessToken := 'U4314taadsffhjjjjykllFVissffdfssdfsdfsgfgz';
      client.Authenticator := auth;
      request := TRESTRequest.Create(nil);
      try
        request.Client := client;
        request.Method := rmPOST;
        request.Resource := 'api/notify';
        request.AddParameter('message', 'abcTest', pkREQUESTBODY);
        request.AddParameter('stickerPackageId', '1', pkREQUESTBODY);
        request.AddParameter('stickerId', '113', pkREQUESTBODY);
        request.AddParameter('imageFile', 'D:\mypic.jpg', pkFILE);
        request.Execute;
        response := request.Response;
        if response.Status.Success then
        begin
          Writeln('Success: ' + response.Content);
        end
        else
        begin
          Writeln('Failed with ' + response.StatusText + ': ' + response.Content);
        end;
      finally
        request.Free;
      end;
    finally
      auth.Free;
    end;
  finally
    client.Free;
  end;
end;

 

  • Like 1

Share this post


Link to post

I wonder what is the equivalent command for TIdHTTP and THTTPClient if they were used instead of TRESTClient.  

        request.AddParameter('message', 'abcTest', pkREQUESTBODY);
        request.AddParameter('stickerPackageId', '1', pkREQUESTBODY);
        request.AddParameter('stickerId', '113', pkREQUESTBODY);
        request.AddParameter('imageFile', 'D:\mypic.jpg', pkFILE);

 

Share this post


Link to post

Now I knew how to use TIdHttp and THttpClient instead of TRESTClient.   

For Indy TidHttp,  use TIdMultiPartFormDataStream for adding all Parameters.

For THttpClient, use TMultipartFormData for adding all Parameters

 

Uwe Raabe, Thank for all helps. 

Share this post


Link to post
12 hours ago, amit said:

I wonder what is the equivalent command for TIdHTTP and THTTPClient if they were used instead of TRESTClient.

The TIdHTTP version would look like this:

uses
  ..., IdHTTP, IdSSLOpenSSL, IdMultipartFormDataStream;

var
  HTTP: TIdHTTP;
  SSL: TIdSSLIOHandlerSocketOpenSSL;
  Params: TIdMultipartFormDataStream;
begin
  HTTP := TIdHTTP.Create;
  try
    SSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
    SSL.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
    // other options as needed...

    HTTP.IOHandler := SSL;

    HTTP.Request.BasicAuthentication := False;
    HTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer U4314taadsffhjjjjykllFVissffdfssdfsdfsgfgz';
    // or: HTTP.Request.CustomHeaders.AddValue('Authorization', 'Bearer U4314taadsffhjjjjykllFVissffdfssdfsdfsgfgz');

    Params := TIdMultipartFormDataStream.Create;
    try
      Params.AddFormField('message', 'abcTest');
      Params.AddFormField('stickerPackageId', '1');
      Params.AddFormField('stickerId', '113');
      Params.AddFile('imageFile', 'D:\mypic.jpg');

      HTTP.Post('https://notify-api.line.me/api/notify', Params);
    finally
      Params.Free;
    end;
  finally
    HTTP.Free;
  end;
end;

 

  • Like 1

Share this post


Link to post

Thank you Remy.  I had created the indy version before you reply.     in my version, I did not include IdSSLOpenSSL unit in uses clause and no SSL as shown in your code.    However, it works.     I just wonder if I should use SSL as you suggested.    I'm not sure if I did not use it, it may have problem sometime or not.  
 

Edited by amit

Share this post


Link to post
28 minutes ago, amit said:

I had created the indy version before you reply.     in my version, I did not include IdSSLOpenSSL unit in uses clause and no SSL as shown in your code.    However, it works.

Probably due to this feature:

https://www.indyproject.org/2014/12/22/new-https-functionality-for-tidhttp/

28 minutes ago, amit said:

I just wonder if I should use SSL as you suggested.

You MUST use an SSLIOHandler if you want to access an HTTPS url.  Whether you create your own SSLIOHandler object, or let TIdHTTP create one implicitly, is a separate matter.

  • Like 2

Share this post


Link to post

HI Remy,

I wonder why it can be used on my development PC but not on the target PC.    I got this error on the Target PC - EIdOSSLCouldNotLoadSSLLibrary: Could not load SSL library.     I knew it concerned to SSL libeay32.dll and ssleay32.dll.     I copied it to the application folder but it still have this error.    Can you suggest what should I do?

Share this post


Link to post
1 hour ago, amit said:

I wonder why it can be used on my development PC but not on the target PC.    I got this error on the Target PC - EIdOSSLCouldNotLoadSSLLibrary: Could not load SSL library.     I knew it concerned to SSL libeay32.dll and ssleay32.dll.     I copied it to the application folder but it still have this error.

Very possible that you run into a version conflict. Check used Delphi Indy version and use for that proper libraries.

 

//tip

To find out the location of the "good" library (on your development pc), download a tool like ProcessHacker, run your application, let it load libraries, open ProcessHacker, doubleclick on your process, switch to "Modules" tab, either move mouse over library or doubleclick library, both result in telling you location.

Edited by KodeZwerg
  • Like 1

Share this post


Link to post
17 hours ago, amit said:

I wonder why it can be used on my development PC but not on the target PC.    I got this error on the Target PC - EIdOSSLCouldNotLoadSSLLibrary: Could not load SSL library.     I knew it concerned to SSL libeay32.dll and ssleay32.dll.     I copied it to the application folder but it still have this error.    Can you suggest what should I do?

You likely copied an incompatible version of the OpenSSL DLLs.  For instance, if you copied OpenSSL 1.1.x, as TIdSSLIOHandlerSocketOpenSSL supports only up to OpenSSL 1.0.2 (use this SSLIOHandler instead for 1.1.x). Or, if you copied 32bit DLLs for a 64bit app, or vice versa. What do Indy's OpenSSLVersion() and WhichFailToLoad() functions report?

  • Like 1

Share this post


Link to post
On 4/1/2021 at 6:15 PM, Remy Lebeau said:

The TIdHTTP version would look like this:


uses
  ..., IdHTTP, IdSSLOpenSSL, IdMultipartFormDataStream;

var
  HTTP: TIdHTTP;
.....

 

 

Hi, I'm trying to convert the cUrl for TIdHttp but no success. Can you please tell me where i am wrong? (BAD REQUEST)

curl https://api.dropbox.com/oauth2/token \  -d code=<AUTHORIZATION_CODE> \  -d grant_type=authorization_code \  -u <APP_KEY>:<APP_SECRET>

My (bad) convert:   ( ........ SOLVED !!!  - see the solution below ............)

   IdHTTP := TIdHTTP.Create(nil);
   try
      //'curl https://api.dropbox.com/oauth2/token \     -d code=<AUTHORIZATION_CODE> \     -d grant_type=authorization_code \     -u <APP_KEY>:<APP_SECRET>'
      ssl := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
      ssl.SSLOptions.SSLVersions  := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
      ssl.SSLOptions.Mode         := TidSSLMode.sslmUnassigned;
      ssl.SSLOptions.VerifyMode   := [];
      ssl.SSLOptions.VerifyDepth  := 0;
      ssl.host                    := '';
      //ssl.OnStatusInfoEx          := __IdSSLIOHandlerSocketOpenSSL1StatusInfoEx; 
      ssl.DefStringEncoding       := IndyTextEncoding_UTF8;
      IdHTTP.HandleRedirects  := True;
      IdHTTP.IOHandler        := ssl;
      IdHTTP.Request.BasicAuthentication := False;
      IdHTTP.Request.Username := 'MY_APP_KEY';
      IdHTTP.Request.Password := 'MY_APP_SECRET';

      Params := TIdMultipartFormDataStream.Create;
      try
         Result := True;
         Params.AddFormField('code', 'MY_AUTH_CODE');
         Params.AddFormField('grant_type', 'authorization_code');
         aStatus := IdHTTP.Post('https://api.dropbox.com/oauth2/token', Params);
      except
         on E: EIdHTTPProtocolException do
         begin
            Result := false;
            aStatus := ErrorResult(IdHTTP.ResponseText);
         end;
      end;
      (**)
   finally
      //SSLstatusInfo := fStatusSSLInfo;
      ssl.Free;
      IdHTTP.Free;
   end;

*************   SOLVED  *******************************************************

      IdHTTP.Request.BasicAuthentication := TRUE;
      IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';

********************************************************************************

 

and USES is displayed incorrectly

uses
  ..., IdMultipartFormDataStream;

correct

uses
  ..., IdMultipartFormData;

thanks for Lemy !

 

 

Edited by polasss

Share this post


Link to post
On 1/28/2023 at 1:28 AM, polasss said:

Hi, I'm trying to convert the cUrl for TIdHttp but no success. Can you please tell me where i am wrong?

The original curl request of this discussion thread uses the "-F" parameter, whereas your request uses the "-d" parameter instead.  If you read curl's documentation, the "-F" parameter sends an HTTP "multipart/form-data" request, whereas the "-d" parameter sends an HTTP "application/x-www-form-urlencoded" request.  The TIdHTTP.Post() method has separate overloads for those types of requests.  Your code is using the wrong overload.  You need to use the overload that takes a TStrings, not a TIdMultipartFormDataStream, eg:

Result := False;

IdHTTP := TIdHTTP.Create(nil);
try
  //'curl https://api.dropbox.com/oauth2/token \     -d code=<AUTHORIZATION_CODE> \     -d grant_type=authorization_code \     -u <APP_KEY>:<APP_SECRET>'

  ssl := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
  ssl.SSLOptions.SSLVersions  := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
  ssl.SSLOptions.Mode         := TidSSLMode.sslmUnassigned;
  ssl.SSLOptions.VerifyMode   := [];
  ssl.SSLOptions.VerifyDepth  := 0;
  //ssl.OnStatusInfoEx          := __IdSSLIOHandlerSocketOpenSSL1StatusInfoEx; 

  IdHTTP.HandleRedirects  := True;
  IdHTTP.IOHandler        := ssl;

  IdHTTP.Request.BasicAuthentication := True;
  IdHTTP.Request.Username := 'MY_APP_KEY';
  IdHTTP.Request.Password := 'MY_APP_SECRET';

  try
    Params := TStringList.Create;
    try
      Params.Add('code=MY_AUTH_CODE');
      Params.Add('grant_type=authorization_code');
      aStatus := IdHTTP.Post('https://api.dropbox.com/oauth2/token', Params);
      Result := True;
    finally
      Params.Free;
    end;
  except
    on E: EIdHTTPProtocolException do
    begin
      aStatus := ErrorResult(IdHTTP.ResponseText);
    end;
  end;
  (**)
finally
  IdHTTP.Free;
end;

 

Edited by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×