Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
vobu
Active Contributor

Or as the subtitle could also read: Overcoming "Access-Control-Allow-Origin"- errors


Setup in this example is:

  • development machine with local (web) server running a WebApp from http://localhost:12345
  • Gateway server accessible under a different domain than the local development machine, such as http://example.gateway.com:8000
  • need to consume services onGateway server, originating from local machine => Cross-Domain Request!

There's a lot written out there why Cross-Domain read requests (not write requests!) aren't a good idea. They generally open up data transfer possibilities between domains. Which is something you don't necessarily want - for production environments, that is. What you should also never cater to - use a proxy-based approach to consolidate data read access under one domain, either software-based or with middleware.

But what about development?

There are legitimate reasons to read data across domains in development scenarios. Not the least is if you want to work with features offered by SAP Gateway - accessing SAP Backend logic that is exposed via OData Services. Which means issuing cross-domain REST requests from your development machine to a Gateway instance. If you don't have Gateway running on your development machine. Which is unlikely. So here we are...

The good and the caveat - SOP

First of all, in the Web's overall architecture, there's SOP or Same-Origin-Policy:

[It] restricts how a document or script
loaded from one origin can interact
with a resource from another origin.

Origin here means the combination of protocol (e.g. http), FQDN (e.g. my.domain.com) and port (e.g. 80). So https://www.js-soft.com:4711 is considered an origin - so would http://localhost:12345.

And "can interact" in the quote above should be read as "scripts running from one origin are generally forbidden to interact with scripts from another origin". (Does that mean you can't include content from different sites? No! Read on...)

The client side

Stir in some OData- and Gateway-spice and it adds up to the following:

The user agent (e.g. Firefox) is rendering the WebApp from origin1, let's say running on your development machine at http://localhost:12345/.

Now, if the WebApp is trying to retrieve JSON or XML via OData from http://example.gateway.com:8000/sap/opu/odata/sap/ZService/Entity(1), the user agent will send an "XMLHttpRequest cannot load"-error and block the request:


XMLHttpRequest cannot load http://example.gateway.com:8000/sap/opu/odata/sap/ZService/Entity(1).
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:12345/' is therefore not allowed access.

This is due to SOP being implemented in all major user agents: the scripts in the WebApp are forbidden to consume resources from origins other than (in our example) http://localhost:12345/. Retrieving OData from the same origin such as http://localhost:12345/the/odata/endpoint would be allowed, retrieving http://example.gateway.com:8000/sap/opu/odata/sap/ZService/Entity(1) is not.

Note that we're talking run-time and client-side here. SOP doesn't apply to including JavaScript-files per se, it applies to the run-time interpretation of the script itself. So if you include JS-files via the <script>-tag, (e.g. <script src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js">), the JS-file will be downloaded from the remote address first. Then it will run from your origin, being interpreted by a user agent - that's the moment that SOP restrictions will apply, not earlier.

Disclaimer: SOP is generally a Good Thing(tm). In prevents scripts from origin A to read data from origin B and transfer it back to A.

Which is exactly what you'd like to do in development :smile:

Resolution: start-flag for Chrome

Google Chrome offers a way to turn off SOP.

If you start the binary with the switch --disable-web-security, SOP gets disabled, allowing client-side cross-domain requests.

E.g. on OS X:

    /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --disable-web-security

On Windows:

    "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security

We're half-way there - cross-domain requests are allowed on the client-side now.

The server side

Even though the client now allows requests across domain boundaries, the server still needs to grant access to those requests.

A standard way of doing this is utilizing CORS or Cross-Origin Resource Sharing on the server-side.

In essence, this means sending a an "Access-Control-Allow-Origin" header back to the client, authorizing the client's domain - or granting general access with '*'.

Note: '*'-access is exactly what all the Northwind OData Test Services do. And what explains their popularity in example code.

Resolution: CORS with Gateway

Per default, Gateway send similar headers such as these:

Content-Encoding:"gzip"

Content-Length:"43233"

Content-Type:"text/html; charset=utf-8"

Server:"SAP NetWeaver Application Server / ABAP 731"

dataserviceversion:"2.0"

sap-metadata-last-modified:"Tue, 08 Jul 2014 08:55:38 GMT"

In order to send an additional, custom header from a Gateway-service, use set_header from Interface /iwbep/if_mgw_conv_srv_runtime.

It takes a structure as argument, consisting of a key-value pair.


data:
        ls            type ihttpnvp.
ls-name = 'Access-Control-Allow-Origin'.
ls-value = '*'.
/iwbep/if_mgw_conv_srv_runtime~set_header( is_header = ls ).

This will result in the desired CORS "Access-Control-Allow-Origin" header, granting all clients ("*") read access:

access-control-allow-origin:"*"

Conclusion

Bringing all the above together means that by

  • using a switch to Google Chrome, you can get around SOP on the client side
  • sending the 'Access-Control-Allow-Origin' header from the Gateway-service allows CORS on the server side

And there you are, hopefully hacking away happily on your local machine, calling Gateway OData back and forth :smile:

For development purposes only - don't unhinge these web security fundamentals just to make a quick transition into production scenarios, please!

tl;dr: Chrome --disable-web-security disables SOP, Gateway /iwbep/if_mgw_conv_srv_runtime~set_header allows CORS => developer happy

23 Comments
Labels in this area