Como evitar que window.open te joda los ámpersands

28 Jul

O también “Cómo abrir un Popup con una URL “escapada” en el GET y no morir en el intento”

Escenario de la catástrofe

Imaginad que queréis llamar a un script servidor desde Javascript, y que una de las variables que se le pasa vía GET es una URL. Nada del otro mundo:


<a href="http://server.com/script.php?url=' + varUrl + '">

Lo normal y que a más de uno se le habrá ocurrido ya, es escapar la url para no tener problemas. Escapar no es más que convertir los caracteres conflictivos (“:”,”?”,”&”,”/”…) a sus correspondientes representaciones hexadecimales (más sobre escapar en js). Así que haríamos:


url=encodeURIComponent("http://bla.com/index.php?pubid=101852&pag=5");

Con lo que la variable url quedaría:


http%3A%2F%2Fbla.com%2Findex.php%3Fpubid%3D101852%26pag%3D5

Hasta aquí estamos de acuerdo, no hemos descubierto nada nuevo y el tema funcionaría como se espera. Entonces… ¿dónde carajo está la catástrofe?

La catástrofe en sí

No os creáis que con lo de arriba ya se acaba el post, ¡aún falta lo bueno!

La catástrofe nos amenaza el cogote cuando intentamos hacer lo que he comentado arriba, pero abriendo el script servidor que se llama en un Popup. Aaah muchacho, ¡entonces ya la has jodido bien!


<a href="javascript:void(
     window.open('http://server.com/script.php
              ?url=http%3A%2F%2Fbla.com%2Findex.php
              %3Fpubid%3D101852%26pag%3D5', null,''));">

Nota para tiquismiquis: los saltos de línea del código anterior los he metido yo a mano para que no se me descojone la página. Iría todo en una única línea.

Aquí, el window.open() que se cree muy listo coge y te hace por su cuenta y riesgo un unescape de la url que va a abrir en el popup, convirtiéndo los valores hexadecimales a sus caracteres ascii y jodiéndote el chiringuito de paso. Y digo jodiéndote el chiringuito porque cuando cargues las variables GET en tu script servidor adivina que te vas a encontrar:


url=http://www.ejemplo.com/index.php?pubid=101852
pag=5

en vez de esto, que sería lo que debería ser:


url=http://www.ejemplo.com/index.php?pubid=101852&pag=5

¿No os lo acabáis de creer? ¿Queréis seguir pensando que el window.open() es vuestro amigo fiel y no os joderá los ámpersands? Pobres ilusos. Aquí tenéis un ejemplo en vivo y en directo para acabar de hundir vuestras pobres esperanzas. Y que conste que no he podido encontrar que este comportamiento errático y desalmado del window.open() esté documentado en ningún sitio, así que el tema es aún más gracioso.

Salvando el mundo

Como he leído por ahí ([1] y [2]) y mira que me ha costado encontrar referencias; la solución es tan sencilla como doble-escapar los ámpersands, de %26 (su representación HEX normal) a %2526. Esto el browser lo procesa la primera vez y se queda en %26, que es lo que nos interesa, nuestro ámpersand escapado.

Así que al final lo que he acabado haciendo en mi código es lo siguiente:


//encodeURL with ampersand support
function encodeURL(url) {
    return encodeURIComponent(url).replace(/%26/g, "%2526");
}

Trackbacks and Pingbacks

  1. hosthg » Blog Archive » Como evitar que window.open te joda los ámpersands - 31-10-2007

    [...] check the full story here [...]