Jinja: urlencode não escapa de barras

Criado em 20 nov. 2015  ·  21Comentários  ·  Fonte: pallets/jinja

Isso foi gerado em # 444, mas esse código sempre avalia como b'/' no Python 3.4.1, portanto, as barras ainda não escaparam.

Comentários muito úteis

Eu encontrei esse problema ao tentar criar um arquivo em um repositório gitlab por meio de chamadas de API. A API gitlab requer que as barras sejam codificadas. Para fazer este trabalho eu faço: {{myvar | urlencode | regex_replace ('/', '% 2F')}}. Estou trabalhando com os filtros Ansible e Jinja2 em minhas tarefas de manual. Isso pode ser uma solução alternativa para aqueles de vocês que estão acertando isso, pois eu validei que funciona.

Todos 21 comentários

Apenas um aviso @mitsuhiko
Não tenho ideia do porquê, mas do_urlencode ainda não escapa das barras, enquanto unicode_urlencode funciona como esperado.

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 o filtro urlencode não escapa das barras. Existe uma razão específica para isso? Para esclarecer isso: ele apenas codifica barras na posição do valor dos pares chave / valor passados.

Acredito que esse seja o comportamento padrão para funções destinadas à codificação de urls. Ferramentas como http://meyerweb.com/eric/tools/dencoder/ se comportam dessa maneira. Além disso, tenho pelo menos uma ferramenta dentro de nossa empresa que espera URLs sendo passados ​​dentro de solicitações GET com barras de escape.
Além disso, não entendo por que unicode_urlencode chamou dentro de do_urlencode com for_qs=True .
Pode ser que eu entenda algo errado.

As barras são caracteres reservados no componente de caminho e o comportamento mais comum é codificar tudo, exceto as barras, ao forçar as coisas para o comportamento de codificação de URL. A alternativa (codificar barras para %2f ) nem mesmo faz sentido, já que a maioria dos servidores rejeita completamente essas solicitações devido a problemas de segurança, pois os servidores de back-end normalmente não conseguem distinguir %2f e / em o componente de caminho à medida que operam em octetos decodificados.

Portanto, a única parte em que uma barra realmente faz sentido na codificação é em strings de consulta e é aqui que o codificador baseado em dict que urlencode tem funciona assim. No entanto, mesmo lá, uma barra não precisa ser codificada, portanto, não há razão para forçá-la a ser codificada.

A função urlencode deve ser usada pela maioria das pessoas por padrão, por isso ela não codifica uma barra. Se você tiver requisitos personalizados, poderá substituir a função no registro do filtro.

OK. Obrigado Armin.

Olá, tenho o mesmo problema com a rejeição de barra. Aqui está o código:

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

Eu quero rejeitar o disco raiz, mas não funciona mais, como resolver isso?

>>> 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 mim.

Ainda não funciona para mim, @ThiefMaster .

    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 (e você não pode esperar que 'foo' is 'foo' funcione). Você quer equalto que usa == .

Sim, funciona, não sou da família com Jinja2. Obrigado, @ThiefMaster

Portanto, a única parte em que uma barra realmente faz sentido na codificação é nas strings de consulta e é aqui que o codificador baseado em dict que o urlencode tem funciona assim. No entanto, mesmo lá, uma barra não precisa ser codificada, portanto, não há razão para forçá-la a ser codificada.

Não, por exemplo, você precisa codificar / em nomes de usuário e senhas também.
É a razão pela qual JS tem encodeURI __and__ encodeURIComponent .

Isso é justo, mas na prática também não é necessário e as credenciais incluídas estão obsoletas de qualquer maneira. Como é improvável que sejam produzidos dentro de modelos, é um caso extremo que realmente não vale a pena considerar.

Ansible usa Jinja, e é muito comum lidar com credenciais de segurança ao configurar sistemas. Acabei de chegar a um caso em que uma senha gerada automaticamente continha uma barra que não foi substituída por urlencode para gerar uma URL de banco de dados, o que é bastante lamentável. Embora quebrar o comportamento atual seja problemático, por que não introduzir um segundo filtro que escape das barras?

Ansible poderia fazer isso. Não há necessidade de tal mudança estar no próprio Jinja - é extensível o suficiente para adicionar filtros personalizados ou até mesmo substituir os embutidos.

@ThiefMaster Os casos de uso, além da construção de modelos HTML, são irrelevantes para determinar o que é útil incluir no próprio Jinja? Por exemplo, o projeto Saltstack, com finalidade semelhante ao Ansible, também usa Jinja para modelagem e se beneficiaria da mesma mudança.

@danielkza, o que impede que o saltstack forneça um filtro que faça isso?

@mitsuhiko Por que Jinja inclui algum filtro embutido então? Só posso supor que é porque eles são úteis em vários casos de uso. Usei Ansible e Salt como dois exemplos de onde é desejável poder escapar de barras em URLs e, portanto, seria valioso tê-lo disponível para todos.

Que tal adicionar um argumento safe a urlencode , como fez o urllib.url_quote do Python, de forma que por padrão as barras sejam preservadas, mas de uma forma que possa ser facilmente substituída?

Jinja tenta fornecer alguma funcionalidade comumente usada. Temos dois modos de urlencoding, o que leva você a cerca de 95% lá. Você pode codificar querystrings inteiras codificando um dicionário e você pode codificar para um conjunto comum que é válido para caminhos através de urlencode em strings.

Não fazemos nada além de utf-8 ou isso. Porque onde isso iria parar. Há muitas partes de um url, há íris e todas têm suas próprias dobras. Quando estamos lá, por que não apenas fornecer um codificador punycode para o netloc?

Eu encontrei esse problema ao tentar criar um arquivo em um repositório gitlab por meio de chamadas de API. A API gitlab requer que as barras sejam codificadas. Para fazer este trabalho eu faço: {{myvar | urlencode | regex_replace ('/', '% 2F')}}. Estou trabalhando com os filtros Ansible e Jinja2 em minhas tarefas de manual. Isso pode ser uma solução alternativa para aqueles de vocês que estão acertando isso, pois eu validei que funciona.

Vejo alguns debates sobre quais caracteres devem ser codificados por cento, no meu entendimento, isso está atualmente coberto no RFC3986. https://tools.ietf.org/html/rfc3986#section -2.2

Embora, para meu caso de uso, @ahuffman tenha fornecido uma

Quero encerrar porque surgiu novamente. Meus argumentos contra isso já foram levantados aqui anteriormente, mas quero reiterá-los porque na verdade há um PR aberto atualmente (# 864) que propõe adicionar outro filtro para ajudar a API do GitLab.

API do GitLab quebrada se colocada atrás de todos os tipos de configurações de proxy e há questões abertas para ela ( problema de exemplo ). Em vez disso, eu proporia documentar uma solução alternativa e por que as pessoas não deveriam fazê-lo.

Um exemplo de solução alternativa poderia ser este:

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

Isso é um pouco assumir uma posição, mas fazer isso pode encorajar as pessoas a não repetir os erros dos outros que vieram antes delas.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

Yannik picture Yannik  ·  4Comentários

guettli picture guettli  ·  5Comentários

humiaozuzu picture humiaozuzu  ·  3Comentários

mitsuhiko picture mitsuhiko  ·  3Comentários

dwt picture dwt  ·  3Comentários