Si quiero crear una URL usando una variable, tengo dos opciones para codificar la cadena. urlencode()
y rawurlencode()
.
¿Cuáles son exactamente las diferencias y cuál es el preferido?
php
urlencode
url-encoding
Gary Willoughby
fuente
fuente
rawurlencode
. Rara vez se topará con un sistema que se ahoga cuando se dan espacios codificados como%20
, mientras que los sistemas que se ahogan con espacios codificados+
son más comunes.Respuestas:
Dependerá de tu propósito. Si la interoperabilidad con otros sistemas es importante, entonces parece que el código sin procesar es el camino a seguir. La única excepción son los sistemas heredados que esperan que la cadena de consulta siga el estilo de codificación de formulario de espacios codificados como + en lugar de% 20 (en cuyo caso necesita el código urlen).
rawurlencode sigue RFC 1738 antes de PHP 5.3.0 y RFC 3986 después (ver http://us2.php.net/manual/en/function.rawurlencode.php )
Nota sobre RFC 3986 vs 1738. rawurlencode anterior a php 5.3 codificó el carácter tilde (
~
) de acuerdo con RFC 1738. Sin embargo, a partir de PHP 5.3, rawurlencode sigue RFC 3986 que no requiere codificar caracteres tilde.urlencode codifica espacios como signos más (no
%20
como se hace en rawurlencode) (consulte http://us2.php.net/manual/en/function.urlencode.php )Esto corresponde a la definición de aplicación / x-www-form-urlencoded en RFC 1866 .
Lectura adicional:
También puede ver la discusión en http://bytes.com/groups/php/5624-urlencode-vs-rawurlencode .
Además, RFC 2396 merece un vistazo. RFC 2396 define la sintaxis de URI válida. La parte principal que nos interesa es del componente de consulta 3.4:
Como puede ver, el
+
es un carácter reservado en la cadena de consulta y, por lo tanto, debería codificarse según RFC 3986 (como en rawurlencode).fuente
La prueba está en el código fuente de PHP.
Te guiaré a través de un proceso rápido de cómo descubrir este tipo de cosas por tu cuenta en el futuro en cualquier momento que desees. Tenga paciencia conmigo, habrá un montón de código fuente C que puede leer (lo explico). Si desea repasar un poco de C, un buen lugar para comenzar es nuestra wiki de SO .
Descargue la fuente (o use http://lxr.php.net/ para navegar en línea), seleccione todos los archivos para el nombre de la función, encontrará algo como esto:
PHP 5.3.6 (más reciente en el momento de escribir esto) describe las dos funciones en su código nativo de C en el archivo url.c .
RawUrlEncode ()
UrlEncode ()
Bien, entonces, ¿qué hay de diferente aquí?
Ambos esencialmente llaman a dos funciones internas diferentes respectivamente: php_raw_url_encode y php_url_encode
¡Así que ve a buscar esas funciones!
Veamos php_raw_url_encode
Y, por supuesto, php_url_encode:
Un poco de conocimiento rápido antes de avanzar, EBCDIC es otro conjunto de caracteres , similar a ASCII, pero un competidor total. PHP intenta lidiar con ambos. Pero básicamente, esto significa que el byte EBCDIC 0x4c no está
L
en ASCII, en realidad es un<
. Estoy seguro de que ves la confusión aquí.Ambas funciones administran EBCDIC si el servidor web lo ha definido.
Además, ambos usan una matriz de caracteres (piense en el tipo de cadena)
hexchars
para obtener algunos valores, la matriz se describe como tal:Más allá de eso, las funciones son realmente diferentes, y las voy a explicar en ASCII y EBCDIC.
Diferencias en ASCII:
URLENCODE:
+
signo a la cadena de salida.isalnum(c)
), y tampoco es y_
,-
o.
carácter, entonces, enviamos un%
signo a la posición 0 de la matriz, buscamos unahexchars
matriz para buscar unaos_toascii
matriz ( una matriz de Apache que traduce char a código hexadecimal) para la clave dec
(el carácter actual), luego cambiamos bit a la derecha por 4, asignamos ese valor al carácter 1, y a la posición 2 asignamos la misma búsqueda, excepto que preformamos un lógico y para ver si el valor es 15 (0xF), y devolver un 1 en ese caso, o un 0 en caso contrario. Al final, terminarás con algo codificado._-.
caracteres, genera exactamente lo que es.CÓDIGO SIN PROCESAR:
Nota: Muchos programadores probablemente nunca hayan visto un bucle for iterar de esta manera, es algo hackeo y no es la convención estándar utilizada con la mayoría de los bucles for, presta atención, asigna
x
yy
comprueba la salida allen
llegar a 0, e incrementa ambosx
yy
. Lo sé, no es lo que esperarías, pero es un código válido.str
._-.
caracteres, y si no lo es, hacemos casi la misma asignación que con URLENCODE donde realiza búsquedas, sin embargo, incrementamos de manera diferente, usando eny++
lugar deto[1]
, esto es porque el Las cadenas se construyen de diferentes maneras, pero de todos modos alcanzan el mismo objetivo al final.\0
byte.Diferencias:
\0
byte a la cadena, RawUrlEncode sí (esto puede ser un punto discutible)Básicamente iteran de manera diferente, uno asigna un signo + en el caso de ASCII 20.
Diferencias en EBCDIC:
URLENCODE:
0
, con la excepción de ser un.
o-
, O menor queA
pero mayor que char9
, O mayor queZ
y menor quea
pero no a_
. O mayor quez
(sí, EBCDIC es un poco complicado para trabajar). Si coincide con alguno de ellos, realice una búsqueda similar a la que se encuentra en la versión ASCII (simplemente no requiere una búsqueda en os_toascii).CÓDIGO SIN PROCESAR:
z
, se excluye~
de la codificación URL.\0
byte a la cadena antes de regresar.Gran resumen
~
que UrlEncode no lo haga ( este es un problema reportado ). Vale la pena señalar que ASCII y EBCDIC 0x20 son ambos espacios.+
, RawUrlEncode crea un espacio en las%20
búsquedas de matriz.Descargo de responsabilidad: no he tocado C en años, y no he visto EBCDIC en mucho, mucho tiempo. Si me equivoco en alguna parte, avísame.
Implementaciones sugeridas
Basado en todo esto, el código rawurlen es el camino a seguir la mayor parte del tiempo. Como puede ver en la respuesta de Jonathan Fingland, sígalo en la mayoría de los casos. Se trata del esquema moderno para los componentes de URI, donde como urlencode hace las cosas a la antigua usanza, donde + significa "espacio".
Si está tratando de convertir entre el formato anterior y el nuevo, asegúrese de que su código no aumente y convierta algo que es un signo decodificado + en un espacio mediante la doble codificación accidental o escenarios similares de "oops" alrededor de esto espacio / 20% / + tema.
Si está trabajando en un sistema más antiguo con un software más antiguo que no prefiere el nuevo formato, siga con urlencode, sin embargo, creo que% 20 en realidad será compatible con versiones anteriores, ya que según el antiguo estándar% 20 funcionó, simplemente no era privilegiado. Pruébalo si estás dispuesto a jugar, dinos cómo te fue.
Básicamente, debe seguir con raw, a menos que su sistema EBCDIC realmente lo odie. La mayoría de los programadores nunca se encontrarán con EBCDIC en ningún sistema fabricado después del año 2000, tal vez incluso 1990 (eso es difícil, pero aún es probable en mi opinión).
fuente
rendimientos
mientras
rendimientos
La diferencia es el
asd%20asd
vsasd+asd
urlencode difiere de RFC 1738 al codificar espacios como en
+
lugar de%20
fuente
Una razón práctica para elegir uno sobre el otro es si va a utilizar el resultado en otro entorno, por ejemplo, JavaScript.
En PHP
urlencode('test 1')
devuelve'test+1'
mientras querawurlencode('test 1')
devuelve'test%201'
como resultado.Pero si necesita "decodificar" esto en JavaScript utilizando la función decodeURI () , entonces
decodeURI("test+1")
le dará"test+1"
mientras quedecodeURI("test%201")
le dará"test 1"
como resultado.En otras palabras, el espacio ("") codificado por urlencode a más ("+") en PHP no será decodificado correctamente por decodeURI en JavaScript.
En tales casos , se debe utilizar la función PHP rawurlencode .
fuente
json_encode
yJSON.parse
para ese propósito.Creo que los espacios deben codificarse como:
%20
cuando se usa dentro del componente de ruta URL+
cuando se usa dentro del componente de cadena de consulta URL o datos de formulario (consulte 17.13.4 Tipos de contenido de formulario )El siguiente ejemplo muestra el uso correcto de
rawurlencode
yurlencode
:Salida:
¿Qué sucede si codifica la ruta y consulta los componentes de la cadena al revés? Para el siguiente ejemplo:
latest+songs
lugar delatest songs
q
contendrálady gaga
fuente
q
contendrálady gaga
" ¿Qué más contendría de lo contrario? El parámetro de consultaq
parece tener el mismo valor pasado a la$_GET
matriz, independientemente de su usorawurlencode
ourlencode
en PHP 5.2+. Sin embargo,urlencode
codifica en elapplication/x-www-form-urlencoded
formato predeterminado para las solicitudes GET, así que voy con su enfoque. +1+
y%20
están decodificados como espacio cuando se usan en cadenas de consulta.La diferencia está en los valores de retorno, es decir:
urlencode () :
rawurlencode () :
Los dos son muy similares, pero el último (código rawurlen) reemplazará los espacios con un '%' y dos dígitos hexadecimales, lo cual es adecuado para codificar contraseñas o similares, donde un '+' no es, por ejemplo:
fuente
1. ¿Cuáles son exactamente las diferencias y
La única diferencia está en la forma en que se tratan los espacios:
urlencode: basado en la implementación heredada convierte espacios en +
rawurlencode - basado en RFC 1738 traduce espacios a% 20
La razón de la diferencia es porque + es reservado y válido (sin codificar) en las URL.
2. ¿Cuál es el preferido?
Justamente, tengo una estrategia simple que sigo al tomar estas decisiones que compartiré con ustedes con la esperanza de que pueda ayudar.
Creo que fue la especificación HTTP / 1.1 RFC 2616 que pidió " Aplicaciones tolerantes "
Cuando se enfrentan a preguntas como estas, la mejor estrategia es siempre consumir tanto como sea posible y producir lo que cumple con los estándares.
Por lo tanto, mi consejo es usar
rawurlencode
para producir cadenas codificadas RFC 1738 que cumplan con los estándares y usarurldecode
para ser compatibles con versiones anteriores y acomodar todo lo que pueda encontrar para consumir.Ahora puedes tomar mi palabra, pero demostremos que si ...
Parece que PHP tenía exactamente esto en mente, a pesar de que nunca me he encontrado con nadie que rechace ninguno de los dos formatos, no puedo pensar en una mejor estrategia para adoptar como su estrategia de facto, ¿puede?
nJoy!
fuente
fuente
Espacios codificados como
%20
vs.+
La razón más grande que he visto usar
rawurlencode()
en la mayoría de los casos es porqueurlencode
codifica espacios de texto como+
(más signos) donde losrawurlencode
codifica como los comúnmente vistos%20
:He visto específicamente ciertos puntos finales de la API que aceptan consultas de texto codificado que esperan ver
%20
por un espacio y, como resultado, fallan si se usa un signo más en su lugar. Obviamente, esto va a diferir entre las implementaciones de API y su kilometraje puede variar.fuente
Creo que urlencode es para parámetros de consulta, mientras que el rawurlencode es para los segmentos de ruta. Esto se debe principalmente a los
%20
segmentos de ruta frente+
a los parámetros de consulta. Vea esta respuesta que habla sobre los espacios: ¿ Cuándo codificar el espacio a más (+) o% 20?Sin embargo,
%20
ahora también funciona en los parámetros de consulta, por lo que rawurlencode siempre es más seguro. Sin embargo, el signo más tiende a usarse cuando la experiencia del usuario en la edición y la legibilidad de los parámetros de consulta son importantes.Tenga en cuenta que esto significa
rawurldecode
que no se decodifica+
en espacios ( http://au2.php.net/manual/en/function.rawurldecode.php ). Esta es la razón por la $ _GET siempre se pasa automáticamente a travésurldecode
, lo que significa que+
y%20
son decodificados tanto en espacios.Si desea que la codificación y la decodificación sean consistentes entre las entradas y las salidas y ha seleccionado usar siempre
+
y no%20
para los parámetros de consulta, entoncesurlencode
está bien para los parámetros de consulta (clave y valor).La conclusión es:
Segmentos de ruta: siempre use rawurlencode / rawurldecode
Parámetros de consulta: para la decodificación siempre use urldecode (hecho automáticamente), para codificar, tanto rawurlencode como urlencode están bien, solo elija uno para que sea consistente, especialmente al comparar URL.
fuente
simple * rawurlencode la ruta: la ruta es la parte anterior a "?" - los espacios deben codificarse como% 20 * urlencode la cadena de consulta - La cadena de consulta es la parte después de "?" -los espacios están mejor codificados como "+" = rawurlencode es más compatible en general
fuente