Search code examples
delphinetwork-programmingdelphi-7indy

Interrupt HTTP GET operation


In a special diagnostics mode, I test for an internet connection by performing an HTTP GET operation on a known always-expected-to-be-live server. While this is normally very fast, this can be slow and/or timeout after 15s or more when working in a remote location or when the computer network adapter is disabled.

Is is possible to configure the Indy component so that I can interrupt it on demand? Or maybe there is a better way to perform a test HTTP GET operation? My code is below which I might call with HasInternet(http://master11.teamviewer.com/);

function HasInternet(strTestWebServer: String) : Boolean;
var
    idHTTP: TIdHTTP;
begin
    // Test an internet connection to the named server
    Result := False;
    idHTTP := TIdHTTP.Create(nil);
    if (idHTTP <> nil) then
        begin
        try
            try
                // Handle redirects in response from HTTP server. Not required for some servers,
                // but can confirm a connection to servers that redirect to https.
                idHTTP.HandleRedirects := True;

                // Add in the HTTP protocol header (if required) and retrieve the HTTP resource
                // Note: HTTP_PROTOCOL = 'http://';
                if (AnsiPos(HTTP_PROTOCOL, strTestWebServer) > 0) then
                    Result := (idHTTP.Get(strTestWebServer) <> '')
                else
                    Result := (idHTTP.Get(HTTP_PROTOCOL + strTestWebServer) <> '');
            except
                // HTTP protocol errors are sometimes returned by servers, with the status code
                // saved in TIdHTTP.ResponseCode. Common responses include:
                // * 403 Forbidden (request was valid, but server is refusing to respond to it)
                // * 404 Not Found (requested resource could not be found)
                // * 405 Method Not Allowed (requested method not supported by that resource)
                // These errors are counted as "valid connection to the internet possible"
                on E: EIdHTTPProtocolException do
                    // Status code can be found in "E.ReplyErrorCode" or "idHTTP.ResponseCode"
                    Result := True;
            else
                // All other exceptions are counted as definite failures
                Result := False;
            end;
        finally
            idHTTP.Free();
        end;
        end;
end;

Solution

  • You can interrupt a running TIdHTTP HTTP method by calling Disconnect from context of a thread different from the one in which the method was executed. With your design it would mean exposing the internally used TIdHTTP object in some way.

    But for your task you might give e.g. the InternetCheckConnection function a try. For example for Delphi 7 it could be:

    const
      FLAG_ICC_FORCE_CONNECTION = $00000001;
    
    function InternetCheckConnectionA(lpszUrl: PAnsiChar; dwFlags: DWORD; dwReserved: DWORD): BOOL; stdcall;
      external 'wininet.dll' name 'InternetCheckConnectionA';
    
    function InternetCanConnect(const URL: AnsiString): Boolean;
    begin
      Result := Boolean(InternetCheckConnectionA(PAnsiChar(URL), FLAG_ICC_FORCE_CONNECTION, 0));
    end;
    
    function InternetNotConnected(const URL: AnsiString): Boolean;
    begin
      Result := not Boolean(InternetCheckConnectionA(PAnsiChar(URL),
        FLAG_ICC_FORCE_CONNECTION, 0)) and (GetLastError = ERROR_NOT_CONNECTED);
    end;