SAP / cloud-sdk-js

Use the SAP Cloud SDK for JavaScript / TypeScript to reduce development effort when building applications on SAP Business Technology Platform that communicate with SAP solutions and services such as SAP S/4HANA Cloud, SAP SuccessFactors, and many others.
Apache License 2.0
167 stars 57 forks source link

executeHttpRequest not working stable #2806

Closed Yuhong-Huang closed 2 years ago

Yuhong-Huang commented 2 years ago

I am trying to use executeHttpRequest to call a destination (Successfatctors’s OData api, OAuth2SAMLBearerAssertion) . The trust between BTP and Successfactors is also maintained.

The app is deployed to BTP trial account. However, it is not always working, sometimes I can get the data, sometimes not, with the below error: image

Below is the code: image

The destination: image

fwilhe commented 2 years ago

Hi @Yuhong-Huang

However, it is not always working, sometimes I can get the data, sometimes not, with the below error

This sounds like something that is hard to debug. Just to clarify what you mean: You re-run the HTTP requests with the same parameters and credentials, and sometimes they work, and sometimes they don't?

Do the requests work when you use another http client, such as postman or cURL?

Yuhong-Huang commented 2 years ago

Hi @fwilhe , What I meant is, in the browser, if I refresh the page, sometimes I got the error, sometimes I got the correct data from Successfactors.

I have used another api (sap-cf-axios), which is working fine.

FrankEssenberger commented 2 years ago

Hi @Yuhong-Huang

thanks for opening an issue. This looks like there is some hickup when the destination service tires to obtain a token using the token endpoint you provided. To ensure this you can split the execution in two steps. First you get the destination and then make the request.

  const destination = await getDestination({
    destinationName: 'myDest',
    jwt: 'myJwt',
    //useCache: true // cache could help as mitigation
  }); 
  if (!destination) {
    throw new Error('Destination could not be found.');
  }
  if (!destination.authTokens || destination.authTokens.length === 0) {
    throw new Error('Destination service did not give any auth token');
  }
  if (destination.authTokens[0].error) {
    throw new Error(
      `Destination service got an error in retrieving auth token: ${destination.authTokens[0].error}`
    );
  }

  executeHttpRequest(destination, { method: 'get' });

The SDK actually just delegates the token flow to the destination service. I am pretty sure the other lib does the same. So they also depend on the potential flaky result of the service. I can only guess that they have a caching switched on per default, which helps to avoid multiple calls. The SDK also has a tenant/user aware cache, so once you have a successful run we store the destination result for the token lifetime in the cache. You can try to switch on caching to mitigate the issue.

Note that we are also working on version 3.0 and plan to introduce some middleware approach which will be wrapped around all calls. One provided middleware will be a retry one which you could add in such cases to get a bit more resilience. Stay tuned on version 3.0 :-)

I hope this improves the situation and I wish you a good weekend.

Best Frank

jjtang1985 commented 2 years ago

Hi @Yuhong-Huang ,

You can try to switch on caching to mitigate the issue.

Please check the doc here.

Here is the code example:

executeHttpRequest(
{
  destinationName: destinationName,
  jwt: retrieveJwt (req),
  useCache: true
},
...
Yuhong-Huang commented 2 years ago

Hi @FrankEssenberger , @jjtang1985 , yes, that helped.

Thanks for your help!

FrankEssenberger commented 2 years ago

There is still the question why the token endpoint is not stable OR if the destination service is creating the flakynes. However, this is not a SDK issue so is it ok to close the issue?