Title: How to do JavaScript calls to the RTC server using XML-RPC Post by: brian71us on September 16, 2016, 04:07:28 PM I've built a simple server using Real Thin Client that has a couple of functions. I'd like to call these functions from a web page using the XML-RPC library below. http://plugins.jquery.com/xmlrpc/ I have added the library to my web page as described and created a function (shown below) to make a request. function getUsers() { $.xmlrpc({ url: 'http://localhost:8095/mytest', methodName: 'GetData', params: [{Table: 'BrechbuhlerUser'}], success: function(response, status, jqXHR) { document.getElementById("theResponse").innerHTML = response; }, error: function(jqXHR, status, error) { document.getElementById("theResponse").innerHTML = error; } }); The server is listening on port 8095 and I have TRtcServerModule with the module file name 'mytest', a function group, and two functions (one named GetData). The function's event handler is shown below. procedure TDataModule1.RtcFunction2Execute(Sender: TRtcConnection; Param: TRtcFunctionInfo; Result: TRtcValue); var ja: TJSONArray; results: string; begin with Sender as TRtcDataServer do begin results := ''; query.SQL.Text := 'SELECT * FROM [' + Param.asString['Table'] + ']'; try query.Open; ja := TConverter.New.DataSet(query).AsJSONArray; results := ja.ToJSON; finally Result.asString := results; query.Close; end; end; end; Is this everything that I need to do? Am I missing a step? Title: Re: How to do JavaScript calls to the RTC server using XML-RPC Post by: D.Tkalcec (RTC) on September 16, 2016, 08:07:35 PM Since you are using XML-RPC, you have to enable XML-RPC format on the TRtcServerModule component by opening the DataFormats list in the object inspector and setting fmt_XMLRPC to True, because only fmt_RTC is enabled by default. Provided your TRtcServerModule is also attached to the Server (using its Server or Link property), your remote functions should become accessible using XML-RPC from any HTTP-based Client and you should be able to access all the parameters in the OnExecute event of your TRtcFunction component.
Here is an old FAQ topic about the translation between XML-RPC and RTC objects (http://www.realthinclient.com/sdkarchive/index72ff72ff.html). Best Regards, Danijel Tkalcec Title: Re: How to do JavaScript calls to the RTC server using XML-RPC Post by: brian71us on September 18, 2016, 01:58:46 AM OK, so everything works if I launch the web page from Chrome and serve up the pages from the built in web server. ;D
If I double click the index.html file (or run it from within Brackets) then the web page opens but the XML-RPC call fails with the message "XMLHttpRequest cannot load http://localhost:8095/mytest. Response for preflight has invalid HTTP status code 404" ??? I have added the CORS header when the request is accepted by the web server component. Any suggestions for how to troubleshoot this issue? Title: Re: How to do JavaScript calls to the RTC server using XML-RPC Post by: D.Tkalcec (RTC) on September 19, 2016, 09:19:24 PM 1. Are you using absolute URLs inside your HTML and JavaScript files to ensure that your Server will be receiving the request even if the HTML is served locally?
2. To check if your Server is receiving anything (regardless of context or source), you can add a new TRtcDataProvider component to your Project, set its CheckOrder property to -1 (it has to be lower than any other components CheckOrder value), assign your TRtcHttpServer component to its Server property and implement its OnCheckRequest event, from where you can log the following info: -> TRtcDataServer(Sender).Request.HeaderText; -> TRtcDataServer(Sender).Request.URL; Or run your Server from Delphi in DEBUG mode and set a breakpoint in any OnCheckRequest event, then open the index.html file and see if anything happens on the Server side. Best Regards, Danijel Tkalcec Title: Re: How to do JavaScript calls to the RTC server using XML-RPC Post by: brian71us on September 21, 2016, 07:32:58 PM This is the XML-RPC call in JavaScript: function getUsers() { $.xmlrpc({ url: 'http://localhost:8095/mytest', methodName: 'GetData', params: [{Table: 'BrechbuhlerUser'}], success: function(response, status, jqXHR) { document.getElementById("theResponse").innerHTML = response; }, error: function(jqXHR, status, error) { document.getElementById("theResponse").innerHTML = error; } }); The URL is absolute - http://localhost:8095/mytest Here's what I get when I request the web page by opening the browser and entering http://localhost:8095/ localhost:8095/ Host: localhost:8095 Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 COOKIE: ScaleDealer_DetailView_Main_Tabs=1; SupportTicket_DetailView_Main_SizeableEditors_Item2=0; Branch_DetailView_Main_Tabs=0 localhost:8095/jquery-1.9.1.min.js Host: localhost:8095 Connection: keep-alive Cache-Control: max-age=0 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 Accept: */* Referer: http://localhost:8095/ Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 COOKIE: ScaleDealer_DetailView_Main_Tabs=1; SupportTicket_DetailView_Main_SizeableEditors_Item2=0; Branch_DetailView_Main_Tabs=0 localhost:8095/jquery.xmlrpc.js Host: localhost:8095 Connection: keep-alive Cache-Control: max-age=0 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 Accept: */* Referer: http://localhost:8095/ Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 COOKIE: ScaleDealer_DetailView_Main_Tabs=1; SupportTicket_DetailView_Main_SizeableEditors_Item2=0; Branch_DetailView_Main_Tabs=0 localhost:8095/favicon.ico Host: localhost:8095 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 Accept: */* Referer: http://localhost:8095/ Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 COOKIE: ScaleDealer_DetailView_Main_Tabs=1; SupportTicket_DetailView_Main_SizeableEditors_Item2=0; Branch_DetailView_Main_Tabs=0 localhost:8095/favicon.ico Host: localhost:8095 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 Accept: */* Referer: http://localhost:8095/ Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 COOKIE: ScaleDealer_DetailView_Main_Tabs=1; SupportTicket_DetailView_Main_SizeableEditors_Item2=0; Branch_DetailView_Main_Tabs=0 localhost:8095/favicon.ico Host: localhost:8095 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 Accept: */* Referer: http://localhost:8095/ Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 COOKIE: ScaleDealer_DetailView_Main_Tabs=1; SupportTicket_DetailView_Main_SizeableEditors_Item2=0; Branch_DetailView_Main_Tabs=0 localhost:8095/favicon.ico Host: localhost:8095 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 Accept: */* Referer: http://localhost:8095/ Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 COOKIE: ScaleDealer_DetailView_Main_Tabs=1; SupportTicket_DetailView_Main_SizeableEditors_Item2=0; Branch_DetailView_Main_Tabs=0 This is what I get when I make the XML-RPC call when I enter "http://localhost:8095" in Chrome, which works properly... localhost:8095/mytest Host: localhost:8095 Connection: keep-alive Content-Length: 194 Accept: application/xml, text/xml, */*; q=0.01 Origin: http://localhost:8095 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 Content-Type: text/xml Referer: http://localhost:8095/ Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.8 COOKIE: ScaleDealer_DetailView_Main_Tabs=1; SupportTicket_DetailView_Main_SizeableEditors_Item2=0; Branch_DetailView_Main_Tabs=0 If I double click "index.html" to open the web page instead of fetching it from the RTC web server... localhost:8095/mytest Host: localhost:8095 Connection: keep-alive Access-Control-Request-Method: POST Origin: null User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 Access-Control-Request-Headers: content-type Accept: */* Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 There is a difference, though why I don't know as I'm calling the same XML-RPC method whether I'm serving up the web page from RTC web server or double-clicking the index.html file. Title: Re: How to do JavaScript calls to the RTC server using XML-RPC Post by: D.Tkalcec (RTC) on September 23, 2016, 11:57:51 AM When you get the HTML file from the Server, the JS library you are using will be sending a 'POST' request to the Server with the correct XML-RPC content in the request content body (as expected) and the OnExecute event will be triggered on the TRtcFunction component responsible for handling that specific XML-RPC request.
But ... if you open the same HTML file directly by double-clicking it in the File Explorer, instead of directly sending the "POST" request with the XML-RPC content, the Web Browser is sending an "OPTIONS" request to the Server, with no content body. Since the TRtcServerModule component does NOT handle "OPTIONS" requests, you will have to add a "TRtcDataProvider" with a "CheckOrder" lower than that used by your TRtcServerModule component (for example: CheckOrder := -1) and implement its "OnCheckRequest" event to something like this: procedure TForm1.OriginDataProviderCheckRequest(Sender: TRtcConnection); var Srv:TRtcDataServer absolute Sender; begin if (Srv.Request.Method='OPTIONS') and (Srv.Request.FileName='/mytest') then begin Srv.Accept; Srv.Response['Access-Control-Allow-Headers']:='Origin, X-Requested-With, Content-Type, Accept'; Srv.Response['Access-Control-Allow-Origin']:='*'; Srv.Write; end; end; The above event will be ONLY handling "OPTIONS" requests for "/mytest" reuests. You might have to add more HTTP Response headers if you wat to handle other kinds of OPTIONS requests, but the above should do the trick for your specific problem with XML-RPC requests not being executed when the HTML file was loaded directly by double-clicking it in the File Explorer. If you want to make it general, you could also write a single Data Provider to handle all "OPTIONS" requests by removing the ...FileName='/mytest') check. Best Regards, Danijel Tkalcec |