3

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?

ar099968
  • 6,963
  • 12
  • 64
  • 127
  • 5
    so basically executing a DOS attack?? – whosrdaddy Jul 09 '18 at 16:48
  • 1
    How can you be sure that the GET reached the server when the code does not wait for a reaction (or a timeout)? – mjn Jul 09 '18 at 16:48
  • 1
    Why you don´t execute this code into a Thread? – Luiz Alves Jul 09 '18 at 18:34
  • 3
    This is a pointless thing to do. What are you *actually* trying to accomplish? – J... Jul 09 '18 at 19:09
  • just for talk... the purpose is send some statistical data on software usage, without impact the software performance. Isn't important the server response, because it only collect the data. – ar099968 Jul 10 '18 at 07:04
  • 2
    You may use ICS TCP/IP IP library , open source, asynchronous, event-driven and thread-safe more informations here : http://edn.embarcadero.com/cs/article/20465 – philnext Jul 10 '18 at 11:44
  • You should really be doing this in a background thread. That won't impact "software performance" but it will ensure that you do things correctly. It will also be faster than what you are doing because it still takes time to open the TCP/IP connection, etc. You would be far better off adding this statistical information to a list and then pulling the information from that list in a background thread and sending it through to your server. – Graymatter Jul 11 '18 at 22:21
  • I'm no expert, but wouldn't UDP be more indicated in this sort of situation? – Frazz Jul 12 '18 at 12:47
  • @Frazz i think because UDP is [connectionless](https://en.wikipedia.org/wiki/Connectionless_communication) – ar099968 Jul 12 '18 at 12:50
  • But you don't actually care about any response... neither do you seem to bother the server ever received the data. I thought that would be a perfect job for UDP. – Frazz Jul 12 '18 at 12:54

1 Answers1

11

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/');
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770