SAP / openui5

OpenUI5 lets you build enterprise-ready web applications, responsive to all devices, running on almost any browser of your choice.
http://openui5.org
Apache License 2.0
2.95k stars 1.24k forks source link

UI5 fails to load CORS compliant external APIs #2402

Closed krisho007 closed 5 years ago

krisho007 commented 5 years ago

OpenUI5 version: 1.56.7

Browser/version (+device/version): Chrome

Any other tested browsers/devices(OK/FAIL): IE works fine.

Steps to reproduce the problem:

  1. Use any external CORS compliant (which returns Access-Control-Allow-Origin: * ) API from your UI5 application.
  2. I am using https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer?f=json, which returns Access-Control-Allow-Origin: *.
  3. But UI5 sends additional http header x-xhr-logon with the API call which is not expected by the external API.

What is the expected result? Do not send header x-xhr-logon header along with the request to external API.

What happens instead? Sends unwanted http headers.

stephania87 commented 5 years ago

Are you running from Fiori Launchpad, Fiori Client? Or else?

Check if you can add the service to the destinations, or better see the discussion here https://answers.sap.com/questions/99498/cors-issue-with-chrome.html

krisho007 commented 5 years ago

I am running from Fiori Launchpad, but On-Premise. So no chance for the destination.

Check the below code from abap.js. image

As you see in the above image, URL is pointing to an external API, still, UI5 adds "X-XHR-Logon".

mschleeweiss commented 5 years ago

What I did in this case was the following workaround:

_overrideRequestPrototype: function () {
    if (!XMLHttpRequest._SAP_ENHANCED) {
        return;
    }
    this.__send = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function (oBody) {
        let oChannel = {};
        this._checkEventSubscriptions();
        try {
            oChannel = this._channel;
            this._saveParams(oBody);
            this._send(oBody);
            if (oChannel) {
                oChannel.sent();
            }
        } catch (oError) {
            if (oChannel) {
                oChannel["catch"](oError);
            } else {
                throw oError;
            }
        }
    };
},

_restoreRequestPrototype: function () {
    if (!XMLHttpRequest._SAP_ENHANCED) {
        return;
    }
    XMLHttpRequest.prototype.send = this.__send;
}

Call the first method immediately before sending the request, the second one in the success/error callback

krisho007 commented 5 years ago

Thanks, @mschleeweiss for the workaround. But I do not have control on (when) this external API call. Nevertheless, this is a bug. There is no point sending x-xhr-logon http header to a public, non-SAP API.

krisho007 commented 5 years ago

Little more details on the impact of this bug.

So what happens when UI5 sends an unnecessary x-xhr-logon http header to a public, CORS compliant API?

  1. Because of this new header, the call to the API is no longer a simple call. Because of this Chrome sends a Preflight request to the API endpoint. Along with this Preflight call, Chrome also checks with the API if sending x-xhr-logon header is expected.
  2. API responds with Access-Control-Allow-Origin: * header, to the preflight request indicating it is ok to send a CORS request. But in the response header, it does not list x-xhr-logon as the allowed http header. (As the API does not recognize and require it).
  3. Chrome stops the actual call to the external API. The exact error message is field X-XHR-Logon is not allowed by Access-Control-Allow-Headers in preflight response.

In summary, because of this bug UI5 is forcing the use of a proxy product even when it is not required. Thus increasing the TCO (total cost of ownership) unnecessarily.

matz3 commented 5 years ago

The header is not set or handled by OpenUI5, but within the Fiori Launchpad / SAPUI5. Therefore I'm closing this issue here. Please use the corresponding SAP support channels instead.

gregorwolf commented 5 years ago

Hi @krisho007, you have the chance for a "destination" also on premise. Get your SAP basis admins to install a Web Dispatcher in front of the Lauchpad and reverse proxy the external API. CU Gregor

krisho007 commented 5 years ago

Hi @gregorwolf , Yeah I am aware of Web Dispatcher. But I do not want to do it as the third party API is CORS compliant (returns Access-Control-Allow-Origin: * ). SAPUI5 should fix this.

stephania87 commented 5 years ago

The code you mention is not handled by this project. Run an incident through the support system and my colleagues will route you to the correct team/project in order to get details about authentication in FLP

gregorwolf commented 5 years ago

But I do not have control on (when) this external API call.

Can you elaborate on this? Is this API used somewhere in the SAP standard?

rkmishra2703 commented 5 years ago

Hi Krisho007,

what is the solution to this issue please suggest.I am also getting same error. BR, Ram

krisho007 commented 5 years ago

@gregorwolf : I use an external JS library, which makes further calls to external CORS compliant library. These 'further calls' are not directly initiated by my code, thus I cannot rout them through the web dispatcher.

krisho007 commented 5 years ago

@rkmishra2703 : SAP has replied that issue is with Fiori Launchpad. (as @matz3 rightly pointed out). I will update here when I get a solution.

krisho007 commented 5 years ago

SAP has provided a solution. This issue is resolved with SAPUI5 version 1.60.9. Thought it will be useful to anyone coming here by searching.

fabiopagoti commented 5 years ago

Hi @krisho007 do you happen to have the SAP Note number for that issue?

krisho007 commented 5 years ago

@fabiopagoti There is no Note for it. SAP replied that the bug is resolved with 1.60.9 and I have verified it.