The issue
I need to do an authenticated download using javascript and fetch api. However, there is an automatic call to the backend of type document
(which is request to fetch metadata), which does not get the necessary access token from the custom header (XCompanyAccessToken
) to actually create the file to be downloaded.
The code
I am currently using the following code I found online:
function download(fileUrl) {
let fileName;
fetch(fileUrl, , {
method: 'GET',
headers: {
'XCompanyAccesstoken' = '<access-token>',
/* more headers, obsolete here */
},
mode: 'cors',
})
// the whole then blocks here only handle gziped files, but I left it here for completeness
.then(response => {
const contentEncodingHeader = response.headers?.get('Content-Encoding');
if (contentEncodingHeader === 'gzip') {
// kudos: https://stackoverflow.com/questions/40939380/how-to-get-file-name-from-content-disposition
// there is no "build-in" way of parsing this, unfortunately.
const contenDispositionHeader = response.headers?.get('Content-Disposition');
const fileNameSplit = contenDispositionHeader?.split('filename=')?.[1];
// removes double quotes at the beginning and end
fileName = JSON.parse(fileNameSplit ?? '""');
return response.blob();
}
return null;
})
.then(blobby => {
if (blobby) {
const objectUrl = window.URL.createObjectURL(blobby);
anchor.href = objectUrl;
anchor.download = fileName;
anchor.click();
window.URL.revokeObjectURL(objectUrl);
}
})
}
And those headers are correctly set in the call to the backend of type fetch, but missing in the call to the backend of type document.
In order to make the download work, the response header has the following headers exposed:
access-control-expose-headers: Content-Disposition, Content-Encoding
and the values are set correctly:
content-disposition: attachment; filename="2022-10-12_13-12_download.csv"
content-type: text/csv; charset=UTF-8
(note: the content-encoding header is not set)
However, as stated earlier, there are three calls to the backend done.
- the preflight (which runs fine)
- the metadata call (which needs the token, but does not get it)
- the fetch (which has the token):
I tried
to google a dozen different ways, all asking how can i add a custom header to the fetching of metadata for downloads?
, but could not find anything on that matter.
Other than that, I noticed, that cookies are send to the backend when fetching the metadata:
So I tried to add the access token to the cookies programmatically, but the cookie is ignored because the cookie header does not include the programmatically set cookie.
Finally, the question
Is there any way, that I can make this work?
Is there any way, that I can send the custom XCompanyAccessToken
header to the backend when the browser decides to initiate a call of type document
to retrieve metadata?
Are any changes on the backend side needed for this?