L'Antre d'un poulpe

Créer un bookmarklet LAN/WAN

· Grishka

Le dernière fois, j’ai expliqué comment j’ai mis en place une méthode de fainéant ingénieuse pour pouvoir joindre mon domaine blog.grishka.fr en toute circonstance, que je sois sur mon réseau local ou sur un autre réseau.

En parallèle, je me suis demandé s’il était possible d’obtenir un résultat similaire sans toucher aux paramètres réseau, juste avec un signet.

Et la réponse est oui, avec un bookmarklet. En deux mots, c’est un signet qui exécute un bref code en javascript au lieu d’ouvrir simplement une adresse internet.

Le code

Voici le contenu du bookmarklet :

javascript:(function(){javascript:(function(){javascript:(function(){
    var localIp = "ip_locale_ici"; // IP locale avec port si besoin
    var distantDomain = "domaine_ici"; // Domaine distant
    var timeoutDuration = 200; // Timeout en millisecondes

    // Fonction pour créer un timeout de promesse
    var timeout = new Promise(function(resolve, reject) {
        setTimeout(reject, timeoutDuration, 'timeout');
    });

    // Fonction pour vérifier si l'IP locale est accessible avec un fetch
    var fetchLocalIp = fetch(localIp, { mode: 'no-cors' });

    // Utilisation de Promise.race pour ajouter un timeout à la requête fetch
    Promise.race([fetchLocalIp, timeout])
        .then(function() {
            // Si l'IP locale est accessible, redirige vers l'IP locale
            if (window.location.href !== localIp) {
                window.location.href = localIp;
            }
        })
        .catch(function(error) {
            // Si le timeout est atteint ou si la requête échoue, redirige vers le domaine distant
            if (window.location.href !== distantDomain) {
                window.location.href = distantDomain;
            }
        });
})();})();})();

Je ne vais pas m’amuser à expliquer chaque ligne, pour la bonne raison que je n’ai aucune compétence en javascript. Ce code a été inspiré par quelques lectures sur le web et conçu avec l’aide d’un générateur de texte branché sur un LLM. Je pourrais dire « une IA » tout de suite, mais le terme m’agace, et je fais ce que je veux sur mon blog. :p

Les commentaires dans le code sont de toute façon suffisamment explicites :

  1. Je renseigne 2 variable, une pour l’IP locale du service, l’autre pour le nom de domaine.
  2. On ajoute un timeout à la vérification : passé 200 ms, on considère que c’est un échec.
  3. On vérifie si l’IP locale est accessible
  4. Si c’est le cas, on l’ouvre.
  5. Si ce n’est pas le cas, on ouvre le nom de domaine.

Il ne faut pas placer le code tel quel dans le champ « adresse » d’un signet, il faut qu’il soit url_encoded : c’est une méthode pour remplacer les espaces et saut de ligne par des caractères lisibles par le navigateur.

J’ai utilisé un service auto-hébergé pour cela : https://tools.grishka.fr/url-encoder/. Il suffit de copier le code et de le coller dans la zone your string du bloc encode. Vous obtiendrez ceci en dessous :

javascript%3A(function()%7Bjavascript%3A(function()%7Bjavascript%3A(function()%7B%0A%20%20%20%20var%20localIp%20%3D%20%22ip_locale_ici%22%3B%20%2F%2F%20IP%20locale%20avec%20port%20si%20besoin%0A%20%20%20%20var%20distantDomain%20%3D%20%22domaine_ici%22%3B%20%2F%2F%20Domaine%20distant%0A%20%20%20%20var%20timeoutDuration%20%3D%20200%3B%20%2F%2F%20Timeout%20en%20millisecondes%0A%0A%20%20%20%20%2F%2F%20Fonction%20pour%20cr%C3%A9er%20un%20timeout%20de%20promesse%0A%20%20%20%20var%20timeout%20%3D%20new%20Promise(function(resolve%2C%20reject)%20%7B%0A%20%20%20%20%20%20%20%20setTimeout(reject%2C%20timeoutDuration%2C%20'timeout')%3B%0A%20%20%20%20%7D)%3B%0A%0A%20%20%20%20%2F%2F%20Fonction%20pour%20v%C3%A9rifier%20si%20l'IP%20locale%20est%20accessible%20avec%20un%20fetch%0A%20%20%20%20var%20fetchLocalIp%20%3D%20fetch(localIp%2C%20%7B%20mode%3A%20'no-cors'%20%7D)%3B%0A%0A%20%20%20%20%2F%2F%20Utilisation%20de%20Promise.race%20pour%20ajouter%20un%20timeout%20%C3%A0%20la%20requ%C3%AAte%20fetch%0A%20%20%20%20Promise.race(%5BfetchLocalIp%2C%20timeout%5D)%0A%20%20%20%20%20%20%20%20.then(function()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20Si%20l'IP%20locale%20est%20accessible%2C%20redirige%20vers%20l'IP%20locale%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(window.location.href%20!%3D%3D%20localIp)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20window.location.href%20%3D%20localIp%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%20%20%20%20.catch(function(error)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20Si%20le%20timeout%20est%20atteint%20ou%20si%20la%20requ%C3%AAte%20%C3%A9choue%2C%20redirige%20vers%20le%20domaine%20distant%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(window.location.href%20!%3D%3D%20distantDomain)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20window.location.href%20%3D%20distantDomain%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%7D)()%3B%7D)()%3B%7D)()%3B

Difficilement lisible, mais ce n’est pas le but. Copier/coller simplement le code à la place de l’adresse web d’un signet et le tour est joué. Il est recommandé de supprimer tous les commentaires avant également, pour alléger le code. Ce sont les lignes qui commencent par //.