Skip to main content

Perform HTTP Requests

This guide explains how to execute arbitrary HTTP requests using the SAP Cloud SDK for JavaScript. The HTTP client provided by the SAP Cloud SDK provides some convenience features which are explained in detail in this guide.

tip

If you want to use an OData API, please refer to the Executing a request using a generated OData client page. In case you want to use an OpenAPI client, please refer to the Execute a Request Using a Generated OpenAPI Client page.

When to Use What?

The SAP Cloud SDK for JavaScript can generate clients for OData and OpenAPI. Use generated clients for OData or OpenAPI services, if possible.

Generated clients provide convenience features such as:

  • Type-safe response objects
  • Convenient handling of filter, select and expand conditions
  • Built-in ETag versions handling
note

Be sure to check if the clients for OData or OpenAPI support your use case. For example, the OData client does not support the upsert operation.

The generic HTTP client is based on the open source axios HTTP client, but provides convenience features which are specific to working on SAP Business Technology Platform, such as:

executeHttpRequest

The most basic way to use the SAP Cloud SDK HTTP client is the function executeHttpRequest.

executeHttpRequest(destination, requestConfig, httpRequestOptions): Promise<HttpResponse>;

It takes the following parameters:

tip

This guide provides code snippets. Fully executable example code can be found in the SAP-samples/cloud-sdk-js repository on GitHub.

In the most simple form, the function can be invoked like this:

const response = await executeHttpRequest({
url: 'https://example.com'
});

In the example above, since the requestConfig value is not provided, the SDK treats it as a GET request. To perform a different operation, set the method property in requestConfig to the required value, e.g., POST.

caution

Note that the destination and requestConfig parameters have an overlap in the keys they accept. For example, both have a url and an authorization property. For keys that exist for both objects, the requestConfig takes precedence.

The executeHttpRequest() function returns a promise of type HttpResponse.

Parameter Encoding

URL encoding allows using characters as part of the URL which normally would cause issues such as spaces. For example, the space character is replaced with %20.

The HTTP client automatically takes care of encoding parameters except for custom parameters. Custom parameters can be useful when you need control exactly how values are transmitted to the backend system.

Customized Parameter Encoding

If you need to customize parameter encoding, you can provide your own function to do the transformation. This feature is meant for cases where backends have special requirements for the encoding that don't work with the default URL-encoding done by the HTTP client. You should usually avoid this as it adds additional complexity to the application code.

The example below shows how to do a string replace:

const myCustomParameterEncodingFunction: ParameterEncoder = function (
params: Record<string, any>
): Record<string, any> {
const encodedParams: Record<string, any> = {};

for (const key in params) {
// Customize your required encoding logic here
encodedParams[key] = params[key].toString().replace('x', 'y');
}

return encodedParams;
};

const response = await executeHttpRequest(
{
url: 'https://example.com'
},
{
method: 'get',
params: {
param1: 'a/bx',
param2: 'x1'
},
// Pass your custom encoding function
parameterEncoder: myCustomParameterEncodingFunction
}
);

Setting Middlewares

You can specify middlewares for a request via the middleware property of the request config

const response = await executeHttpRequest(httpsDestination, {
middleware: [myMiddleware],
method: 'get'
});

Middleware is a general concept used to add arbitrary enhancements to the request. A typical use case is to also add resilience to requests.

The HTTP request in this example will contain the parameter values a/by and y1 because the parameter encoder function replaced the x with a y.

CSRF Token Fetching

Cross-Site Request Forgery (CSRF) is a common type of attack on web applications. The HTTP client provided by SAP Cloud SDK allows to automatically retrieve a CSRF token for HTTP APIs which support this.

info

Fetching CSRF token is automatically enabled for all requests that typically might change data, such as PUT, POST, DELETE, or PATCH requests. It is not available for GET requests.

Fetching the CSRF token can be enabled or disabled via the httpRequestOptions.fetchCsrfToken parameter of executeHttpRequest() function. See its API documentation for details.

For example, to avoid CSRF token fetching when doing a PUT, POST, DELETE, or PATCH request, disable it like in this example:

const response = await executeHttpRequest(
{
url: `https://example.com`
},
{
method: 'post'
},
{
fetchCsrfToken: false
}
);

If you need to adjust the way CSRF token are fetched, you can do so by using the middlewares.

  • Disable the token fetching to deactivate the default code
  • Add a middleware to include your custom token fetching.

The SAP Cloud SDK offers a csrf middleware which allows to configure some basic options:

  • method The HTTP method used to get a token
  • URL The URL which is called to retrieve a token
  • middleware Middlewares used for the token retrieval request
const response = await executeHttpRequest(
{
url: `https://example.com`
},
{
method: 'post',
middleware: [csrf({ url: 'https://example.com/csrf/token/url' })]
},
{
fetchCsrfToken: false
}
);

executeHttpRequestWithOrigin()

The executeHttpRequestWithOrigin() function is a variation of executeHttpRequest() which allows more fine-grained control over configuration precedence.

caution

The term "origin" as it is used in the context of this guide does not refer to a URL as in the "same-origin policy". Instead it refers to the origin or source of HTTP client configuration.

This function may be helpful in situations where you want to define the priority of headers and parameters, for example if:

  • You want to enforce a hard-coded API key or JWT and ignore the ones from the destination
  • You want a default query parameter, which can be overwritten by the destination properties

Headers and query parameters with the same name are prioritized in the following order:

  1. custom
  2. Destination related headers/query parameters
  3. requestConfig

In this example the HTTP request will contain the URL parameter myParam with the value custom-param and the HTTP header apiKey with the value custom-header:

const response = await executeHttpRequestWithOrigin(
{
url: 'https://example.com'
},
{
method: 'get',
headers: {
custom: { apiKey: 'custom-header' },
requestConfig: { apiKey: 'default-header' }
},
params: {
custom: { myParam: 'custom-param' },
requestConfig: { myParam: 'default-param' }
}
}
);