在 GET 请求中使用 URL 中的希腊字母

Use Greek letters in URL in GET request

我正在 Delphi 10.4 中开发一个 Android 应用程序。我的客户端通过网络服务与服务器通信。

我使用带有 GET 方法的按名称搜索服务来获取名称列表,具体取决于我输入的字母是英语还是希腊语 TEdit。代码行如下所示:

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

每次用户在 TEdit 和 returns 中输入以用户输入的文本的第一个字母开头的字母时,都会调用该请求。

当我使用英文字母时,搜索工作正常,但当我使用希腊字母时,它无法正常工作。相反,它 returns 所有名称列表 1.

我在浏览器中使用希腊字母尝试路径,如下所示:http://.../Names/search/Αντ,它起作用了,returns 以 Αντ 开头的名称。但是在应用程序中,它不起作用。

会不会是TEditTIdHTTP组件的编码有误?

好像不读希腊字母,发的是空字符串

1因为如果路径是:http://.../Names/search/,它returns所有的名字列表。

我的代码如下所示:

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 不能包含 未编码 non-ASCII 字符。您不能只附加 TEdit 文本 as-is,您需要 url-encode 任何 non-ASCII 字符,以及 URI 规范保留的字符。

如果您使用浏览器的 built-in 调试器,您会发现它在向服务器传输请求时实际上是在进行这种编码。例如,URL 像:http://.../Names/search/Αντ 发送这样的请求:

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

通知Αντ=>%CE%91%CE%BD%CF%84

在您的代码中,您可以使用 Indy 的 TIdURI class 来实现此目的,例如:

uses
  ..., IdURI;

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

旁注:

由于您发送的是 GET 请求,因此不需要设置 Request.ContentTypeRequest.CharSetRequest.ContentEncoding 属性(此外,'UTF-8' 无效ContentEncoding 无论如何)。

此外,ParseJSONValue() 有一个需要 string 的重载,因此您不需要使用 TEncoding.UTF8.GetBytes().