Search code examples
delphiindyidhttp

Delphi send HTTP GET request without wait for the server response


I want send HTTP request (GET) without wait for the server response.

I have tried with IdHTTP by ignoring the response, eg.:

aIdHTTP := TIdHTTP.create;
try
  aIdHTTP.Get('https://stackoverflow.com/');
finally
  aIdHTTP.free;
free

but it always wait for the server response...

A trick is close the connection by raising an exception in the TIdHTTP.OnWork event when AWorkMode is wmRead, this close the connection sooner... but wait for the "first byte" response.

There is a way for send data without waiting for the response?


Solution

  • The short answer is NO, well not with TIdHTTP, anyway. HTTP is a protocol, and TIdHTTP follows the protocol, which includes reading the server's response.

    As you discovered, you could raise an exception in the TIdHTTP.OnWork event, but that will only work once at least 1 byte is received from the server. You could specify a short TIdHTTP.ReadTimeout value to avoid that, though.

    Another option is to close the socket connection in the TIdHTTP.OnHeadersAvailable event, but that requires TIdHTTP reading the server's complete response headers.

    IF the response is using HTTP 1.1 chunking, you could enable the hoNoReadChunked flag in the TIdHTTP.HTTPOptions property. But that also requires reading the server's complete response header.

    Really, the only way to accomplish what you are asking for is to not use TIdHTTP at all. Use TIdTCPClient instead, and manually send your own HTTP request and then close the connection after sending it, eg:

    aIdClient := TIdTCPClient.Create;
    try
      aIdClient.Host := 'stackoverflow.com';
      aIdClient.Port := 443;
    
      aIdClient.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(aIdClient);
      TIdSSLIOHandlerSocketOpenSSL(aIdClient.IOHandler).PassThrough := False;
    
      aIdClient.Connect;
      try
        aIdClient.IOHandler.WriteLn('GET / HTTP/1.1');
        aIdClient.IOHandler.WriteLn('Host: stackoverflow.com');
        aIdClient.IOHandler.WriteLn('Connection: close');
        aIdClient.IOHandler.WriteLn;
      finally
        aIdClient.Disconnect;
      end;
    finally
      aIdClient.free;
    end;
    

    But what is the point of requesting a file and not actually downloading it?

    If you just want to check that the server can be connected to, you don't have to send anything at all

    aIdClient := TIdTCPClient.Create;
    try
      aIdClient.Host := 'stackoverflow.com';
      aIdClient.Port := 443;
      aIdClient.Connect;
      aIdClient.Disconnect;
    finally
      aIdClient.free;
    end;
    

    If you are just trying to avoid downloading a file's actual content over HTTP, you could use TIdHTTP.Head() instead of TIdHTTP.Get():

    aIdHTTP.Head('https://stackoverflow.com/');