0

I'm using Indy ver 10.5498 to post some multipart/form data including an attached file to an api. My code is adapted from that supplied to my by Remy in this post, with protocol error handling taken from here. The code I now have works well and I get a response back from the server with data about 2 seconds after making the post.

However on occasion I might need to do a post multiple times very quickly, for example by looping through the dataset returned from a database and doing a post for each record.

Is there anything I need to know or any special code I need to write in order to deal with the situation where I might be making a second POST before the first POST has completed sending (or at least before the server's response has been received? Or is the POST a blocking call that does not return control until the response is received?

At the moment the TIdHTTP component is placed on the form, not dynamically created. I could create a new TIdHTTP object for every post and destroy it afterwards if that's necessary.

The code I use to do the post at the moment is below

function TForm1.Upload(url: string; params, filenames: TStrings): string;
var
 FormData : TIdMultiPartFormDataStream;
 ResponseText : string;
 i : integer;
begin
  FormData := TIdMultiPartFormDataStream.Create;
  try
    for i := 0 to params.Count - 1 do
      FormData.AddFormField(params.Names[i], params.ValueFromIndex[i]);
    for i := 0 to filenames.Count - 1 do
       FormData.AddFile('attachment', filenames[i]);   

    //add authorisation header
    IdHTTP1.Request.CustomHeaders.Add('Authorization:Basic ' + U_generalStuff.base64encodeStr(ATHORISATION_STR));

    //way to use just one try except yet get the full text server response whether its a 400 error or a success response
    //see https://stackoverflow.com/questions/54475319/accessing-json-data-after-indy-post
    // Make sure it uses HTTP 1.1, not 1.0,  and disable EIdHTTPProtocolException on errors
    IdHTTP1.ProtocolVersion := pv1_1;
    IdHTTP1.HTTPOptions := IdHTTP1.HTTPOptions + [hoKeepOrigProtocol, hoNoProtocolErrorException, hoWantProtocolErrorContent];
    try
       ResponseText := IdHTTP1.Post(url, FormData);   //post to the api
    except
      on E: Exception do
         begin
         ResponseText := E.ClassName + ': ' + E.message;
         raise;
         end;
    end; //try-except
  finally
     result := ResponseText;
  end; //try finally
end;

I've since seen this post that talks about threading and using the parallel library. Is that something I should be investigating to answer my question?

user2834566
  • 775
  • 9
  • 22

1 Answers1

1

Like most things in Indy, TIdHTTP.Post() is a synchronous operation. It does not return back to the caller until the response has been received in full (or until an error occurs). So, if you call TIdHTTP.Post() in a simple loop, you CANT send a new POST request until the previous request has fully completed. If you need to do that, you will have to call TIdHTTP.Post() asynchronously by calling it in multiple worker threads (and give each thread its own TIdHTTP object, as you can't reuse a TIdHTTP object across multiple simultaneous requests).

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770