Cypress: Intercepting a binary file download call -> corruped Zip
Hello there. I want to intercept a binary file download api call using cypress. I want to mock it with a local file. It is a zip file.
The backend sends me a binary.
The requests:
Body response
The Content-Type is application/octet-stream
Real world response header:
Access-Control-Allow-Credentials:
true
Access-Control-Expose-Headers:
Content-Disposition
Content-Type:
application/octet-stream
Date:
Mon, 22 May 2023 12:06:47 GMT
Real world request header:
Accept:
application/octet-stream
Mocked with cypress response header:
access-control-allow-credentials: true
access-control-allow-origin: *
Connection: keep-alive
Content-Type: octet-stream
Date: Mon, 22 May 2023 11:54:56 GMT
Keep-Alive: timeout=5
Transfer-Encoding: chunked
Mocked with cypress request header:
GET /backup HTTP/1.1
Accept: application/octet-stream
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Referer: http://127.0.0.1:4200/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/111.0.0.0 Safari/537.36
X-Cypress-Is-XHR-Or-Fetch: xhr
sec-ch-ua: "Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
In my applications it becomes a Blob and I can unzip it and work with the content. If I take the same file and use cypress' readFile I see the exact same string as the above body response. I put it in the interceps body. I also set the proper headers.
The error: "Error: Corrupted zip: missing 2059592310 bytes." occurs The logged Blob also has a different size, even tho it is the same file.
real world: »Blob {size: 31478, type: 'application/octet-stream'}
mocked with cypress: »Blob {size: 56721, type: 'application/octet-stream'}
Code:
Then('I navigate to the live settings tab and intercept the download call', () => {
cy.readFile('src/fixtures/machines/machine-settings-export/settings_values.zip', 'utf-8').then((file) => {
cy.intercept('GET', '**/backup', (req) => {
// reset the request header in case it does make any difference
req.headers['accept-encoding'] = null;
// file and headers are set
console.warn('headers', req.headers);
console.warn('file', file);
req.reply({
statusCode: 200,
body: file,
headers: {
'Content-Type': 'octet-stream',
},
});
}).as('downloadCall');
cy.get('machine-configurations-dialog').contains('LIVE MASCHINEN-EINSTELLUNGEN').click();
});
cy.wait('@downloadCall')
.its('request')
.then((req) => {
// body is empty for some reason aswell
console.warn('download intercept its request: ', req);
// download it here aswell to test it in another way
const fileName = `1234TEST.zip`;
saveAs(req.body, fileName);
});
});
What I tried:
I tried to remove the accept-encoding header.
I thought the browser might handle the response in a different way, but it didnt work out.
I also tried using different encodings for the readFile (utf8 or binary) but utf8 seems right because the response body looks identical to the real world applications.
I found some github issues where people also had problems with intercepting binary files.
https://github.com/cypress-io/cypress/issues/16722
https://github.com/cypress-io/cypress/issues/15038
I really dont know what it could be.
Since in the real world application and in the intercepted cypress call the response body was identical (the picture) I think the problem may be the intercept itself or different headers.
I also tried setting the response headers
'Accept-Ranges': 'bytes',
'Content-Length': file.length.toString(),
This resulted in a different length of the Blob and another error:
Blob {size: 30009, type: 'application/octet-stream'}
Corrupted zip: can't find end of central directory
Update:
Setting readfile to 'binary' seems right.
Using this code afterwards works perfectly and lets me unpack the zip:
cy.writeFile('cypress/fixtures/machines/machine-settings-export/test.zip', file, 'binary');
file.length is the correct number. After the blob creating inside the api service the the size of the blob is almost twice as big.
I have no idea why this happens. This only happens whenever I dont set the content-length header. If I do set the header, the blob size will be correct, but it is still a corrupted zip. The content-type header does not make any difference to that behavior.
log screenshot
original file size