We have a problem with a Datasnap REST (Delphi 10.1 Berlin) Server accessed by AngularJS clients. I can't activate Authorization because Angular can't send the dssession within a Pragma Header, seems to be a problem with CORS, because the browser is the one changing that Header (launching Chrome with the --disable-web-security flat everything runs fine).
Even running Angular and Datasnap on the same machine for testing (Angular at localhost:8080 and Datasnap at localhost:8081), the browser detects the calls as Cross-Origin calls and when Angular tries to send the dssession it doesn't arrive to Datasnap. Note: I allow cross-origin calls using the following: code http://delphi.org/2015/04/cors-on-datasnap-rest-server/
Running the Server as an StandAlone application I can see in the WebModuleBeforeDispatch event that the TWebRequest gets an Access-Control-Request-Headers with the value "Pragma" instead of the expected Pragma Header, so it looks like the browser is issuing a CORS Options request and Datasnap doesn't answers it (it raises a TDSServiceException with the "command closed or unassigned" message).
I have solved it for the StandAlone application, passing the dssession through the URL (it doesn't interfere with the normal pass of parameters because I only use POST calls from AngularJS), and then intercepting the Request on the WebModuleBeforeDispatch event and manually adding a Pragma Header with the dssession retrieved from the calling URL.
procedure TWebModule1.WebModuleBeforeDispatch(Sender: TObject; Request: TWebRequest;
Response: TWebResponse; var Handled: Boolean);
var Token: string;
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
if FServerFunctionInvokerAction <> nil then
FServerFunctionInvokerAction.Enabled := AllowServerFunctionInvoker;
I have finally found a neat solution to set Datasnap to answer to CORS requests as it's supposed to answer them.
When your Datasnap receives a COR request on the WebModule.Before dispatch event, you just have to answer to allow sending the customized header (Pragma), it's important to set Handled to True, so Datasnap won't try to manage that OPTION request as a normal request calling for a method.
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;