Question

I am having trouble implementing a HTTP server with indy 10 in delphi 2007.

I have set up a simple event handler for the CommandGet event.

When replying to data sent using the GET method I can parse the params and send XML data back with no problems. (see code below)

    Download := ARequestInfo.Params.Values['dld'];
    Config := ARequestInfo.Params.Values['config'];
    Flash := ARequestInfo.Params.Values['flash'];
    Employees := ARequestInfo.Params.Values['employees'];
    Schedule := ARequestInfo.Params.Values['schedules'];
    AppTables := ARequestInfo.Params.Values['apptables'];

    Heartbeat :=  NewHeartbeat;

    Heartbeat.Version.Dld := Download;
    Heartbeat.Version.Config := Config;
    Heartbeat.Version.Flash := Flash;
    Heartbeat.Version.Employee := Employees;
    Heartbeat.Version.Schedule := Schedule;
    Heartbeat.Version.AppTables := AppTables;

    AResponseInfo.ContentType := 'application/xml';
    AResponseInfo.ResponseNo := 200;
    AResponseInfo.ContentText := '<?xml version="1.0" encoding="utf-8"?>' +
      #13+#10 + FormatXMLData(Heartbeat.XML);

When I try to reply to the data that is sent using a POST the response is never sent by indy, instead a EidConnClosedGracefully is raised by TIdIOHandler.WriteDirect form the CheckForDisconnect(True, True) line. here is how i'm handling the incoming POST data

    XMLDocument1.xml.Clear;
    XMLDocument1.Active := True;
    XMLDocument1.XML.text := ARequestInfo.FormParams;

    SynMemo1.Lines.Add(ARequestInfo.FormParams);
    SynMemo1.Lines.Add(#13+#10);

    if XMLDocument1.XML.Count > 0 then
    begin
      XMLDocument1.XML.Delete(0);
      XMLDocument1.XML.Delete(0);

      for i := pred(xmldocument1.xml.count) downto 0 do
      begin
        stmp := XMLDocument1.XML.Strings[i];

        if Length(stmp) > 0 then
        begin
          if Copy(stmp,1,1) = '<' then
            break
          else
            XMLDocument1.XML.Delete(i);
        end
        else
          XMLDocument1.XML.Delete(i);

      end;

      XMLDocument1.XML.Text := StringReplace(XMLDocument1.XML.Text,
        '<Punches ', '<Punches xmlns="http://ats/punch" ', [rfReplaceAll]);



    end;

    Punch := GetPunches(XMLDocument1);

    PunchReply := NewOperationStatus;
    PunchReply.Uid := Punch.Uid;
    PunchReply.NodeValue := 'OK';

    stmp := '<?xml version="1.0" encoding="utf-8"?>' +
      #13+#10 + FormatXMLData(PunchReply.XML);
    SynMemo1.Lines.Add(stmp);
    SynMemo1.Lines.Add(#13+#10);

    AResponseInfo.ContentType := 'text/html';
    AResponseInfo.ContentStream := TStringStream.Create(stmp);

I have used wireshark to see what is happening and it looks like indy is sending an ACK back before the response is sent and causing the client to disconnect.

to test this I set-up Apache with PHP and wrote a PHP script to do the same job and everything works ok, The difference is the POST data is replied to with the response content not an ACK.

any suggestions on how to resolve this so I respond to the POST data as well as GET.


I'm stuck with this now, as you can see from this wireshark trace (click link for image) i have increased the timeout to 20 seconds. and its still not working. I'm going to do some more investigations. and see what I can find out. Its looking like Indy thinks the disconnect has occurred before it has

Click here for image

Was it helpful?

Solution

Looks like the http is being sent as

Transfer-Encoding: chunked

Therefore there is no content-length. but the version of Indy I am using doesn't support this mode.

OTHER TIPS

ACKs are not sent by Indy itself, but by the underlying socket instead, and even then only in reply to packets received from the other party. EIdConnClosedGracefully means that the client is intentionally disconnecting the socket on its end before your server can sent its reply data. The fact that an ACK is present helps prove that (the socket is likely ACK'ing the client's FIN packet during disconnection).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top