datajs unsupported on Webkit

Jan 10, 2012 at 2:57 PM

Hi Team,

I was trying to use datajs library to create a iOS prototype app connecting to SAP NetWeaver Gateway.

Unfortunately, I was not able to use the library because it does not work for Firefox or Chrome, it is only supported for IE.

I would like to know if you have planned to make the datajs library work on Webkit based browsers.

Developers will appreciate it if you will do so.

Regards,

Acos Rodriguez

Jan 10, 2012 at 6:49 PM

Hi Acos,

   Hope you are doing great.  Thank you for trying out the library and yes the library has always been supported in Firefox (3.6 and later), Chrome (9 and later), and Safari (5 and later) besides IE (8 and 9 out of the box.. in IE 6 and 7 you will have to include the json2 script in your web app). 

   Could you please elaborate on what is not working for you and on which browsers (name and version) you are having issues?

Regards,

Alex Trigo.     

Jan 11, 2012 at 7:26 AM

Hi Alex,

thanks for replying so fast.

I am not able to get a success call to an OData service from SAP Demo system. As you can see in the below code, am just trying to call the service and, dependingo on the result, I popup a window with a success or error message.

If you try this code, you will see that on IE, it prompt success, as soon as its executed on Firefox or Chrome, a HTTP error appears. Thats why i mean it does not work, maybe am wrong, I hope you can help me.

 

Thanks in advance for your help & time

 

<!DOCTYPE html>
<html>
<head>
<title>hello world</title>
  <script src="http://domain.netau.net/datajs-1.0.2.js" type="text/javascript"></script>
</head>
<body onload="getData()">
    <div id="results"><h3>Call gateway service</h3></div>
<script type="text/javascript">
    function getData() {
      var serviceUri = "http://gw.esworkplace.sap.com/sap/opu/sdata/iwfnd/catalogservice/CatalogCollection%28ID%3d%27HW1%27%29/Services";
      OData.read(
        { requestUri: serviceUri, user: "GWDEMO", password: "DEMO4GW" },
        function (data){
          alert("success");
        },
        function (err) {
          //Error Callback
          alert("Error occurred " + err.message);
          print_r(err);
        }) ;
    }
  
    function print_r(theObj){
      if(theObj.constructor == Array ||
         theObj.constructor == Object){
        document.write("<ul>")
        for(var p in theObj){
          if(theObj[p].constructor == Array||
            theObj[p].constructor == Object){
            document.write("<li>["+p+"] => "+typeof(theObj)+"</li>");
            document.write("<ul>")
            print_r(theObj[p]);
            document.write("</ul>")
          } else {
            document.write("<li>["+p+"] => "+theObj[p]+"</li>");
          }
        }
        document.write("</ul>")
      }
    }
</script>
</body>
</html>

Jan 12, 2012 at 12:39 AM
Edited Jan 12, 2012 at 12:40 AM

Hi Acos,

   The issue is not that the library is not working in Chrome or FireFox.  The issue you are hitting is because of the same domain policy and how it is implemented in the browser.  The request you are making to the endpoint is a cross domain request and each browser reacts differently to it.. for example, IE usually pops up a little message box warning the user that the page is trying to request data that it is not under its control.  If you accept, then IE will go ahead and send the request... that's why you see your example work on IE .. sort of... because if you deny the rquest then you will hit an access denied error message coming from the browser itself.  Chrome and Firefox ( and probably other webkit based browsers ) simply deny the request causing the library to trigger the error handler...

    I would say to you that you should enable the JSONP callbacks for cross domain GET requests in the library...  But this particular request will not work with JSONP because it has to be authenticated...   There are two options for getting this properly working:

   1.  Provide a simple endpoint in your domain that relays the request to the desired endpoint. 

   2.  Use a custom http client object that knows how to use the browser's specific cross domain request support ( CORS, XDR... )

  I would go with solution number one because you don't need explicit support from the endpoint (in this case the SAP endpoint) for a particular technology (like CORS) and you can fully control the access and what your relaying service does.

More information that will be helpful:

http://datajs.codeplex.com/wikipage?title=OData%20Networking&referringTitle=Documentation

http://datajs.codeplex.com/wikipage?title=Cross%20Domain%20Requests&referringTitle=Documentation

http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/

http://www.html5rocks.com/en/tutorials/file/xhr2/#toc-cors

Regards,

Alex Trigo.

 

 

Jan 12, 2012 at 12:28 PM
Edited Jan 12, 2012 at 3:07 PM

Hi Alex,

thanks for your detailed feedback.

I was reading the links you have attached and tried to implement the service call like referred.

Unfortunately, am not able to call the service successfully. Have you any idea what does not work properly in the below code?


Thanks for your help

 

<!DOCTYPE html>
<html>
<head>
<title>prototype</title> 
</head>

<body onload="getData()">

  <div id="results"><h3>Call gateway service</h3></div>

  <script type="text/javascript">
    var url = 'http://GWDEMO:DEMO4GW@gw.esworkplace.sap.com/sap/opu/sdata/iwfnd/catalogservice/CatalogCollection%28ID%3d%27HW1%27%29/Services/';

    function getData() {
      var xhr = createCORSRequest('GET', url);
      if (!xhr) {
        alert('CORS not supported');
      }

      xhr.withCredentials = "true";
      xhr.setRequestHeader('Content-Type', 'application/atom+xml;type=feed');
      xhr.setRequestHeader('X-PINGOTHER', 'pingpong');  
      xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
      xhr.setRequestHeader('Access-Control-Allow-Credentials', 'true');
      xhr.setRequestHeader('Access-Control-Allow-Methods', '*'); //xhr.setRequestHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,HEAD,OPTIONS');
      xhr.setRequestHeader('Access-Control-Allow-Headers', '*');//xhr.setRequestHeader('Access-Control-Allow-Headers', 'Authorization, X-Authorization');
      xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');      

      xhr.onload = function() {
        alert('Response from CORS');
      };

      xhr.onerror = function() {
        alert('Woops, there was an error making the request.');
      };

      xhr.send();
    }

    function createCORSRequest(method, url) {
      var xhr = new XMLHttpRequest();
      if ("withCredentials" in xhr) {
        xhr.open(method, url, true);
      } else if (typeof XDomainRequest != "undefined") {
        xhr = new XDomainRequest();
        xhr.open(method, url);
      } else {
        xhr = null;
      }
      return xhr;
    }
</script>
</body>
</html>

Jan 16, 2012 at 6:33 PM

Hi Acos,

   I see that you are adding the access control headers to your request to enable a CORS like request.  The problem with CORS is that the server has to support CORS and do the appropriate thing with the access-control-* headers.  I think you will have to go with a relaying service in this case and talk to the SAP endpoint through the service that is in the same domain as your web page.  Also, I'd be careful of not including the user name and password information in the URI itself, because it is exposed.

Regards,

Alex Trigo.

Jan 17, 2012 at 1:03 PM
atrigo wrote:

Hi Acos,

   I see that you are adding the access control headers to your request to enable a CORS like request.  The problem with CORS is that the server has to support CORS and do the appropriate thing with the access-control-* headers.  I think you will have to go with a relaying service in this case and talk to the SAP endpoint through the service that is in the same domain as your web page.  Also, I'd be careful of not including the user name and password information in the URI itself, because it is exposed.

Regards,

Alex Trigo.

Hi Alex,

there something I do not understand and maybe am not explaining it well. If I use datajs library on IE it works, but as soon as I execute the code on Chrome/Firefox,  I get HTTP status 0.

My doubt is, these means that SAP endpoint allows CORS, not? Because if not, it would not work on any browser or am I wrong? On every reply, am getting more confused than before ... :-(

Regards,

Acos Rodriguez

Jan 23, 2012 at 7:43 PM
Edited Jan 24, 2012 at 12:10 AM

Hi ACoz,

   Sorry If didn't explain my self clearly.  First of all,  I don't think that the SAP endpoint you are hitting supports CORS, (remember, CORS has to be supported by the server as well as the client to work properly).  Tracing a request to the endpoing gives me:

HTTP/1.1 204 No Content
Proxy-Connection: Keep-Alive
Connection: Keep-Alive
content-length: 0
Via: 1.1 TK5-PRXY-07
Date: Mon, 23 Jan 2012 20:28:48 GMT
Content-Type: text/plain
Server: SAP NetWeaver Application Server / ABAP 702
allow: GET,POST,OPTIONS

Notice that there are no "Access-Control-*" headers in the response.. this hints me that CORS is not supported.  I think you should contact the SAP endpoint support and ask them is they do have CORS enabled.  Keep in mind that CORS is fairly new and it is just starting to gain traction.

Now, the fact that datajs "works" in IE and not in Chrome of Firefox is not an issue of the libary, but rather an implementation detail of each browser.  The library uses XmlHttpRequest to communicate with the target endpoint.  If the endpoint is in a different domain, then XmlHttpRequest will behave differently depending on the browser.  This is because of how the developers of the browser decided to implement XHR and the same origin policy:   IE for instance allows doing cross domain requests if and only if the user approves by clicking yes to a message box that the browser pops up.  This pop up comes from the browser itself and not datajs.  If the user approves, then IE allows the request and it all seems to work.  Chrome and Firefox on the other hand chose to completly block any cross domain request using XHR unless it is a CORS request.  IE has some level of CORS support using the Cross Domain Request (XDR) object... but its capabilities are rather limited for the needs of the libary. 

My recommendation, to work around the XHR restrictions is to use a dummy OData endpoint in your webserver that just relays the request to your desired endpoint in some other domain and passes the response through to your web app.

Regards,

Alex Trigo

Jul 21, 2014 at 8:30 PM
Hi everyone
I'm trying to to connect through Ajax's Jquery method to comsume gateway as a service based Odata and with this Library returns me the next error:

"Uncaught SyntaxError: Unexpected token :"
but it returns me this JSON

{"d":{"__metadata":{"id":"https://gwaas-p1940518915trial.hanatrial.ondemand.com/odata/IWBEP/GWDEMO;v=1/CountryCollection('CO')","uri":"https://gwaas-p1940518915trial.hanatrial.ondemand.com/odata/IWBEP/GWDEMO;v=1/CountryCollection('CO')","type":"GWDEMO.Country"},"CountryCode":"CO","CountryText":"Colombia"}}

it suppose to bn ok and the request header status it's 200... I don't understand this error... and when I use datajs I get this error:

GET https://gwaas-p1940518915trial.hanatrial.ondemand.com/odata/IWBEP/GWDEMO;v=…yCollection('CO')?$format=json&$callback=parent.handleJSONP_0&$format=json 400 (Bad Request)

can any one help me?