¿Cuál es la forma correcta de encoding URL de caracteres Unicode?

Conozco el esquema% uxxxx no estándar, pero eso no parece una buena elección ya que el esquema ha sido rechazado por el W3C.

Algunos ejemplos interesantes:

El personaje del corazón Si escribo esto en mi navegador:

http://www.google.com/search?q=♥ 

Luego copie y pegue, veo esta URL

 http://www.google.com/search?q=%E2%99%A5 

lo que hace que parezca que Firefox (o Safari) está haciendo esto.

 urllib.quote_plus(x.encode("latin-1")) '%E2%99%A5' 

lo cual tiene sentido, excepto por las cosas que no se pueden codificar en Latin-1, como el personaje de punto triple.

  

Si escribo la URL

 http://www.google.com/search?q=… 

en mi navegador y luego copiar y pegar, obtengo

 http://www.google.com/search?q=%E2%80%A6 

espalda. Lo cual parece ser el resultado de hacer

 urllib.quote_plus(x.encode("utf-8")) 

lo cual tiene sentido ya que … no se puede codificar con Latin-1.

Pero no está claro para mí cómo el navegador sabe si decodificar con UTF-8 o Latin-1.

Dado que esto parece ser ambiguo:

 In [67]: u"…".encode('utf-8').decode('latin-1') Out[67]: u'\xc3\xa2\xc2\x80\xc2\xa6' 

funciona, así que no sé cómo el navegador se da cuenta de si descifrar eso con UTF-8 o Latin-1.

¿Qué es lo correcto con los personajes especiales con los que tengo que lidiar?

    Yo siempre codificaría en UTF-8. Desde la página de Wikipedia sobre la encoding porcentual :

    La syntax URI genérica exige que los nuevos esquemas URI que proporcionan la representación de datos de caracteres en un URI deben, en efecto, representar caracteres del conjunto sin reservas sin traducción, y deben convertir todos los demás caracteres en bytes de acuerdo con UTF-8, y luego porcentaje de codificar esos valores. Este requisito se introdujo en enero de 2005 con la publicación de RFC 3986 . Los esquemas de URI introducidos antes de esta fecha no se ven afectados.

    Parece que debido a que en el pasado existían otras formas aceptadas de hacer la encoding URL, los navegadores intentan varios métodos de deencoding de un URI, pero si usted es el que hace la encoding, debe usar UTF-8.

    La regla general parece ser que los navegadores codifican respuestas de formulario de acuerdo con el tipo de contenido de la página desde la que se envió el formulario. Se supone que si el servidor nos envía “text / xml; charset = iso-8859-1”, esperan que las respuestas vuelvan a tener el mismo formato.

    Si solo está ingresando una URL en la barra de URL, entonces el navegador no tiene una página base para trabajar y, por lo tanto, solo tiene que adivinar. Entonces, en este caso, parece estar haciendo utf-8 todo el tiempo (ya que ambas entradas produjeron valores de forma de tres octetos).

    La triste verdad es que AFAIK no hay un estándar para qué carácter establecer los valores en una cadena de consulta, o de hecho, cualquier carácter en la URL, debe interpretarse como. Al menos en el caso de valores en la cadena de consulta, no hay ninguna razón para suponer que necesariamente se corresponden con los caracteres.

    Es un problema conocido que tiene que indicarle a su estructura de servidor qué conjunto de caracteres espera que la cadena de consulta se codifique como — por ejemplo, en Tomcat, debe llamar a request.setEncoding () (o algún método similar) antes que usted llama a cualquiera de los métodos request.getParameter (). La escasez de documentación sobre este tema probablemente refleja la falta de conocimiento del problema entre muchos desarrolladores. (Con regularidad pregunto a los entrevistados de Java cuál es la diferencia entre un Reader y un InputStream, y obtengo regularmente miradas en blanco)

    IRI ( RFC 3987 ) es el último estándar que reemplaza los estándares URI / URL ( RFC 3986 y anteriores). URI / URL no admite de forma nativa Unicode (bueno, el RFC 3986 agrega disposiciones para futuros protocolos URI / basados ​​en URL para soportarlo, pero no actualiza los RFC anteriores). El esquema “% uXXXX” es una extensión no estándar para permitir Unicode en algunas situaciones, pero no es universalmente implementado por todos. IRI, por otro lado, es completamente compatible con Unicode, y requiere que el texto se codifique como UTF-8 antes de que se codifique porcentualmente.

    Los IRI no reemplazan los URI, porque solo los URI (efectivamente, ASCII) son permisibles en algunos contextos, incluido HTTP.

    En su lugar, especifica un IRI y se transforma en un URI al salir por el cable.

    La primera pregunta es ¿cuáles son sus necesidades? La encoding UTF-8 es un buen compromiso entre tomar texto creado con un editor barato y soporte para una amplia variedad de idiomas. Con respecto al navegador que identifica la encoding, la respuesta (del servidor web) debe indicarle al navegador la encoding. Sin embargo, la mayoría de los navegadores intentarán adivinar, porque esto falta o está mal en muchos casos. Adivinan al leer una cierta cantidad del flujo de resultados para ver si hay un personaje que no cabe en la encoding predeterminada. Actualmente, todos los navegadores (? No lo he comprobado, pero está muy cerca de la verdad) usan utf-8 como valor predeterminado.

    Así que use utf-8 a menos que tenga una razón convincente para usar uno de los muchos otros esquemas de encoding.