Is there a way to use JSONP with a Delphi DataSnap REST server?
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.
You can write a TDSHTTPServiceComponent descendant and hook it up with your instance of TDSHTTPService
. In the following example an instance of TJsonpDispatcher
is created at runtime (to avoid registering it in the IDE):
type
TJsonpDispatcher = class(TDSHTTPServiceComponent)
public
procedure DoCommand(AContext: TDSHTTPContext; ARequestInfo: TDSHTTPRequest; AResponseInfo: TDSHTTPResponse;
const ARequest: string; var AHandled: Boolean); override;
end;
TServerContainer = class(TDataModule)
DSServer: TDSServer;
DSHTTPService: TDSHTTPService;
DSServerClass: TDSServerClass;
procedure DSServerClassGetClass(DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
protected
JsonpDispatcher: TJsonpDispatcher;
procedure Loaded; override;
end;
implementation
procedure TServerContainer.DSServerClassGetClass(DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
begin
PersistentClass := ServerMethodsUnit.TServerMethods;
end;
procedure TServerContainer.Loaded;
begin
inherited Loaded;
JsonpDispatcher := TJsonpDispatcher.Create(Self);
JsonpDispatcher.Service := DSHTTPService;
end;
procedure TJsonpDispatcher.DoCommand(AContext: TDSHTTPContext; ARequestInfo: TDSHTTPRequest;
AResponseInfo: TDSHTTPResponse; const ARequest: string; var AHandled: Boolean);
begin
// e.g. http://localhost:8080/getdata?callback=workit
if SameText(ARequest, '/getdata') then
begin
AHandled := True;
AResponseInfo.ContentText := Format('%s(%s);', [ARequestInfo.Params.Values['callback'], '{"id": "Delphi Pro", "price":999}']);
end;
end;
the origin policy problem can be solved easyly in DataSnap. You can Customize the response header in this way:
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;