0

I have a problem posting to a web server using HTTPS. I am not sure if the problem is with me or with the server. So it appeared that if I try to post a Stream greater than 32KB, Delphi crashes with Socket Error 10054 - Connection reset by peer. I am using Delphi XE5 with the internal version of Indy and latest to date open ssl dlls. I also try this on XE with latest to date Indy and ssl dlls.

Here is part of my code

function TForm1.SendItemsList(aDataList: TStringList): Boolean;
var
  aHTTP: TIdHTTP;
  aRes: String;

  aURL: String;
  aErrMsg: String;

  aStrm: TMemoryStream;
  aResStrm: TMemoryStream;
  aXML: TNativeXML;
  aTmpNode: TXmlNode;
  aErrNode: TXmlNode;
  aList: TList;
  i: Integer;

begin
  Result := False;

  aStrm := TMemoryStream.Create;
  aResStrm := TMemoryStream.Create;
  aXML := TNativeXML.Create(nil);
  aHTTP := CreateHTTP('application/x-www-form-urlencoded');
  try
    aDataList.SaveToStream(aStrm);
    aStrm.Position := 0;
    aURL := Format(cIRPURL, ['1']);
    try
      aHTTP.Post(aURL, aStrm, aResStrm);
      aResStrm.Position := 0;

      aXML.LoadFromStream(aResStrm);

      aTmpNode := aXML.Root.FindNode('ResponseCode');
      if aTmpNode <> nil then
      begin
        if aTmpNode.Value <> '0' then
        begin
          aErrNode := aXML.Root.FindNode('ResponseText');
          aErrMsg := '';
          if aErrNode <> nil then
            aErrMsg := aErrNode.Value;
          aList := TList.Create;
          try
            aXML.Root.FindNodes('Detail', aList);
            for i := 0 to aList.Count-1 do
            begin
              aErrMsg := aErrMsg+#13#10+TXmlNode(aList[i]).Value;
            end;
          finally
            aList.Free;
          end;
        end;
      end;
    except
      on E:Exception do
      begin
        if E is EIdHTTPProtocolException then
          aErrMsg := E.Message + #13#10 + (E as EIdHTTPProtocolException).ErrorMessage
        else
          aErrMsg := E.Message;

        Exit;
      end;
    end;
  finally
    aXML.Free;
    aStrm.Free;
    aHTTP.Free;
    aResStrm.Free;
  end;

  Result := True;
end;

Where CreateHTTP looks like

function TForm1.CreateHTTP(aContentType: String): TIdHTTP;
begin
  Result := TIdHTTP.Create(nil);
  Result.ConnectTimeout:=60000;
  Result.ReadTimeout:=90000;
  Result.ProtocolVersion:=pv1_1;
  Result.HTTPOptions := [hoForceEncodeParams];
  Result.HandleRedirects:=True;
  Result.IOHandler := SSLHandler;
  SSLHandler.ReadTimeout := 30000;
  Result.Request.Accept:='*/*';
  Result.Request.AcceptLanguage:='en-US';
  Result.Request.ContentType:=aContentType;
  Result.Request.CharSet:='utf-8';
  Result.Request.UserAgent := 'Mozilla/5.0';
end;

All these timeouts exist just because I was testing why I get that error. Then I realized that the problem is when the stream to be sent is larger than 32KB. I can't really say that there is something wrong with the code at all, because in the same way I send data to several other services like Amazon and Walmart for example where I send sometimes megabytes and I don't receive any errors.

The server is IIS but I don't know what version, the support doesn't seem to believe me that I am doing everything OK.

What I notice is that the SSL handler has some default buffer sizes - SendBufferSize and RecvBufferSize which default to 32KB. Well I tried setting that to 1MB but still I get the same error. If I send something which is less than 32KB then everything is OK. The error is returned immediately after line with POST is executed - there is no delay, just immediate error. Otherwise sending small streams results in having a delay of a second or two before it gets processed and then the debugger goes to the next line. I started believing it is a setting of the IIS and there is really such a setting, but the guys there say everything on their side is ok and they have 4MB of limit for the requests.

The service provider is IRPCommerce but unfortunately I can't give links for testing because of IP filtering which takes place at the moment there.

I spent several days discussing this with them, searching the web for problems any limitations etc. So is there something I am missing here, any limitations in Indy which may cause this problem, I doubt but just to be sure I am asking? Anything else I can do to make it clearer where the problem might be?

EDIT: Here is excerpt of the aDataList:

Stock_ExternalStockID|Brands_Active|Brands_Brand|Models_Active|Models_Model|Models_Description|Models_AdditionalInformation1|Models_AdditionalInformation2|Stock_DisplayOrder|Stock_Option|Stock_Price|Stock_RRP|Stock_SupplierCost|Categories_Active|Categories_Name|Stock_PostageWeight|Stock_PartCode|Stock_ISBNNumber|Stock_UPCAPartCode|Stock_EAN13PartCode|Models_ImageURLs|OptionSelector|OptionSelectorAttributes|OptionSelectorCount|Stock_OutOfStockStatus
17664-00001|TRUE|Polypads|TRUE|Polypads Plus One Outsider Pet Bed|<ul><li>The perfect pet bed for any animal around the house or for covering car seats or boots for travelling. </li><li>Convenient to use.  </li><li>6cm Plus One thickness.  </li><li>Fully machine washable and quick drying. </li><li>As there is such an extensive range of colours available for the Polypad collection many colour combinations will have to be ordered in specifically; this service could take up to two weeks. </li><li>If you do not have any specific colours in mind please select, Colour Not Important, from the drop down menu.</li></ul>| | |10|Royal Blue-Navy|43.95|48.99|21.69|TRUE|Dog Beds|1000|160||||https://saddlery.biz/media/catalog/product/o/u/outp1.jpg|1|21,44|2|10
17664-00002|TRUE|Polypads|TRUE|Polypads Plus One Outsider Pet Bed|<ul><li>The perfect pet bed for any animal around the house or for covering car seats or boots for travelling. </li><li>Convenient to use.  </li><li>6cm Plus One thickness.  </li><li>Fully machine washable and quick drying. </li><li>As there is such an extensive range of colours available for the Polypad collection many colour combinations will have to be ordered in specifically; this service could take up to two weeks. </li><li>If you do not have any specific colours in mind please select, Colour Not Important, from the drop down menu.</li></ul>| | |20|Soft Blue-Royal Blue|43.95|48.99|21.69|TRUE|Dog Beds|1000|160||||https://saddlery.biz/media/catalog/product/o/u/outp1.jpg|1|21,44|2|10
17664-00003|TRUE|Polypads|TRUE|Polypads Plus One Outsider Pet Bed|<ul><li>The perfect pet bed for any animal around the house or for covering car seats or boots for travelling. </li><li>Convenient to use.  </li><li>6cm Plus One thickness.  </li><li>Fully machine washable and quick drying. </li><li>As there is such an extensive range of colours available for the Polypad collection many colour combinations will have to be ordered in specifically; this service could take up to two weeks. </li><li>If you do not have any specific colours in mind please select, Colour Not Important, from the drop down menu.</li></ul>| | |30|Black-Purple|43.95|48.99|21.69|TRUE|Dog Beds|1000|160||||https://saddlery.biz/media/catalog/product/o/u/outp1.jpg|1|21,44|2|10

Here I have 165 rows. If I send about 40 of them they go, just because 40 are just about 32KB. I have confirmed that data is not the problem, because I have tried sending one by one each of the lines.

I tried multipart/form-data with no luck. Actually they haven't told me what to use, no matter how much times I have asked about that, so I used the same thing I am using with Walmart.

I think the server is IIS 8.5.

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • To find out if the issue is client-side or server-side, you could try another client to test the query. For instance you could use curl on the command line (see [here](https://stackoverflow.com/questions/6408904/send-post-request-with-data-specified-in-file-via-curl/6409028#6409028) for an example). – Olivier May 20 '20 at 16:34
  • Actually I used Postman for that, but I receive **HTTP Method of GET is disallowed on this page.** and I am not sure I am doing that right, I tried both Raw and Binary with selecting a file – Georgi Nikolov May 20 '20 at 16:53
  • You must use the POST method. – Olivier May 20 '20 at 17:10
  • I am using the POST method of course, this is not the first time I use Postman, but never with sending files. But I don't get why it is returning that message. – Georgi Nikolov May 20 '20 at 17:28
  • @GeorgiNikolov You did not show the content of `aDataList`, but some web servers do have a max limit on the size of the data being posted. And you are posting an `application/x-www-webform-urlencoded` request, are you sure the server is actually expecting that? Such webforms are typically not expected to be so large. Posting files via webforms typically use `multipart/form-data` instead so they can post unencoded binary data. – Remy Lebeau May 20 '20 at 19:09
  • @RemyLebeau please see the EDIT part. Well I am interested if Indy makes any limitations, probably there is on one better than you who can say. From what I see going briefly in some of the units, there is no such a limit. – Georgi Nikolov May 20 '20 at 20:33
  • @GeorgiNikolov `application/x-www-webform-urlencoded` is meant for `name=value` pairs of data. That is NOT what you are actually posting, so why are you using `application/x-www-webform-urlencoded` at all? What are you REALLY trying to accomplish? If `aDataList` is supposed to represent raw file data, then you probably need to use `Put()` instead of `Post()`, or at least use a more suitable `ContentType` like `text/plain` or even `application/octet-stream`. So, again, I ask, what is the server ACTUALLY EXPECTING you to transmit? Please provide those details. – Remy Lebeau May 20 '20 at 20:40
  • @GeorgiNikolov "*I tried multipart/form-data with no luck*" - you can't send a `multipart/form-data` request with the `TStrings` overload of `TIdHTTP.Post()`, you need to use the `TIdMultipartFormDataStream` overload instead. "*Actually they haven't told me what to use, no matter how much times I have asked about that*" - then how do you expect to interact with this server if you don't know its protocol? "*I used the same thing I am using with Walmart*" - just because something works on one webserver does not meant it will work on another webserver. Every webserver has its own requirements. – Remy Lebeau May 20 '20 at 20:41
  • They told me to POST **Pipe Delimited in Input Stream** I was suspicious about the content type, but never got a proper answer and since it was posting without a problem I left it in that way until problems with larger data started. So now I tried text/xml and it worked. **application/octet-stream** throws the same error – Georgi Nikolov May 20 '20 at 20:51
  • I've rolled back your edit. It is not appropriate here to add SOLVED and edit a solution into your question. If you've found a solution you want to share, do so by writing an answer in the space provided below for that purpose. See [Can I answer my own question?](http://stackoverflow.com/help/self-answer) for more information. – Ken White May 20 '20 at 23:21
  • @GeorgiNikolov the data you showed is not XML so `text/xml` would not be an appropriate `ContentType`. Makes me think that either the webserver ignores the `ContentType`, or is misconfigured. – Remy Lebeau May 21 '20 at 05:13

1 Answers1

0

It seems that the "solution" is to change the Content-type to text/xml. None of the other mentioned content-types work with streams larger than 32KB. At the same time I got a confirmation from the developers of the site that the content-type is not considered at all on the server side. So I am really confused what is going on here and why only 'text/xml' works fine.

  • Indy does not care what you set the `Content-Type` header to, it will just be sent to the server as-is, so any behavioral differences due to different `Content-Type` values has to be on the server side. – Remy Lebeau May 26 '20 at 00:34