I use service worker to modify the fetch response with below code,
self.addEventListener('install', function(event) {
console.log('install');
});
self.addEventListener('activate', function(event) {
console.log('Claiming control');
return self.clients.claim();
});
self.addEventListener('fetch', function(event) {
console.log("fetch event")
event.respondWith(
fetch(event.request).then(function (response) {
if(response.url.match('.mp4')){
console.log(event);
response.arrayBuffer().then(
buffer =>{
let length = 100
view = new Uint8Array(buffer,0,length)
for(i=0,j=length - 1; i<j; i++,j--){
view[i] = view[i] ^ view[j]
view[j] = view[j] ^ view[i]
view[i] = view[i] ^ view[j]
}
}
)
}
return response.clone();
})
);
});
Whichi will lead to this warning and error,
The FetchEvent for "" resulted in a network error response: the promise was rejected.
sw.js:60 Uncaught (in promise) TypeError: Failed to execute 'clone' on 'Response': Response body is already used at sw.js:60
If I put the clone() before arrayBuffer() like below,
self.addEventListener('install', function(event) {
console.log('install');
});
self.addEventListener('activate', function(event) {
console.log('Claiming control');
return self.clients.claim();
});
self.addEventListener('fetch', function(event) {
console.log("fetch event")
event.respondWith(
fetch(event.request).then(function (response) {
if(response.url.match('.mp4')){
console.log(event);
responseCloned = response.clone();
responseCloned.arrayBuffer().then(
buffer =>{
let length = 100
view = new Uint8Array(buffer,0,length)
for(i=0,j=length - 1; i<j; i++,j--){
view[i] = view[i] ^ view[j]
view[j] = view[j] ^ view[i]
view[i] = view[i] ^ view[j]
}
}
)
}
return responseCloned;
})
);
});
It will lead to below warning and error,
The FetchEvent for "" resulted in a network error response: a Response whose "body" is locked cannot be used to respond to a request.
GET http://localhost/web/357765_decrypted.mp4 net::ERR_FAILED
Try instantiating and returning a new Response() with the decrypted bytes:
self.addEventListener('fetch', event => {
if (event.request.url.endsWith('.mp4') {
event.respondWith(getDecryptedResponse(event.request))
}
})
async function getDecryptedResponse(request) {
const response = await fetch(request)
const bytes = new Uint8Array(await response.arrayBuffer())
return new Response(
new Blob([ decryptMp4Bytes(bytes) ], { type: 'application/mp4' }),
{
headers: response.headers, // possibly required for this case
}
)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With