Jinja: urlencode no escapa a las barras

Creado en 20 nov. 2015  ·  21Comentarios  ·  Fuente: pallets/jinja

Esto se generó en # 444, pero este código siempre se evalúa como b'/' en Python 3.4.1, por lo que las barras inclinadas aún no se escapan.

Comentario más útil

Encontré este problema al intentar crear un archivo en un repositorio de gitlab a través de llamadas a la API. La api de gitlab requiere que las barras estén codificadas. Para que esto funcione, hago: {{myvar | urlencode | regex_replace ('/', '% 2F')}}. Estoy trabajando con filtros Ansible y Jinja2 en las tareas de mi libro de jugadas. Esta podría ser una solución para aquellos de ustedes que tengan esto en cuenta, ya que validé que funciona.

Todos 21 comentarios

Solo un aviso @mitsuhiko
No tengo idea de por qué, pero do_urlencode todavía no escapa a las barras, mientras que unicode_urlencode funciona como se esperaba.

Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import jinja2
>>> jinja2.utils.unicode_urlencode("http://url.by", for_qs=True)
'http%3A%2F%2Furl.by'
>>> jinja2.filters.do_urlencode("http://url.by")
'http%3A//url.by'
>>> jinja2.__version__
'2.9.dev'

Porque el filtro urlencode no escapa a las barras. ¿Existe una razón específica por la que tiene que hacerlo? Para aclarar esto: solo codifica barras en la posición del valor de los pares clave / valor pasados.

Creo que este es un comportamiento estándar para la función destinada a codificar URL. Herramientas como http://meyerweb.com/eric/tools/dencoder/ se comportan de esta manera. Además, tengo al menos una herramienta dentro de nuestra empresa que espera que las URL se pasen dentro de las solicitudes GET con barras inclinadas.
Además, no entiendo por qué unicode_urlencode llamado dentro de do_urlencode con for_qs=True .
Puede que entienda algo mal.

Las barras diagonales son caracteres reservados en el componente de ruta y el comportamiento más común es codificar todo, excepto las barras inclinadas allí cuando se fuerza el comportamiento codificado en URL. La alternativa (codificar barras inclinadas a %2f ) ni siquiera tiene sentido, ya que la mayoría de los servidores rechazan directamente esas solicitudes debido a problemas de seguridad, ya que los servidores backend normalmente no pueden distinguir %2f y / en el componente de ruta, ya que operan en octetos decodificados.

Entonces, la única parte en la que una barra tiene sentido en la codificación es en las cadenas de consulta y aquí es donde el codificador basado en dict que tiene urlencode funciona así. Sin embargo, incluso allí una barra inclinada no tiene que codificarse, por lo que no hay razón para forzar su codificación.

La función urlencode debería usarse para la mayoría de las personas de forma predeterminada, por eso no codifica una barra. Si tiene requisitos personalizados, puede anular la función en el registro de su filtro.

Está bien. Gracias Armin.

Hola, tengo el mismo problema con la barra de rechazo, aquí está el código:

jinja2.Template ("{{discos | rechazar ('sameas', '/') | lista}}"). render (disks = ["/", "/ mnt / disk0", "/ mnt / disk1"])
u "['/', '/ mnt / disk0', '/ mnt / disk1']"

Quiero rechazar el disco raíz, pero ya no funciona, ¿cómo solucionarlo?

>>> import jinja2
>>> jinja2.Template("{{ disks|reject('sameas', '/')|list }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
u"['/mnt/disk0', '/mnt/disk1']"
>>> jinja2.__version__
Out[3]: '2.8'

Funciona para mi.

Todavía no me funciona, @ThiefMaster , ¿sería un problema de Python? cuál es la versión de Python que usaste.

    Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import jinja2
    >>> jinja2.Template("{{ disks|reject('sameas', '/')|list }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
    u"['/', '/mnt/disk0', '/mnt/disk1']"
    >>> jinja2.__version__
    '2.8'

Oh .. sameas usa is (y no puedes esperar que 'foo' is 'foo' funcione). Quieres equalto que usa == .

Sí, funciona, no soy de la familia de Jinja2. Gracias, @ThiefMaster

Entonces, la única parte en la que una barra tiene sentido en la codificación es en las cadenas de consulta y aquí es donde el codificador basado en dict que tiene urlencode funciona así. Sin embargo, incluso allí una barra inclinada no tiene que codificarse, por lo que no hay razón para forzar su codificación.

No, por ejemplo, también debe codificar / en nombres de usuario y contraseñas.
Es la razón por la que JS tiene encodeURI __ y__ encodeURIComponent .

Eso es bastante justo, pero en la práctica tampoco es necesario allí y las credenciales incluidas están obsoletas de todos modos. Dado que es poco probable que se produzcan dentro de las plantillas, es un caso marginal que realmente no vale la pena considerar.

Ansible usa Jinja, y es bastante común manejar credenciales de seguridad al configurar sistemas. Acabo de encontrar un caso en el que una contraseña generada automáticamente contenía una barra que no fue reemplazada por urlencode para generar una URL de base de datos, lo cual es bastante desafortunado. Si bien romper el comportamiento actual sería problemático, ¿por qué no introducir un segundo filtro que escape a las barras?

Ansible podría hacer eso. No es necesario que dicho cambio esté en Jinja, es lo suficientemente extensible como para agregar filtros personalizados o incluso reemplazar los integrados.

@ThiefMaster ¿Son los casos de uso distintos de la construcción de plantillas HTML irrelevantes a la hora de determinar qué es útil incluir en el propio Jinja? Por ejemplo, el proyecto Saltstack, con un propósito similar al de Ansible, también usa Jinja para crear plantillas y se beneficiaría del mismo cambio.

@danielkza, ¿qué impide que saltstack proporcione un filtro que haga eso?

@mitsuhiko ¿Por qué Jinja incluye filtros integrados entonces? Solo puedo suponer que es porque son útiles en múltiples casos de uso. Usé Ansible y Salt como dos ejemplos de dónde se desea poder escapar de las barras inclinadas en las URL y, por lo tanto, sería valioso tenerlo disponible para todos.

¿Qué hay de agregar un argumento safe a urlencode , como lo ha hecho el urllib.url_quote Python, de modo que se conserven las barras diagonales predeterminadas, pero de una manera que se pueda anular fácilmente?

Jinja intenta proporcionar algunas funciones de uso común. Tenemos dos modos de codificación urlen que lo llevan al 95%. Puede codificar cadenas de consulta completas codificando un dict y puede codificar en un conjunto común que sea válido para rutas a través de urlencode en cadenas.

No hacemos nada más que utf-8 o eso. Porque, ¿dónde se detendría? Hay demasiadas partes de una URL, hay iris y todas tienen sus propios problemas. Cuando estamos allí, ¿por qué no proporcionar también un codificador punycode para el netloc?

Encontré este problema al intentar crear un archivo en un repositorio de gitlab a través de llamadas a la API. La api de gitlab requiere que las barras estén codificadas. Para que esto funcione, hago: {{myvar | urlencode | regex_replace ('/', '% 2F')}}. Estoy trabajando con filtros Ansible y Jinja2 en las tareas de mi libro de jugadas. Esta podría ser una solución para aquellos de ustedes que tengan esto en cuenta, ya que validé que funciona.

Veo cierto debate sobre qué caracteres deben codificarse en porcentaje, según tengo entendido, esto se trata actualmente en RFC3986. https://tools.ietf.org/html/rfc3986#section -2.2

Aunque para mi caso de uso, @ahuffman ha proporcionado una

Quiero cerrar esto porque volvió a surgir. Mis argumentos en contra de tener esto ya estaban aquí antes, pero quiero reiterarlos porque en realidad hay un PR abierto actualmente (# 864) que propone agregar otro filtro para ayudar a la API de GitLab.

La API de GitLab se rompe si se coloca detrás de todo tipo de configuraciones de proxy y hay problemas abiertos para ello ( Problema de ejemplo ). En cambio, propondría documentar una solución alternativa y por qué la gente no debería hacerlo.

La solución alternativa de ejemplo podría ser la siguiente:

{{ value|urlencode|replace("/", "%2f") }}

Es un poco tomar una postura, pero hacerlo puede alentar a las personas a no repetir los errores de otros que les precedieron.

¿Fue útil esta página
0 / 5 - 0 calificaciones