¿Codificar URL en JavaScript?

2470

¿Cómo codifica de manera segura una URL usando JavaScript de modo que pueda colocarse en una cadena GET?

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

¿Asumo que necesitas codificar la myUrlvariable en esa segunda línea?

nickf
fuente
22
Intenta buscar en encodeURI () y decodeURI () .
Zack The Human
1
Puede utilizar esta herramienta aquí: phillihp.com/toolz/url-encode-decode
phillihp
2
encodeURIComponent ()
Andrew

Respuestas:

2791

Consulte la función incorporada encodeURIComponent (str) y encodeURI (str) .
En su caso, esto debería funcionar:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);
Buu Nguyen
fuente
12
¿Qué tal si agregamos la explicación que dio @cms? escapeTambién es una opción válida.
hitautodestruct
11
según @CMS encodeURIno es realmente seguro para la codificación de URL.
Si no es el
13
@AnaelFavre debido a que está destinado a codificar toda la URL, lo que no permite caracteres tales como :, /, @etc., no deben ser utilizados intercambiables Estos 2 métodos, debe saber lo que está codificando para usar el método correcto.
Buu Nguyen
Como se menciona en otra respuesta en esta página , este sitio detalla muy bien la razón para usar este método
Brad Parks,
1522

Tienes tres opciones:

  • escape() no codificará: @*/+

  • encodeURI() no codificará: ~!@#$&*()=:/,;?+'

  • encodeURIComponent() no codificará: ~!*()'

Pero en su caso, si desea pasar una URL a un GETparámetro de otra página, debe usar escapeo encodeURIComponent, pero noencodeURI .

Consulte la pregunta sobre desbordamiento de pila. Práctica recomendada: escape, o encodeURI / encodeURIComponent para obtener más información.

CMS
fuente
76
La codificación de caracteres utilizada con escape es variable. Quédese con encodeURI y encodeURIComponent, que usan UTF-8.
erickson
66
Ten cuidado. Ese escape convierte caracteres no ASCII en sus secuencias de escape Unicode, como %uxxx.
Opteronn
44
Estoy usando encodeURIComponent y me doy cuenta de que no codificará caracteres de tubería |
kevzettler
15
@kevzettler: ¿por qué debería hacer eso? Las tuberías no son de importancia semántica en un URI.
nickf
44
@GiovanniP: personas que admiten caracteres alemanes, franceses, japoneses, chinos y árabes como entrada y pasan estos parámetros a través de GET o POST.
Tseng
180

Quédate con encodeURIComponent(). La función encodeURI()no se molesta en codificar muchos caracteres que tienen importancia semántica en las URL (por ejemplo, "#", "?" Y "&").escape()está en desuso y no se molesta en codificar caracteres "+", que se interpretarán como espacios codificados en el servidor (y, como han señalado otros aquí, no codifica correctamente los caracteres que no son ASCII).

Hay una buena explicación de la diferencia entre encodeURI()y enencodeURIComponent() otros lugares. Si desea codificar algo para que pueda incluirse de forma segura como un componente de un URI (por ejemplo, como un parámetro de cadena de consulta), desea utilizarlo encodeURIComponent().

Mike Brennan
fuente
83

La mejor respuesta es el uso encodeURIComponentde los valores en la cadena de consulta (y ningún otro lugar).

Sin embargo, creo que muchas API quieren reemplazar "" con "+", así que tuve que usar lo siguiente:

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

escapese implementa de manera diferente en diferentes navegadores y encodeURIno codifica muchos caracteres (como # e incluso /); está hecho para usarse en un URI / URL completo sin romperlo, lo que no es muy útil ni seguro.

Y como @Jochem señala a continuación, es posible que desee usar encodeURIComponent()en un (cada) nombre de carpeta, pero por alguna razón, estas API no parecen querer +en los nombres de carpeta, por lo que los viejos encodeURIComponentfuncionan muy bien.

Ejemplo:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;
Ryan Taylor
fuente
22
Tenga en cuenta que solo debe reemplazar% 20 con símbolos + después del primer signo de interrogación (que es la parte de 'consulta' de la URL). Digamos que quiero navegar http://somedomain/this dir has spaces/info.php?a=this has also spaces. Debería convertirse a: http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spacespero muchas implementaciones permiten que '% 20' en la cadena de consulta se reemplace por '+'. Sin embargo, no puede reemplazar '% 20' con '+' en la sección de ruta de la URL, esto dará como resultado un error No encontrado a menos que tenga un directorio con +un espacio en lugar de un espacio.
Jochem Kuijpers
@Jochem Kuijpers, definitivamente, no pondrías "+" en un directorio. Solo aplicaría esto a los valores de los parámetros de consulta en sí (o las claves si es necesario), no a la URL completa, o incluso a toda la cadena de consulta.
Ryan Taylor
Reemplazaría en valor en lugar de en el resultado de la codificación
njzk2
1
@ njzk2 desafortunadamente encodeURIComponent('+')te daría %2B, así que tendrías que usar dos expresiones regulares ... lo que supongo es un poco por qué esto funciona, porque '+' son '' están codificadas de manera diferente al final.
Ryan Taylor
No hay razón para traducir% 20 a "+". La secuencia de escape válida para el espacio ASCII es% 20, no "+", que no se menciona en RFC 3986 ( tools.ietf.org/html/rfc3986 ). "+" se usó en la década de 1990; ahora está obsoleto y solo se admite por motivos heredados. No lo uses
xhienne
40

Si está utilizando jQuery, iría por el $.parammétodo. Su URL codifica los campos de asignación de objetos a valores, lo que es más fácil de leer que llamar a un método de escape en cada valor.

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1
Maksym Kozlenko
fuente
Creo que ese ejemplo proporcionado es suficiente. Si necesita más información sobre $ .param en api.jquery.com/jquery.param
Maksym Kozlenko
Casi todos usan jQuery y me siento más cómodo con esto en lugar de encoreURIComponent
Cyril Duchon-Doris
12

encodeURIComponent () es el camino a seguir.

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

PERO debe tener en cuenta que existen pequeñas diferencias con respecto a la versión de php urlencode()y, como se mencionó en @CMS, no codificará todos los caracteres. Chicos en http://phpjs.org/functions/urlencode/ hicieron js equivalente a 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
fuente
10

Para codificar una URL, como se ha dicho antes, tiene dos funciones:

encodeURI()

y

encodeURIComponent()

La razón por la que ambos existen es que el primero conserva la URL con el riesgo de dejar demasiadas cosas sin escapar, mientras que el segundo codifica todo lo necesario.

Con el primero, podría copiar la URL recién escapada en la barra de direcciones (por ejemplo) y funcionaría. Sin embargo, sus '&' sin escape interferirían con los delimitadores de campo, los '=' interferirían con los nombres y valores de campo, y los '+' se verían como espacios. Pero para datos simples cuando desea preservar la naturaleza de URL de lo que está escapando, esto funciona.

El segundo es todo lo que necesita hacer para asegurarse de que nada en su cadena interfiera con una URL. Deja varios caracteres sin importancia sin escapes para que la URL permanezca lo más legible posible sin interferencia. Una URL codificada de esta manera ya no funcionará como una URL sin desescaparla.

Entonces, si puede tomarse el tiempo, siempre desea usar encodeURIComponent (), antes de agregar pares de nombre / valor codifique tanto el nombre como el valor usando esta función antes de agregarlo a la cadena de consulta.

Me está costando trabajo encontrar razones para usar el encodeURI (). Se lo dejaré a las personas más inteligentes.

Gerard ONeill
fuente
5

Tipo similar de cosas que probé con javascript normal

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

Manera elegante

En mi humilde opinión, la forma más elegante de codificar parámetros de consulta es crear un objeto con parámetros como

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

y luego codificarlo usando:

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

como se menciona en esta respuesta: https://stackoverflow.com/a/53171438/7284582

Qback
fuente
4

Para evitar la doble codificación, es una buena idea decodificar la url antes de codificar (si se trata de URL ingresadas por el usuario, por ejemplo, que podrían estar ya codificadas).

Digamos que tenemos abc%20xyz 123como entrada (un espacio ya está codificado):

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

Qué es la codificación de URL:

Se debe codificar una URL cuando hay caracteres especiales ubicados dentro de la URL. Por ejemplo:

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

En este ejemplo, podemos observar que todos los caracteres, excepto la cadena, notEncodedestán codificados con signos%. La codificación URL también se conoce como codificación porcentual porque escapa a todos los caracteres especiales con un%. Luego, después de este signo%, cada carácter especial tiene un código único

¿Por qué necesitamos la codificación de URL?

Ciertos caracteres tienen un valor especial en una cadena URL. Por ejemplo, el? El carácter indica el comienzo de una cadena de consulta. Para localizar con éxito un recurso en la web, es necesario distinguir cuándo un carácter se entiende como parte de una cadena o parte de la estructura de la URL.

¿Cómo podemos lograr la codificación de URL en JS:

JS ofrece un montón de funciones de utilidad incorporadas que podemos usar para codificar fácilmente las URL. Estas son dos opciones convenientes:

  1. encodeURIComponent(): Toma un componente de un URI como argumento y devuelve la cadena de URI codificada.
  2. encodeURI(): Toma un URI como argumento y devuelve la cadena de URI codificada.

Ejemplo y advertencias:

Tenga en cuenta que no debe pasar toda la URL (incluido el esquema, por ejemplo, https: //) a encodeURIComponent(). En realidad, esto puede transformarlo en una URL no funcional. Por ejemplo:

// 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"));

Podemos observar si ponemos la URL completa en encodeURIComponentque las barras diagonales (/) también se convierten en caracteres especiales. Esto hará que la URL ya no funcione correctamente.

Por lo tanto (como su nombre lo indica) use:

  1. encodeURIComponent en una determinada parte de una URL que desea codificar.
  2. encodeURI en una URL completa que desea codificar.
Willem van der Veen
fuente
3

Nada me funcionó. Todo lo que estaba viendo era el HTML de la página de inicio de sesión, volviendo al lado del cliente con el código 200. (302 al principio pero la misma solicitud de Ajax cargando la página de inicio de sesión dentro de otra solicitud de Ajax, que se suponía que era una redirección en lugar de cargarla sin formato texto de la página de inicio de sesión).

En el controlador de inicio de sesión, agregué esta línea:

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

Y en el controlador global de Ajax, hice esto:

$(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;
            }
        }
    });
});

Ahora no tengo ningún problema, y ​​funciona de maravilla.

Asif Ashraf
fuente
2

Codificar cadena de URL

    var url = $ ( ubicación ). attr ( 'href' ); // obtener la url actual // O var url = 'folder / index.html? param = # 23dd & noob = yes' ; // o especifica uno 
    
      

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
fuente
2

Aquí hay una demostración en vivo de JS encodeURIComponent()y decodeURIComponent()funciones incorporadas:

<!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
fuente
1

Puede usar la biblioteca esapi y codificar su url usando la siguiente función. La función asegura que '/' no se pierda en la codificación mientras que el resto del contenido del texto está codificado:

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
fuente
1

Utilice la fixedEncodeURIComponentfunción para cumplir estrictamente con RFC 3986 :

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

No deberías usarlo encodeURIComponent()directamente.

Eche un vistazo a RFC3986: Identificador uniforme de recursos (URI): sintaxis genérica

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

El propósito de los caracteres reservados es proporcionar un conjunto de caracteres delimitadores que se puedan distinguir de otros datos dentro de un URI.

Estos caracteres reservados de la definición de URI en RFC3986 NO SE ESCAPAN encodeURIComponent().

Documentos web de MDN: encodeURIComponent ()

Para ser más estrictos al adherirse a RFC 3986 (que se reserva!, ', (,) Y *), a pesar de que estos caracteres no tienen usos de delimitación de URI formalizados, se puede usar de manera segura lo siguiente:

Use la función MDN Web Docs ...

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