3
votes

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?

1
so basically executing a DOS attack?? - whosrdaddy
How can you be sure that the GET reached the server when the code does not wait for a reaction (or a timeout)? - mjn
Why you don“t execute this code into a Thread? - Luiz Alves
This is a pointless thing to do. What are you actually trying to accomplish? - J...
You may use ICS TCP/IP IP library , open source, asynchronous, event-driven and thread-safe more informations here : edn.embarcadero.com/cs/article/20465 - philnext

1 Answers

11
votes

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/');