Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: CORS Problem: Javascript can't send the dssession in Pragma Header



Permlink Replies: 4 - Last Post: Aug 12, 2016 1:21 AM Last Post By: Marc Guillot
Marc Guillot

Posts: 15
Registered: 3/16/00
CORS Problem: Javascript can't send the dssession in Pragma Header
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 26, 2016 4:45 AM
Hello,

I'm writting a Datasnap REST (Delphi 10.1 Berlin) server accessed by an AngularJS client and I can't activate Authorization because Angular can't send the dssession within a Pragma Header.

Seems to be a problem with CORS, because launching Chrome with the --disable-web-security flag, everything runs perfectly.

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 arrives to Datasnap.

Note: I allow cross-origin calls using the following code http://delphi.org/2015/04/cors-on-datasnap-rest-server/

Looking at the TWebRequest in WebModuleBeforeDispatch, I see that instead of the expected Pragma Header, I get a header Access-Control-Request-Headers with the value "Pragma".

Looks like the browser is issuing a CORS Options request and Datasnap doesn't answers it (it raises an TDSServiceException exception with the "command closed or unassigned" message).

Do you know how can I pass correctly the session between my AngularJS client and Datasnap REST server on CORS calls ?. Is there any Demo that I can look at ?.

Thank you.
Marc Guillot

Posts: 15
Registered: 3/16/00
Re: CORS Problem: Javascript can't send the dssession in Pragma Header
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 26, 2016 7:52 AM   in response to: Marc Guillot in response to: Marc Guillot
Solved. I can't transmit the dssession within the Pragma Header, so I have set AngularJS to append that value at the calling URL (is a POST call, it doesn't interferes with the normal parameters of the server methods called). Now I can intercept the Request on the WebModuleBeforeDispatch, retrieve that value from the URL, and manually add a Pragma with it.

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;

It works, but I will be thankful if someone can suggest a cleaner solution.

Thank you.

Marc Guillot

Posts: 15
Registered: 3/16/00
Re: CORS Problem: Javascript can't send the dssession in Pragma Header
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 5, 2016 12:00 AM   in response to: Marc Guillot in response to: Marc Guillot
It works on an StandAlone Server, but when compiled as an ISAPI module, it doesn't pass the Pragma, so I still have the same problem.

I'm not sure, because I can't debut the ISAPI module (I don't see the w3wp.exe process available to attach the debugger to it), but I suspect that unlike the StandAlone Server, my ISAPI module doesn't get the dssession passed through the URL on Request.Content or Request.Query.

I would appreciate any suggestion.

Thank you.
Marc Guillot

Posts: 15
Registered: 3/16/00
Re: CORS Problem: Javascript can't send the dssession in Pragma Header
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 11, 2016 8:07 AM   in response to: Marc Guillot in response to: Marc Guillot
That solution to avoid CORS management doesn't work on an ISAPI module because their Request: TWebRequest comes from a TISAPIRequest instead of a TIdHTTPAppRequest (Stand-alone server).

On a TIdHTTPAppRequest Request we can access to their RawHeaders through a Helper class to manually add a customized Pragma Header (as seen in my initial solution), but I can't see how to do the same (add a Pragma Header) when my WebRequest comes from a TISAPIRequest.

Can someone show me how to manually add a customized Pragma Header on a WebModuleBeforeDispath Request when that Request is a TISAPIRequest ?. Or is there any other workaround for CORS to use a Datasnap REST server as an ISAPI module ?

Am I the only person trying to run a Datasnap server as an ISAPI Module ?. This is a huge problem, has existed for over a decade, and I can't find that any solution has ever been proposed: https://forums.embarcadero.com/thread.jspa?threadID=107180
Marc Guillot

Posts: 15
Registered: 3/16/00
Re: CORS Problem: Javascript can't send the dssession in Pragma Header
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 12, 2016 1:21 AM   in response to: Marc Guillot in response to: Marc Guillot
I have finally found a neat solution that sets your Datasnap Server to answer to COR requests as it is supposed to answer them.

When your Datasnap receives a COR request 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 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;
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02