Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to use JSONP with a Delphi DataSnap REST server?

It appears that there is no way to implement a JSONP (JSON with Padding) solution using DataSnap, but I want to throw this question out here in case someone has solved this problem.

Background: JSONP is a mechanism that exploits the cross site referencing capability of the HTML script element to overcome the same origin policy of the XmlHttpRequest class. Using an XmlHttpRequest you can only obtain data (JSON objects) from the same domain that served the HTML document. But what if you want to retrieve data from multiple sites and bind that data to controls in the browser?

With JSONP, your src attribute of the script element does not reference a JavaScript file, but instead references a Web method (one that can reside on a different domain from which the HTML was retrieved). This Web method returns the JavaScript.

The script tag assumes that the returned data is a JavaScript file and executes it normally. However, what the Web method actually returns is a function call with a literal JSON object as its parameter. Assuming that the function that is called is defined, the function executes and can operate on the JSON object. For example, the function can extract data from the JSON object and bind that data to the current document.

The pros and cons of JSONP have been argued extensively (it represents a very serious security problem), so it is not necessary to repeat that here.

What I am interested in is if anybody out there has figured out how to use JSONP with Delphi's DataSnap REST servers. Here's the problem, as I see it. A typical JSONP usage may include a script tag that looks something like this:

<script type="application/javascript" src="http://someserver.com/getdata?callback=workit"> </script>

The getdata Web method would return a call something like the following:

workit({"id": "Delphi Pro", "price":999});

and the workit function might look something like this:

function workit(obj) {
  $("#namediv").val(obj.id);
  $("#pricediv").val(obj.price);
}

The issue is that DataSnap does not seem capable of returning a simple string like

workit({"id": "Delphi Pro", "price":999});

Instead, it is wrapped, like the following:

{"result":["workit({\"id\":\"Delphi Pro\",\"price\":999});"]}

Clearly this is not executable JavaScript.

Any ideas?

like image 491
Cary Jensen Avatar asked Jul 16 '11 19:07

Cary Jensen


1 Answers

There is a way in Delphi DataSnap REST methods to bypass the custom JSON processing and return exactly the JSON you want. Here is a class function I use (in my Relax framework) to return plain data to a jqGrid:

class procedure TRlxjqGrid.SetPlainJsonResponse(jObj: TJSONObject);
begin
  GetInvocationMetadata().ResponseCode := 200;
  GetInvocationMetadata().ResponseContent := jObj.ToString;
end;

Info at http://blogs.embarcadero.com/mathewd/2011/01/18/invocation-metadata/.
Info at https://mathewdelong.wordpress.com/2011/01/18/invocation-metadata/.

BTW, you can assign nil to the result of the REST function.

like image 111
Marco Cantù Avatar answered Oct 09 '22 16:10

Marco Cantù