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;
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()
.