Altro Modificare oggetto Response su Javascript

Helplease

Utente Silver
29 Dicembre 2019
115
31
6
77
Buonasera a tutti, provando a modificare l'attributo body di un oggetto Response ritornato da fetch ho notato che i miei tentativi non avevano alcun effetto su di esso, il quale infatti ho poi scoperto essere read-only dopo una breve ricerca. Qualcuno saprebbe come bypassare questa "protezione"? Grazie.
 
Se stai facendo sviluppo ti consiglio di lasciar perdere, è read-only per un motivo, se devi elaborare la risposta copia il contenuto in una variabile e lavora su quella.

Se invece devi fare hacking penso che una soluzione potrebbe essere fare hook su fetch: da lì chiami la funzione originale, poi crei un Uint8Array con la risposta modificata e un nuovo ReadableStream basato su di esso, infine crei una nuova Response sulla base dello stream e la ritorni.
 
  • Mi piace
Reazioni: Helplease
Grazie mille per la risposta; il mio obiettivo era quello di creare un AD-Blocker per Youtube attraverso TamperMonkey. Avevo già provato la soluzione che tu mi suggerisci, ma quando salvo il programma e apro YT i video smettono di caricarsi dopo qualche secondo, come se il mio nuovo response non venisse "accettato". Ti allego quello che ho fatto finora:
JavaScript:
// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.youtube.com/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    window.fetch0 = window.fetch;
    window.fetch = function (...args) {
        return new Promise(function (a,b)
                           {
            a()
        }).then(function ()
                {
            return fetch0(...args);
        }).then(function (u)
                {
            e = u;
            return u.body.getReader().read();
        }).then(function(a)
                {
            let r = new ReadableStream({
                start(controller) {
                    controller.enqueue(a.value); //a.value verrà poi sostituito con la risposta modificata
                    controller.close();
                }
            }).pipeThrough(new TransformStream({
                transform(chunk, controller) {
                    controller.enqueue(chunk);
                }
            }))
            re = new Response(r,{status:e.status,statusText:e.statusText,headers:e.headers});
            console.log(re);
            return re;
        })
    }})()
E poi un'altra domanda veloce: io potrei fare una cosa del tipo return u,u.body.getReader().read() per evitare di dover creare una variabile e globale?
Grazie ancora.
 
Prova così:

JavaScript:
// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.youtube.com/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        unsafeWindow
// ==/UserScript==

(function() {
    'use strict';
    let original = unsafeWindow.fetch;
    unsafeWindow.fetch = function (...args) {
        var e = {};
        return original(...args)
            .then(function (u) {
                e = u;
                return u.body.getReader().read();
            })
            .then(function(a) {
                let r = new ReadableStream({
                        start(controller) {
                            controller.enqueue(a.value); //a.value verrà poi sostituito con la risposta modificata
                            controller.close();
                        }})
                    .pipeThrough(new TransformStream({
                        transform(chunk, controller) {
                            controller.enqueue(chunk);
                        }}));
                let re = new Response(r,{status:e.status,statusText:e.statusText,headers:e.headers});
                console.log(re);
                return re;
            });
    };
})()
 
  • Mi piace
Reazioni: Helplease
No, purtroppo ancora non funziona. Il motivo potrebbe essere che, creando un nuovo Response, non si possano impostare gli attributi url e type?
 
Non so cosa stai provando ma ho aperto un video a caso su youtube e ha funzionato normalmente mentre in console vedevo scorrere i log delle response. Per la questione di bloccare le ads, hai già verificato se è proprio tramite api fetch che le ottengono? Non xmlhttpwebrequest, websocket...? Io non ho fatto alcun approfondimento in merito ma dai log in console sembrano avvenire proprio nei momenti in cui non sta caricando la pubblicità :asd: ma magari non significa niente e lo fa prima tenendola in cache, non ho analizzato il contenuto.
 
  • Mi piace
Reazioni: Helplease
Le informazioni sugli annunci vengono ottenute con una richiesta POST (attraverso fetch) a https://www.youtube.com/youtubei/v1/player?* (o https://www.youtube.com/watch?* se è la prima volta che viene caricata la pagina).
La mia idea era semplicemente rimuovere dalla risposta la sezione adPlacements.
Ma i video ti funzionano anche se mandi un po' avanti la riproduzione? Perchè anche a me all'inizio sembra che vadano, e poi si bloccano dopo qualche secondo.
 
Le informazioni sugli annunci vengono ottenute con una richiesta POST (attraverso fetch) a https://www.youtube.com/youtubei/v1/player?* (o https://www.youtube.com/watch?* se è la prima volta che viene caricata la pagina).
La mia idea era semplicemente rimuovere dalla risposta la sezione adPlacements.
Ma i video ti funzionano anche se mandi un po' avanti la riproduzione? Perchè anche a me all'inizio sembra che vadano, e poi si bloccano dopo qualche secondo.

Si, ho provato il codice che ho postato con tampermonkey su firefox, ho provato un paio di video a saltare, tornare indietro, cliccare sui suggeriti, con e senza l'estensione che solitamente uso per bloccare le ads (disabilitata e riavvio di firefox). Le Response continuavano ad arrivare però senza modificare il codice è difficile vedere cosa contengono perché qualche componente di YT ha già aperto il reader e non mi è possibile farlo nuovamente da console. Se stai provando con le tue modifiche per rimuovere adPlacements potrebbe essere proprio questa la causa dell'interruzione, altrimenti non saprei quali altre differenze possono avere i nostri browser, quindi se non è quello ti tocca debuggare.

PS: hai aggiornato il grant ad unsafeWindow?
 
  • Mi piace
Reazioni: Helplease
Allora, ho provato con il tuo stesso identico codice (quindi senza provare modifiche) e funziona soltanto su Firefox, anche se pure così ci sono dei piccoli malfunzionamenti (per esempio a volte mi dice che sono offline e devo aggiornare la pagina, la home si carica solo fino ad un certo punto, e gli shorts ogni tanto danno dei problemi). Il problema sembra quindi essere il browser. Secondo te quali potrebbero essere i motivi nello specifico?
 
Non saprei quali differenze di comportamento ci possono essere con Chrome o altri browser e al momento non ho modo di provare. Forse ha a che fare come viene creato il ReadableStream. So solo che se il js di YT controllasse url, type o window.fetch.toString() non funzionerebbe neanche su firefox a meno che non venga escluso esplicitamente per qualche motivo.
 
  • Mi piace
Reazioni: Helplease