Delphi 的 Datasnap ISAPI 模块上的 CORS 问题

CORS issue on a Delphi's Datasnap ISAPI Module

AngularJS 客户端访问的 Datasnap REST(Delphi 10.1 Berlin)服务器出现问题。我无法激活授权,因为 Angular 无法在 Pragma Header 中发送 dssession,这似乎是 CORS 的问题,因为浏览器是更改该 Header 的浏览器(启动 Chrome 与 - -disable-web-security flat everything 运行s fine).

甚至运行ning Angular和Datasnap在同一台机器上测试(Angular在localhost:8080和Datasnap在localhost:8081),浏览器检测调用作为跨源调用,当 Angular 尝试发送 dssession 时,它不会到达 Datasnap。注意:我允许使用以下代码进行跨域调用:code http://delphi.org/2015/04/cors-on-datasnap-rest-server/

运行 作为独立应用程序的服务器 我可以在 WebModuleBeforeDispatch 事件中看到 TWebRequest 获得一个值为 "Pragma" 的 Access-Control-Request-Headers 而不是预期的 Pragma Header,所以看起来浏览器正在发出 CORS 选项请求,而 Datasnap 没有回答它(它引发了带有 "command closed or unassigned" 消息的 TDSServiceException)。

我已经为 StandAlone 应用程序解决了它,通过 URL 传递 dssession(它不会干扰参数的正常传递,因为我只使用来自 [=36 的 POST 调用=]JS),然后拦截 WebModuleBeforeDispatch 事件上的请求,并手动添加一个 Pragma Header,其中包含从调用 URL.

检索到的 dssession
procedure TWebModule1.WebModuleBeforeDispatch(Sender: TObject; Request: TWebRequest; 
                                              Response: TWebResponse; var Handled: Boolean);
var Token: string;
begin
  Response.SetCustomHeader('Access-Control-Allow-Origin','*');     // Allow CORS calls

  Token := TIdHTTPAppRequest(Request).Query;         // Set session on Pragma from the URL
  if Copy(Token, 1, 10) = 'dssession=' then begin
    TIdHTTPAppRequest(Request).GetRequestInfo.RawHeaders.AddValue('Pragma', Token);
  end;

  if FServerFunctionInvokerAction <> nil then
    FServerFunctionInvokerAction.Enabled := AllowServerFunctionInvoker;
end;

它在那个 StandAlone 应用程序上运行良好,但是当我将我的代码重新编译为 ISAPI 模块以将其部署到最终生产环境时,它没有在请求中添加 dssession Pragma Header,可能是因为它没有'无法让 dssession 通过 URL,但我不能确定原因,因为我无法让我的 Delphi 调试那个 ISAPI 模块。

我按照这个教程:http://edn.embarcadero.com/article/40873 并且我可以正确地设置为 运行 我的 ISAPI 模块,但是当我将 w3wp.exe 进程附加到我的 Delphi 调试器时它不会停止到任何断点(它们似乎已禁用,就像代码是使用 Release Build 而不是 Debug Build 编译的一样),事实上,w3wp.exe 进程似乎被冻结并且不参加任何调用,直到我将它从 Delphi 调试器中分离出来。

因此,我将不胜感激任何能够调试该模块的建议,更重要的是,当您的浏览器将 dssession 检测为跨源调用时将它们传递给 ISAPI 模块。

非常感谢。

我终于找到了一个巧妙的解决方案来设置 Datasnap 以响应 CORS 请求,因为它应该响应它们。

当您的 Datasnap 在 WebModule.Before 调度事件上收到 COR 请求时,您只需回答允许发送自定义的 header (Pragma),将 Handled 设置为 True 很重要,因此Datasnap 不会尝试将该 OPTION 请求作为调用方法的正常请求来管理。

procedure TWebModule1.WebModuleBeforeDispatch(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  Response.SetCustomHeader('Access-Control-Allow-Origin','*');        

  if Trim(Request.GetFieldByName('Access-Control-Request-Headers')) <> '' then 
  begin 
    Response.SetCustomHeader('Access-Control-Allow-Headers', Request.GetFieldByName('Access-Control-Request-Headers'));        
    Handled := True;
  end;

  if FServerFunctionInvokerAction <> nil then
    FServerFunctionInvokerAction.Enabled := AllowServerFunctionInvoker;
end;