Search code examples
androiddelphiindyidhttp

Use Greek letters in URL in GET request


I'm developing an Android app in Delphi 10.4. My client communicates with the server through web services.

I use a search-by-name service with the GET method to take a list of names depending on what letter, English or Greek, I type in a TEdit. The line of code looks like this:

mydata := IdHTTP1.GET('http://.../Names/search/'+Edit1.Text);

The request is called every time the user types a letter in the TEdit, and returns the names that start with the first letter(s) of the text that the user typed.

When I use English letters, the search works fine, but when I use Greek letters, it doesn't work properly. Instead, it returns all the list of names 1.

I try the path in a browser using Greek letters, like this: http://.../Names/search/Αντ, and it works, it returns the names starting with Αντ. But in the app, it doesn't work.

Is it possible that the encoding of the TEdit or TIdHTTP component are wrong?

It's like it doesn't read the Greek letters and sends an empty string.

1 Because if the path is: http://.../Names/search/, it returns all the list of names.

My code looks like this:

procedure TForm1.Edit1ChangeTracking(Sender: TObject);
var
  mydata : string;
  jsv,js : TJSONValue;
  originalObj,jso : TJSONObject;
  jsa : TJSONArray;
  i: Integer;

begin
  Memo1.Lines.Clear;
  try

     IdHTTP1.Request.ContentType := 'application/json';
     IdHTTP1.Request.CharSet := 'utf-8';
     IdHTTP1.Request.AcceptLanguage := 'gr';  
     IdHTTP1.Request.ContentEncoding  := 'UTF-8';
 
     mydata := IdHTTP1.Get('http://.../Names/search/'+Edit1.Text);

  except
    on E: Exception do
    begin
      ShowMessage(E.Message);
    end;
  end;

  try
    jsv := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(mydata),0) as TJSONValue;
    try
      jsa := jsv as TJSONArray;
      for i := 0 to jsa.Size-1 do
      begin
        jso := jsa.Get(I) as TJSONObject;
        js :=  jso.Get('Name').JsonValue;
        Memo1.Lines.Add(js.Value);
         if i=4 then  // show the 5 first names of the search
           break;
       end;
     finally
       jsv.Free();
     end;
  except
    on E: exception do
    begin
      ShowMessage(E.Message);
    end;
  end;
end;

Solution

  • URLs can't contain unencoded non-ASCII characters. You can't just append the TEdit text as-is, you need to url-encode any non-ASCII characters, as well as characters reserved by the URI specs.

    If you use your browser's built-in debugger, you will see that it is actually doing this encoding when transmitting the request to the server. For example, a URL like: http://.../Names/search/Αντ sends a request like this:

    GET /Names/search/%CE%91%CE%BD%CF%84 HTTP/1.1
    Host: ...
    ...
    

    Notice Αντ => %CE%91%CE%BD%CF%84

    In your code, you can use Indy's TIdURI class for this purpose, eg:

    uses
      ..., IdURI;
    
    mydata := IdHTTP1.GET('http://.../Names/search/'+TIdURI.PathEncode(Edit1.Text));
    

    On a side note:

    Since you are sending a GET request, you do not need to set the Request.ContentType, Request.CharSet, or Request.ContentEncoding properties (besides, 'UTF-8' is not valid for ContentEncoding anyway).

    Also, ParseJSONValue() has an overload that takes a string, so you don't need to use TEncoding.UTF8.GetBytes().