This blog is inspired by an excellent blog "
Just a single click to test SAP OData Service which needs CSRF token validation" authored by
jerry.wang
I liked the approach Jerry shared. Each time you need to create, update or delete some data via (SAP) oData API you need to use CSRF token (e.g.
it's applicable to C4C oData API). It used to be quite a pain in Postman. Jerry suggested using an environment variable in Postman to share CSRF token between 2 (or more) requests. Where the first request is getting CSRF token for you and stores it in an environment variable while subsequent requests consume this CSRF token via the variable. Sounds logical.
However, in my case, the need to run a collection (of requests) each time when I need to do a quick and simple POST or PUT or PATCH to C4C oData API was not something I would be comfortable with.
I would prefer "real one-click". Just hit the Send button in Postman and here we go. Something similar to OData Explorer tool available in C4C system where you don't need to care about CSRF token at all. Frankly, it's a great tool, but it has some performance issues when you launching it or navigating from one "heavy" entity type to another. And the error handling is another question which, in my opinion, oData Explorer needs to address to show the complete error message produced by the backend of C4C.
Postman beast is still a preference of mine.
So I wanted to improve Jerry's approach to make it a "real one-click".
A bit of research and play with Postman on one of business trips' flights got me to the idea. And the idea was to use Pre-requests Script in Postman. They are powerful. As powerful as Test scripts. Or even more.
Here is the pre-request script I've put together. Console logs are there just for test purposes. Feel free to remove them if you're clear on what the script is doing and when. You can see those logs in Postman Console if you open it before doing the call to your oData API. Postman Console is available either via menu View -> Show Postman Console or hotkey Alt+Ctrl+C.
console.log('Pre-request Script from Request start');
// We don't need to do anything if it's GET or x-csrf-token header is explicitly presented
if (pm.request.method !== 'GET' && !(pm.request.headers.has('x-csrf-token'))) {
var csrfRequest = pm.request.clone();
csrfRequest.method = 'GET';
if (pm.request.method === 'POST') {
// for POST method usually it is ....<something>Collection in the URL
// so we add $top=1 just to quickly get csrf token;
// for PUT, PATCH or DELETE the same URL would be enough,
// because it points to the actual entity
csrfRequest.url = pm.request.url + '?$top=1';
}
csrfRequest.upsertHeader({
key: 'x-csrf-token',
value: 'fetch'
});
pm.sendRequest(csrfRequest, function(err, res) {
console.log('pm.sendRequest start');
if (err) {
console.log(err);
} else {
var csrfToken = res.headers.get('x-csrf-token');
if (csrfToken) {
console.log('csrfToken fetched:' + csrfToken);
pm.request.headers.upsert({
key: 'x-csrf-token',
value: csrfToken
});
} else {
console.log('No csrf token fetched');
}
}
console.log('pm.sendRequest end');
});
}
console.log('Pre-request Script from Request end');
The logic here is:
- We're getting the original request and checking if we need to obtain CSRF token or not (we don't need CSRF token if we're doing GET or if the token already presented explicitly).
- If we're unlucky enough and we need to obtain CSRF token, we're cloning the original request. I didn't find any other way to get the authentication part from the original request into a new request properly and dynamically.
- Having the cloned request, we're immediately changing its method to GET.
- Then we're enriching the URL of the cloned request for performance reason if we need to.
- And populating x-csrf-token header of the cloned request with the value "fetch" barging for a token.
- As a next step, we're sending this cloned and modified request providing a call back function. This function will be executed once the request is completed.
- In this call back function, we're checking for any errors, then looking for x-csrf-token header returned to us and if it's fetched, we're upserting it (updating if exists, creating if it doesn't) into the original request.
To use this script, simply copy the code provided and paste it into the tab called Pre-request Script in your Postman's request. Then click Send to send your POST/PUT/PATCH/DELETE request to C4C oData API.
You can even go further and put this script either into your Folder or Collection in Postman. And then the script will run for any request you're doing within those folders or collections. You can find out more on the sequence of scripts in
Postman documentation.