delphi Indy Http服务器提供了语法错误的Javascript

t5zmwmid  于 2023-02-08  发布在  Java
关注(0)|答案(1)|浏览(144)

我正在尝试使用Indy来提供Javascript(部署Swagger UI来呈现API文档)。

procedure TfmMain.SendJavaScriptFileResponse(AResponseInfo: TIdHTTPResponseInfo; AFileName: String);
begin
  AResponseInfo.ContentType := 'application/javascript';
  AResponseInfo.CharSet := 'utf-8';
  var LFileContents := TStringList.Create;
  try
    LFileContents.LoadFromFile(AFileName);
    AResponseInfo.ContentText := LFileContents.Text;
  finally
    LFileContents.Free;
  end;
end;

当浏览器收到Javascript并试图运行它时,我得到一个语法错误:
未捕获的语法错误:非法字符U +20AC
从Indy IdHttpServer接收到的响应头如下所示:

HTTP/1.1 200 OK
Connection: close
Content-Encoding: utf-8
Content-Type: application/javascript; charset=utf-8
Content-Length: 1063786
Date: Sun, 05 Feb 2023 20:45:56 GMT

然而,当我通过我的托管网站提供完全相同的Javascript文件时,Javascript在浏览器中运行良好,没有错误。
使用Indy HTTP服务器发送Javascript文件时,是否需要使用设置或字符集?

8cdiaqws

8cdiaqws1#

你将Javascript从一个文件加载到一个string中,然后你将这个string发送到客户端。这需要在运行时进行两次数据转换--从文件的编码到内存中的UTF-16,以及从UTF-16到指定的AResponseInfo.Charset。如果你不小心,这两次转换中的任何一次都可能失败。
在内存中, Delphi 2009+中的string始终是UTF-16编码的,但是在将文件加载到TStringList时,您没有指定文件的编码。(例如UTF-8),没有BOM,并且包含任何非ASCII字符(例如,欧元符号),那么TStringList将无法正确地将文件解码为UTF-16。在这种情况下,您必须指定文件的实际编码,例如:

procedure TfmMain.SendJavaScriptFileResponse(
  AResponseInfo: TIdHTTPResponseInfo;
  const AFileName: String);
begin
  AResponseInfo.ContentType := 'application/javascript';
  AResponseInfo.CharSet := 'utf-8';
  var LFileContents := TStringList.Create;
  try
    LFileContents.LoadFromFile(AFileName, TEncoding.UTF8); // <-- HERE
    AResponseInfo.ContentText := LFileContents.Text;
  finally
    LFileContents.Free;
  end;
end;

另一种选择是发送实际文件本身,而不必先将其加载并解码到内存中,例如:

procedure TfmMain.SendJavaScriptFileResponse(
  AContext: TIdContext;
  AResponseInfo: TIdHTTPResponseInfo;
  const AFileName: String);
begin
  AResponseInfo.ContentType := 'application/javascript';
  AResponseInfo.CharSet := 'utf-8';
  AResponseInfo.ServeFile(AContext, AFileName);
end;

无论哪种方式,utf-8都不是HTTP Content-Encoding头的有效值。Indy默认情况下不为该头赋值,因此您必须手动赋值。

相关问题