Raffaele Rossi
Raffaele Rossi

Reputation: 3127

Delphi indy get page content

I have seen a lot of examples online, but I cannot understand why my code doesn't work.

I have an url that looks like this:

http://www.domain.com/confirm.php?user=USERNAME&id=THEID

confirm.php is a page that does some checks on a MySQL database and then the only output of the page is a 0 or a -1 (true or false):

<?php

//long code...
if ( ... ) {
 echo "0"; // success!
 die();
} else {
 echo "-1"; // fail!
 die();
} 

?>

My Delphi FireMonkey app has to open the URL above, passing the username and the id, and then read the result of the page. The result is only a -1 or a 0. This is the code.

//I have created a subclass of TThread
procedure TRegister.Execute;
var
  conn: TIdHTTP;
  res: string;
begin

  inherited;

  Queue(nil,
    procedure
    begin
       ProgressLabel.Text := 'Connecting...';
    end
  );

  //get the result -1 or 0
  try

    conn := TIdHTTP.Create(nil);
    try
      res := conn.Get('http://www.domain.com/confirm.php?user='+FUsername+'&id='+FPId);
    finally
      conn.Free;
    end;

  except
    res := 'error!!';
  end;

  Queue(nil,
    procedure
    begin

      ProgressLabel.Text := res;    
    end
  );

end;

The value of res is always error!! and never -1 or 0. Where is my code wrong? The error caught from on E: Exception do is:

HTTP/1.1 406 not acceptable

Upvotes: 1

Views: 3056

Answers (2)

Jerry Dodge
Jerry Dodge

Reputation: 27266

HTTP Error 406 Not acceptable typically means that the server is not able to respond with the content type the client wanted. Both the Server and Client need to appropriately use the MIME type as you need. In this case, your client's Accept headers should provide the desired type of response, and your server should also be responding with the same. In your case, the Content-Type will most likely be text/plain.

So long story short, your client is expecting a MIME type which the server does not explicitly return in its response. The problem could be on either side, or perhaps both.

  1. Your Client's Accept headers must provide the MIME type(s) you expect and need. Specifically Accept, Accept-Charset, Accept-Language, Accept-Encoding. By default in Indy TIdHTTP, these headers should accept essentially anything, assuming these headers haven't been overwritten. The Accept header is by default set to text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q‌​=0.8 where the */* opens the door for any MIME type.
  2. Your Server's Response's Content-Type must be one of the provided MIME types, as well as the format of the response as also desired by the client. It is likely that your HTTP server is not providing the appropriate Content-Type in its response. If the server responds with anything in the */* filter (which should mean everything), then the client will accept it (assuming the server responds with text/plain). If the server responds with an invalid content type (such as just text or plain), then it could be rejected.

Upvotes: 1

Raffaele Rossi
Raffaele Rossi

Reputation: 3127

I have found a solution using System.Net.HttpClient. I can simply use this function

function GetURL(const AURL: string): string;
var
  HttpClient: THttpClient;
  HttpResponse: IHttpResponse;
begin
  HttpClient := THTTPClient.Create;
  try
    HttpResponse := HttpClient.Get(AURL);
    Result := HttpResponse.ContentAsString();
  finally
    HttpClient.Free;
  end;
end;

This works and gives me -1 and 0 as I expected. To get an example of a working code I have tested this:

procedure TForm1.Button1Click(Sender: TObject);

function GetURL(const AURL: string): string;
var
  HttpClient: THttpClient;
  HttpResponse: IHttpResponse;
begin
  HttpClient := THTTPClient.Create;
  try
    HttpResponse := HttpClient.Get(AURL);
    Result := HttpResponse.ContentAsString();
  finally
    HttpClient.Free;
  end;
end;

function GetURLAsString(const aURL: string): string;
var
  lHTTP: TIdHTTP;
begin
  lHTTP := TIdHTTP.Create;
  try
    Result := lHTTP.Get(aURL);
  finally
    lHTTP.Free;
  end;
end;

begin

 Memo1.Lines.Add(GetURL('http://www.domain.com/confirm.php?user=user&id=theid'));
 Memo1.Lines.Add(GetURLAsString('http://www.domain.com/confirm.php?user=user&id=theid'))

end;

end.

The first function works perfectly but Indy raises the exception HTTP/1.1 406 not acceptable. It seems that Indy cannot automatically handle the content type of the page. Here you can see the REST Debugger log:

enter image description here

Upvotes: 2

Related Questions