delphi-xeindy10

How stop (cancel) a download using TIdHTTP and keep connection


There is a good answer on half of my question: How stop (cancel) a download using TIdHTTP

But if I use Abort, then sometimes the GET request will still continue to run.

If I use Disconnect() then the next GET request will establish a new connection with the server and spend time for that. I run GET requests to an HTTPS server. The HTTPS protocol consumes about 50% time just for establishing connections.

How can I stop a GET request and keep the connection for the next request? How can I sweep garbage and reset state?

I think I need to change:

 try
    try
      ReadBytes(LBuf, i, False);
    except
      on E: Exception do begin

        // ADD THIS!
        if (E is EAbort) then
        begin
          //Set some flags
          //ClearBuffers 
          raise;
        end

        // RLebeau - ReadFromSource() inside of ReadBytes()
        // could have filled the InputBuffer with more bytes
        // than actually requested, so don't extract too
        // many bytes here...

        i := IndyMin(i, FInputBuffer.Size);
        FInputBuffer.ExtractToBytes(LBuf, i, False);
        if (E is EIdConnClosedGracefully) and AReadUntilDisconnect then begin
          Break;
        end else begin                                                                                     
          raise;
        end;
      end;
    end;

Solution

  • Despite your claim, ALL exceptions raised will make TIdHTTP stop running the current request/response cycle, and will propagate the exception back into your code for handling 1.

    1: except in the specific case where an exception is raised when a remote disconnect is performed, and a remote disconnect is expected to indicate the end of the response. TIdHTTP handles that condition internally and stops reading without re-raising the exception.

    My earlier comment on your previous question still applies here:

    You can't abort a request midway and expect to leave the connection open, you don't know what state you are leaving the socket in or what data has already been transmitted. There is no way to clear an HTTP connection and leave it open for a new request. The only sane thing to do is close the connection.

    If you are worried about re-establishing new HTTPS connections taking too long, there are technologies to address that, such as Fast TCP Open and TLS session reuse. But Indy does not implement those features at this time. There are open tickets for them:

    #213: Add support for OpenSSL session reuse

    #263: Add support for TCP Fast Open socket option