Encoder l'URL en JavaScript?

2470

Comment encoder une URL en toute sécurité à l'aide de JavaScript de manière à ce qu'elle puisse être placée dans une chaîne GET?

var myUrl = "http://example.com/index.html?param=1&anotherParam=2";
var myOtherUrl = "http://example.com/index.html?url=" + myUrl;

Je suppose que vous devez coder la myUrlvariable sur cette deuxième ligne?

nickf
la source
22
Essayez de regarder dans encodeURI () et decodeURI () .
Zack The Human
1
Vous pouvez utiliser cet outil ici: phillihp.com/toolz/url-encode-decode
phillihp
2
encodeURIComponent ()
Andrew

Réponses:

2791

Découvrez la fonction intégrée encodeURIComponent (str) et encodeURI (str) .
Dans votre cas, cela devrait fonctionner:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);
Buu Nguyen
la source
12
Que diriez-vous d'ajouter l'explication donnée par @cms? escapeest également une option valide.
hitautodestruct
11
selon @CMS encodeURIn'est pas vraiment sûr pour le codage d'URL.
Si
13
@AnaelFavre parce qu'il est censé coder l'URL complète, ce qui ne permet pas de caractères tels que :, /, @etc. Ces 2 méthodes ne sont pas interchangeables à utiliser, vous devez savoir ce que vous encodez à utiliser la bonne méthode.
Buu Nguyen
Comme mentionné dans une autre réponse sur cette page , ce site détaille bien la raison d'utiliser cette méthode
Brad Parks
1523

Vous avez trois options:

  • escape() ne codera pas: @*/+

  • encodeURI() ne codera pas: ~!@#$&*()=:/,;?+'

  • encodeURIComponent() ne codera pas: ~!*()'

Mais dans votre cas, si vous souhaitez passer une URL dans un GETparamètre d'une autre page, vous devez utiliser escapeou encodeURIComponent, mais pas encodeURI.

Voir la question Stack Overflow Best practice: escape, ou encodeURI / encodeURIComponent pour une discussion plus approfondie.

CMS
la source
76
Le codage de caractères utilisé avec escape est variable. Restez avec encodeURI et encodeURIComponent, qui utilisent UTF-8.
erickson
6
Faites attention. Cet échappement convertit les caractères non ASCII en ses séquences d'échappement Unicode, comme %uxxx.
opteronn
4
J'utilise encodeURIComponent et je remarque qu'il ne codera pas les caractères de la pipe |
kevzettler
15
@kevzettler - pourquoi devrait-il faire cela? Les canaux n'ont pas d'importance sémantique dans un URI.
nickf
4
@GiovanniP: personnes qui autorisent les caractères allemands, français, japonais, chinois et arabes en entrée et transmettent ces paramètres via GET ou POST.
Tseng
180

Restez avec encodeURIComponent(). La fonction encodeURI()ne prend pas la peine de coder de nombreux caractères qui ont une importance sémantique dans les URL (par exemple "#", "?" Et "&"). escape()est obsolète et ne prend pas la peine de coder les caractères "+", qui seront interprétés comme des espaces codés sur le serveur (et, comme d'autres l'ont souligné ici, ne codent pas correctement les caractères non ASCII par URL).

Il y a une belle explication de la différence entre encodeURI()etencodeURIComponent() ailleurs. Si vous voulez coder quelque chose afin qu'il puisse être inclus en toute sécurité en tant que composant d'un URI (par exemple en tant que paramètre de chaîne de requête), vous voulez l'utiliser encodeURIComponent().

Mike Brennan
la source
83

La meilleure réponse est d'utiliser encodeURIComponentsur des valeurs dans la chaîne de requête (et nulle part ailleurs).

Cependant, je trouve que de nombreuses API veulent remplacer "" par "+", j'ai donc dû utiliser ce qui suit:

const value = encodeURIComponent(value).replace('%20','+');
const url = 'http://example.com?lang=en&key=' + value

escapeest implémenté différemment dans différents navigateurs et encodeURIn'encode pas beaucoup de caractères (comme # et même /) - il est fait pour être utilisé sur un URI / URL complet sans le casser - ce qui n'est pas super utile ou sécurisé.

Et comme @Jochem le souligne ci-dessous, vous voudrez peut-être utiliser encodeURIComponent()un nom de dossier (pour chaque), mais pour une raison quelconque, ces API ne semblent pas vouloir +figurer dans les noms de dossier, donc tout simplement vieux encodeURIComponentfonctionne très bien.

Exemple:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;
Ryan Taylor
la source
22
Veuillez noter que vous ne devez remplacer% 20 par des symboles + qu'après le premier point d'interrogation (qui est la partie "requête" de l'URL). Disons que je veux naviguer http://somedomain/this dir has spaces/info.php?a=this has also spaces. Il doit être converti en: http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spacesmais de nombreuses implémentations permettent de remplacer «% 20» dans la chaîne de requête par «+». Néanmoins, vous ne pouvez pas remplacer '% 20' par '+' dans la section de chemin de l'URL, cela entraînera une erreur Introuvable sauf si vous avez un répertoire avec un +au lieu d'un espace.
Jochem Kuijpers
@Jochem Kuijpers, vous ne mettriez certainement pas "+" dans un répertoire. Je n'appliquerais cela qu'aux valeurs des paramètres de requête elles-mêmes (ou aux clés si nécessaire), pas à l'URL entière, ni même à la chaîne de requête entière.
Ryan Taylor
Je remplacerais en valeur plutôt qu'en résultat du codage
njzk2
1
@ njzk2, malheureusement encodeURIComponent('+'), vous donnerait %2B, vous devez donc utiliser deux expressions régulières ... ce qui, je suppose, est un peu pourquoi cela fonctionne, car '+' sont '' sont encodés différemment à la fin.
Ryan Taylor
Il n'y a aucune raison de traduire% 20 en "+". La séquence d'échappement valide pour l'espace ASCII est% 20, pas "+" qui n'est pas mentionné dans RFC 3986 ( tools.ietf.org/html/rfc3986 ). "+" a été utilisé dans les années 1990; il est désormais obsolète et n'est pris en charge que pour des raisons héritées. Ne l'utilisez pas.
xhienne
40

Si vous utilisez jQuery, j'irais pour la $.paramméthode. Son URL code un champ de mappage d'objet en valeurs, ce qui est plus facile à lire que d'appeler une méthode d'échappement sur chaque valeur.

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1
Maksym Kozlenko
la source
Je pense que l'exemple fourni est suffisant. Si vous avez besoin de plus d'informations sur $ .param sur api.jquery.com/jquery.param
Maksym Kozlenko
Presque tout le monde utilise jQuery et je me sens plus à l'aise avec cela au lieu de encoreURIComponent
Cyril Duchon-Doris
12

encodeURIComponent () est la voie à suivre.

var myOtherUrl = "http://example.com/index.html?url=" + encodeURIComponent(myUrl);

MAIS vous devez garder à l'esprit qu'il existe de petites différences par rapport à la version php urlencode()et comme @CMS l'a mentionné, il n'encodera pas tous les caractères. Les gars sur http://phpjs.org/functions/urlencode/ ont rendu js l'équivalent de phpencode():

function urlencode(str) {
  str = (str + '').toString();

  // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current
  // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
  return encodeURIComponent(str)
    .replace('!', '%21')
    .replace('\'', '%27')
    .replace('(', '%28')
    .replace(')', '%29')
    .replace('*', '%2A')
    .replace('%20', '+');
}
Adam Fischer
la source
10

Pour encoder une URL, comme cela a été dit précédemment, vous avez deux fonctions:

encodeURI()

et

encodeURIComponent()

La raison pour laquelle les deux existent est que le premier préserve l'URL avec le risque de laisser trop de choses sans échapper, tandis que le second code tout ce qui est nécessaire.

Avec le premier, vous pouvez copier l'URL nouvellement échappée dans la barre d'adresse (par exemple) et cela fonctionnera. Cependant, vos «&» non échappés interféreraient avec les délimiteurs de champ, les «=» interféreraient avec les noms et les valeurs des champs et les «+» ressembleraient à des espaces. Mais pour les données simples lorsque vous souhaitez conserver la nature de l'URL de ce que vous échappez, cela fonctionne.

La seconde est tout ce que vous devez faire pour vous assurer que rien dans votre chaîne n'interfère avec une URL. Il laisse divers caractères sans importance échappés afin que l'URL reste aussi lisible que possible sans interférence. Une URL encodée de cette façon ne fonctionnera plus comme URL sans la déséchapper.

Donc, si vous pouvez prendre le temps, vous voulez toujours utiliser encodeURIComponent () - avant d'ajouter des paires nom / valeur, encodez à la fois le nom et la valeur en utilisant cette fonction avant de l'ajouter à la chaîne de requête.

J'ai du mal à trouver des raisons d'utiliser l'encodeURI () - je laisse cela aux gens les plus intelligents.

Gerard ONeill
la source
5

Le même genre de chose que j'ai essayé avec du javascript normal

function fixedEncodeURIComponent(str){
     return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}
Narayan Yerrabachu
la source
5

Manière élégante

À mon humble avis, la façon la plus élégante d'encoder des paramètres de requête est de créer un objet avec des paramètres tels que

const queryParams = { param1: 'value1', param2: 'value2' }

puis l'encode en utilisant:

const queryString = new URLSearchParams(queryParams).toString()

comme mentionné dans cette réponse: https://stackoverflow.com/a/53171438/7284582

Qback
la source
4

Pour éviter le double encodage, c'est une bonne idée de décoder l'URL avant l'encodage (si vous traitez par exemple des URL saisies par l'utilisateur, qui peuvent déjà être encodées).

Disons que nous avons abc%20xyz 123en entrée (un espace est déjà encodé):

encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"
serg
la source
4

Qu'est-ce que le codage d'URL:

Une URL doit être codée lorsqu'il y a des caractères spéciaux à l'intérieur de l'URL. Par exemple:

console.log(encodeURIComponent('?notEncoded=&+'));

On peut observer dans cet exemple que tous les caractères sauf la chaîne notEncodedsont encodés avec des signes%. L'encodage d'URL est également connu sous le nom d' encodage en pourcentage car il échappe à tous les caractères spéciaux avec un%. Ensuite, après ce signe%, chaque caractère spécial a un code unique

Pourquoi avons-nous besoin d'un encodage URL:

Certains caractères ont une valeur spéciale dans une chaîne URL. Par exemple, le? Le caractère indique le début d'une chaîne de requête. Afin de localiser avec succès une ressource sur le Web, il est nécessaire de faire la distinction entre le moment où un caractère est censé faire partie d'une chaîne ou d'une partie de la structure d'URL.

Comment pouvons-nous réaliser le codage URL dans JS:

JS offre un tas de fonctions utilitaires intégrées que nous pouvons utiliser pour encoder facilement les URL. Ce sont deux options pratiques:

  1. encodeURIComponent(): Prend un composant d'un URI comme argument et retourne la chaîne URI codée.
  2. encodeURI(): Prend un URI comme argument et renvoie la chaîne URI codée.

Exemple et mises en garde:

N'oubliez pas de ne pas transmettre l'intégralité de l'URL (y compris le schéma, par exemple https: //) dans encodeURIComponent(). Cela peut en fait le transformer en une URL non fonctionnelle. Par exemple:

// for a whole URI don't use encodeURIComponent it will transform
// the / characters and the URL won't fucntion properly
console.log(encodeURIComponent("http://www.random.com/specials&char.html"));

// instead use encodeURI for whole URL's
console.log(encodeURI("http://www.random.com/specials&char.html"));

Nous pouvons observer f nous avons mis l'URL entière dans encodeURIComponentla mesure où les barres obliques (/) sont également converties en caractères spéciaux. Cela entraînera l'URL de ne plus fonctionner correctement.

Par conséquent (comme son nom l'indique), utilisez:

  1. encodeURIComponent sur une certaine partie d'une URL que vous souhaitez encoder.
  2. encodeURI sur une URL entière que vous souhaitez encoder.
Willem van der Veen
la source
3

Rien n'a fonctionné pour moi. Tout ce que je voyais était le code HTML de la page de connexion, revenant du côté client avec le code 200. (302 au début, mais la même demande Ajax chargeant la page de connexion dans une autre demande Ajax, qui était censée être une redirection plutôt que de charger plain texte de la page de connexion).

Dans le contrôleur de connexion, j'ai ajouté cette ligne:

Response.Headers["land"] = "login";

Et dans le gestionnaire global Ajax, j'ai fait ceci:

$(function () {
    var $document = $(document);
    $document.ajaxSuccess(function (e, response, request) {
        var land = response.getResponseHeader('land');
        var redrUrl = '/login?ReturnUrl=' + encodeURIComponent(window.location);
        if(land) {
            if (land.toString() === 'login') {
                window.location = redrUrl;
            }
        }
    });
});

Maintenant, je n'ai aucun problème, et cela fonctionne comme un charme.

Asif Ashraf
la source
2

Encoder la chaîne d'URL

    var url = $ ( emplacement ). attr ( «href» ); // obtenir l'url actuelle // OU var url = 'folder / index.html? param = # 23dd & noob = yes' ; // ou spécifiez-en un 
    
      

var encodedUrl = encodeURIComponent(url); console.log(encodedUrl); //outputs folder%2Findex.html%3Fparam%3D%2323dd%26noob%3Dyes for more info go http://www.sitepoint.com/jquery-decode-url-string
Sangeet Shah
la source
2

Voici une démo en direct de JS encodeURIComponent()et des decodeURIComponent()fonctions intégrées:

<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
    <script>
      // encode string to base64
      function encode()
      {
        var txt = document.getElementById("txt1").value;
        var result = btoa(txt);
        document.getElementById("txt2").value = result;
      }
      // decode base64 back to original string
      function decode()
      {
        var txt = document.getElementById("txt3").value;
        var result = atob(txt);
        document.getElementById("txt4").value = result;
      }
    </script>
  </head>
  <body>
    <div>
      <textarea id="txt1">Some text to decode
      </textarea>
    </div>
    <div>
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
    </div>
    <div>
      <textarea id="txt2">
      </textarea>
    </div>
    <br/>
    <div>
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
    </div>
    <div>
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
    </div>
    <div>
      <textarea id="txt4">
      </textarea>
    </div>
  </body>
</html>
jonathana
la source
1

Vous pouvez utiliser la bibliothèque esapi et encoder votre URL en utilisant la fonction ci-dessous. La fonction garantit que «/» n'est pas perdu lors de l'encodage tandis que le reste du contenu du texte est encodé:

function encodeUrl(url)
{
    String arr[] = url.split("/");
    String encodedUrl = "";
    for(int i = 0; i<arr.length; i++)
    {
        encodedUrl = encodedUrl + ESAPI.encoder().encodeForHTML(ESAPI.encoder().encodeForURL(arr[i]));
        if(i<arr.length-1) encodedUrl = encodedUrl + "/";
    }
    return url;
}

https://www.owasp.org/index.php/ESAPI_JavaScript_Readme

Mohith Maratt
la source
1

Utilisez la fixedEncodeURIComponentfonction pour se conformer strictement à la RFC 3986 :

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
Arthur
la source
1

Vous ne devez pas utiliser encodeURIComponent()directement.

Jetez un oeil à RFC3986: identificateur de ressource uniforme (URI): syntaxe générique

sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Le but des caractères réservés est de fournir un ensemble de caractères de délimitation qui se distinguent des autres données dans un URI.

Ces caractères réservés de la définition d'URI dans RFC3986 NE SONT PAS échappés par encodeURIComponent().

Documents Web MDN: encodeURIComponent ()

Pour être plus rigoureux dans l'adhésion à la RFC 3986 (qui réserve!, ', (,) Et *), même si ces caractères n'ont pas d'utilisations de délimitation URI formalisées, les éléments suivants peuvent être utilisés en toute sécurité:

Utilisez la fonction MDN Web Docs ...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
HoldOffHunger
la source