Forum > Networking and Web Programming

Implemeting CURL script with Indy

(1/1)

patyit:
Hi all !

Please help me implement this CURL script with Indy:

curl -X POST "https://efakturatest.mfin.gov.rs/api/publicApi/sales-
invoice/ubl/upload?requestId=061720221143-upl&sendToCir=No" -H "accept: text/plain" -H
"ApiKey: d7114d70-14ca-40fe-a840-807c5353fd16" -H "Content-Type: multipart/form-data" -F
"ublFile=@TAM721TEST-test.xml;type=text/xml"

I am trying this code but I don't know how to add
-F "ublFile=@TAM721TEST-test.xml;type=text/xml" script segment.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function sales_invoice_ubl_upload(url, key, ubl, rid: string): string;var  idHttp : TIdHTTP;  par : TStringlist;  res : string;begin  Result := '';  idHttp := TIdHTTP.Create;  try    idHttp.HandleRedirects := False;    idHttp.ReadTimeout     := 30000;    idHttp.Request.Accept  := 'text/plain';    idHttp.Request.ContentType := 'multipart/form-data';    idHttp.Request.CustomHeaders.Add('ApiKey: '+key);     par := TStringList.Create;    try      par.Add('RequestId='+rid);      par.Add('sendToCir=No');      try        url += '/api/publicApi/sales-invoice/ubl/upload';        ubl := '"ublFile=@TAM721TEST-test.xml;type=text/xml"';        res := idHttp.Post(url, ubl);        if idHttp.ResponseCode = 200 then          Result := res        else if idHttp.ResponseCode = 400 then          MessageDlg('Request Error  !'+#13#13+                      IntToStr(IdHttp.ResponseCode)+' '+                      idHttp.ResponseText, mtError, [mbOk], 0)        else          MessageDlg('Error: '+IntToStr(IdHttp.ResponseCode)+' '+                      idHttp.ResponseText, mtError, [mbOk], 0);      except        on E: Exception do begin          Result := '';          MessageDlg('Check internet connection ...'+#13#13+                      E.Message, mtError, [mbOk], 0);        end;      end;    finally      par.Free;    end;  finally    idHttp.Free;    Sleep(200);  end;end;         

patyit:
I modified the code a bit

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function sales_invoice_ubl_upload(url, key, ubl, rid: string): string;var  idHttp : TIdHTTP;  req : TStringStream;  res : string;begin  idHttp := TIdHTTP.Create;  try    idHttp.HandleRedirects := False;    idHttp.ReadTimeout     := 30000;    idHttp.Request.Accept  := 'text/plain';    idHttp.Request.ContentType := 'multipart/form-data';    idHttp.Request.CustomHeaders.Add('ApiKey: '+key);    try      // can i specify such parameters in the url ?      url := url+'/api/publicApi/sales-invoice/ubl/upload?RequestId='+rid+'&sendToCir=No';      // is it correct to define xml and file type ?      ubl := '"ublFile=@'+ubl+';type=text/xml"'; // ?????      res := idHttp.Post(url, ubl);      if idHttp.ResponseCode = 200 then        Result := res      else if idHttp.ResponseCode = 400 then begin        Result := '';        MessageDlg('Request Error  !'+#13#13+                    IntToStr(IdHttp.ResponseCode)+' '+                    idHttp.ResponseText, mtError, [mbOk], 0)      end else begin        Result := '';        MessageDlg('Error: '+IntToStr(IdHttp.ResponseCode)+' '+                    idHttp.ResponseText, mtError, [mbOk], 0);      end;    except      on E: Exception do begin        Result := '';        MessageDlg('Check the Internet connection ...'+#13#13+                    E.Message, mtError, [mbOk], 0);      end;    end;  finally    idHttp.Free;    Sleep(200);  end;end;         

Warfley:
-F sends a FORM body in the POST request, where @ references a local file.
So what you have to do is to read the file TAM721TEST-test.xml and either construct the form content yourself (by url encoding the data and creating a key-value list in the form format), or simply by putting the data in a key-value string list and passing it to the .Post method of IdHTTP

Remy Lebeau:

--- Quote from: patyit on July 14, 2022, 10:05:27 am ---Please help me implement this CURL script with Indy:

--- End quote ---

You are calling TIdHTTP.Post() with a filename as a parameter, which will POST the contents of that file as-is as the entire HTTP request body.  That is not what you need in this situation.


--- Quote from: Warfley on July 14, 2022, 11:40:05 am ---So what you have to do is to read the file TAM721TEST-test.xml and either construct the form content yourself (by url encoding the data and creating a key-value list in the form format) or simply by putting the data in a key-value string list and passing it to the .Post method of IdHTTP

--- End quote ---

That is the wrong advice in this situation.  You can clearly see in the curl example that the request needs to be in multipart/form-data format, but what you suggest will send the request in application/x-www-form-urlencoded format instead.

TIdHTTP.Post() has an overload which takes a TIdMultipartFormDataStream to handle multipart/form-data requests, eg:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function sales_invoice_ubl_upload(url, key, ubl, rid: string): string;var  idHttp : TIdHTTP;  postData: TIdMultipartFormDataStream;begin  Result := '';        idHttp := TIdHTTP.Create;  try    idHttp.HandleRedirects := False;    idHttp.ReadTimeout     := 30000;    idHttp.Request.Accept  := 'text/plain';    idHttp.Request.ContentType := 'multipart/form-data';    idHttp.Request.CustomHeaders.Values['ApiKey'] := key;     postData := TIdMultipartFormDataStream.Create;    try      url := url + '/api/publicApi/sales-invoice/ubl/upload?requestId=' + TIdURI.ParamsEncode(rid) + '&sendToCir=No';      postData.AddFile('ublFile', ubl, 'text/xml');      try        Result := idHttp.Post(url, postData);      except        on E: EIdHTTPProtocolException do begin          if E.ErrorCode = 400 then            MessageDlg('Request Error  !'+#13#13+                        IntToStr(E.ErrorCode) + ' ' + E.Message,                        mtError, [mbOk], 0)          else            MessageDlg('Error: '+IntToStr(E.ErrorCode) + ' ' + E.Message,                        mtError, [mbOk], 0);        end;        on E: Exception do begin          MessageDlg('Check the Internet connection ...'+#13#13+                    E.Message, mtError, [mbOk], 0);        end;      end;    finally      postData.Free;    end;  finally    idHttp.Free;    Sleep(200);  end;end;         
Also note that I moved the handling of the HTTP response code inside of the except block.  By default, TIdHTTP raises EIdHTTPProtocolException if the HTTP response code indicates the request failed.  If you want to handle the TIdHTTP.ResponseCode yourself without raising the exception, you would need to specify the hoNoProtocolErrorException flag in the TIdHTTP.HTTPOptions property, eg:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function sales_invoice_ubl_upload(url, key, ubl, rid: string): string;var  idHttp : TIdHTTP;  postData: TIdMultipartFormDataStream;  res: string;begin  Result := '';        idHttp := TIdHTTP.Create;  try    idHttp.HandleRedirects := False;    idHttp.ReadTimeout     := 30000;    idHttp.Request.Accept  := 'text/plain';    idHttp.Request.ContentType := 'multipart/form-data';    idHttp.Request.CustomHeaders.Values['ApiKey'] := key;    idHttp.HTTPOptions := idHttp.HTTPOptions + [hoNoProtocolErrorException];     postData := TIdMultipartFormDataStream.Create;    try      url := url + '/api/publicApi/sales-invoice/ubl/upload?requestId=' + TIdURI.ParamsEncode(rid) + '&sendToCir=No';      postData.AddFile('ublFile', ubl, 'text/xml');      try        res := idHttp.Post(url, postData);        if idHttp.ResponseCode = 200 then          Result := res        else if idHttp.ResponseCode = 400 then          MessageDlg('Request Error  !'+#13#13+                      IntToStr(idHttp.ResponseCode) + ' ' + idHttp.ResponseText,                      mtError, [mbOk], 0)        else          MessageDlg('Error: '+IntToStr(idHttp.ResponseCode) + ' ' + idHttp.ResponseText,                      mtError, [mbOk], 0);      except        on E: Exception do begin          MessageDlg('Check the Internet connection ...'+#13#13+                    E.Message, mtError, [mbOk], 0);        end;      end;    finally      postData.Free;    end;  finally    idHttp.Free;    Sleep(200);  end;end;         

patyit:
Thank you for your help Remy, (the intention for Warfley as well), I will try the suggested code and let you know the result !

Navigation

[0] Message Index

Go to full version