Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有办法将JSONP与Delphi DataSnap REST服务器一起使用?_Delphi_Rest_Jsonp_Delphi Xe_Datasnap - Fatal编程技术网

有没有办法将JSONP与Delphi DataSnap REST服务器一起使用?

有没有办法将JSONP与Delphi DataSnap REST服务器一起使用?,delphi,rest,jsonp,delphi-xe,datasnap,Delphi,Rest,Jsonp,Delphi Xe,Datasnap,似乎没有办法使用DataSnap实现(带填充的JSON)解决方案,但我想在这里抛出这个问题,以防有人解决了这个问题 背景:JSONP是一种利用HTML脚本元素的跨站点引用功能来克服XmlHttpRequest类的同源策略的机制。使用XmlHttpRequest,您只能从提供HTML文档的同一域获取数据(JSON对象)。但是,如果要从多个站点检索数据并将该数据绑定到浏览器中的控件,该怎么办 对于JSONP,script元素的src属性不引用JavaScript文件,而是引用Web方法(可以驻留在从

似乎没有办法使用DataSnap实现(带填充的JSON)解决方案,但我想在这里抛出这个问题,以防有人解决了这个问题

背景:JSONP是一种利用HTML脚本元素的跨站点引用功能来克服XmlHttpRequest类的同源策略的机制。使用XmlHttpRequest,您只能从提供HTML文档的同一域获取数据(JSON对象)。但是,如果要从多个站点检索数据并将该数据绑定到浏览器中的控件,该怎么办

对于JSONP,script元素的src属性不引用JavaScript文件,而是引用Web方法(可以驻留在从中检索HTML的不同域中)。此Web方法返回JavaScript

script标记假定返回的数据是一个JavaScript文件,并正常执行它。然而,Web方法实际返回的是一个函数调用,其参数为文本JSON对象。假设已定义调用的函数,该函数将执行并可以对JSON对象进行操作。例如,该函数可以从JSON对象提取数据,并将该数据绑定到当前文档

JSONP的优点和缺点已经被广泛讨论过(它代表了一个非常严重的安全问题),所以这里不必重复

我感兴趣的是,是否有人知道如何将JSONP与Delphi的DataSnap REST服务器结合使用。在我看来,问题出在这里。一个典型的JSONP用法可能包括一个如下所示的脚本标记:

<script type="application/javascript" src="http://someserver.com/getdata?callback=workit"> </script>
function workit(obj) {
  $("#namediv").val(obj.id);
  $("#pricediv").val(obj.price);
}
workit函数可能如下所示:

<script type="application/javascript" src="http://someserver.com/getdata?callback=workit"> </script>
function workit(obj) {
  $("#namediv").val(obj.id);
  $("#pricediv").val(obj.price);
}
问题是DataSnap似乎无法返回简单的字符串,如

workit({"id": "Delphi Pro", "price":999});
而是将其包装,如下所示:

workit({"id": "Delphi Pro", "price":999});
{"result":["workit({\"id\":\"Delphi Pro\",\"price\":999});"]}
显然,这不是可执行的JavaScript


有什么想法吗?

您可以编写一个TDSHTTPServiceComponent子体,并将其与您的
TDSHTTPService
实例连接起来。在以下示例中,将在运行时创建
TJsonpDispatcher
的实例(以避免在IDE中注册它):


Delphi DataSnap REST方法中有一种方法可以绕过自定义JSON处理并准确返回所需的JSON。以下是我(在我的Relax框架中)用于将普通数据返回到jqGrid的类函数:

class procedure TRlxjqGrid.SetPlainJsonResponse(jObj: TJSONObject);
begin
  GetInvocationMetadata().ResponseCode := 200;
  GetInvocationMetadata().ResponseContent := jObj.ToString;
end;
信息地址:
信息在


顺便说一句,您可以将nil分配给REST函数的结果。

可以在DataSnap中轻松解决源策略问题。您可以通过以下方式自定义响应标头:

procedure TWebModule2.WebModuleBeforeDispatch(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  **Response.SetCustomHeader('access-control-allow-origin','*');**
  if FServerFunctionInvokerAction <> nil then
    FServerFunctionInvokerAction.Enabled := AllowServerFunctionInvoker;
end;
过程TWebModule2.WebModuleBeforeDispatch(发送方:TObject;
请求:TWebRequest;响应:TWebResponse;处理的变量:Boolean);
开始
**SetCustomHeader('access-control-allow-origin','*')**
如果FServerFunctionInvokerAction为nil,则
FServerFunctionInvokerAction.Enabled:=AllowServerFunctionInvoker;
结束;

Nicolás Loaiza的回答激励我找到TDSHTTP服务的解决方案,在跟踪事件中设置客户响应标题:

procedure TDataModule1.DSHTTPService1Trace(Sender:
    TObject; AContext: TDSHTTPContext; ARequest: TDSHTTPRequest; AResponse:
    TDSHTTPResponse);
begin
  if AResponse is TDSHTTPResponseIndy then
    (AResponse as TDSHTTPResponseIndy).ResponseInfo.CustomHeaders.AddValue('access-control-allow-origin', '*');
end;

问题可以简化为“DataSnap是否提供了一个过滤器/钩子/事件,允许在发送到客户端之前修改生成的JSON响应?”谢谢,Marco!很好的解决方案。谢谢你在Mat DeLong的博客中加入了关于这种技术的链接。是的,谢谢你链接到我的博客Marco:)非常好的解决方案。谢谢你的回复。我希望我能接受你和马可的回答都是正确的(不可能)。我接受了马可的答案,因为它很简单。但是,我已经投票支持了你的解决方案。@Cary谢谢你!我也更喜欢马可的答案,了解
tds
非常有趣。不幸的是,它似乎没有公开有关请求的信息,只有响应。有时,从服务器方法中访问请求数据可能很有用。这是一个很好的解决方案,但在我的代码中,DoCommand过程从未被调用。使用Delphi XE7..我还没有机会尝试这种方法,但感谢您的贡献。