(Atualizado porque percebi que estava tentando consertar isso, então fiquei confuso com o problema original e o problema que me fez desistir)
Estou fazendo uma solicitação em partes para um aplicativo que usa Werkzeug (git master atual). get_input_stream acaba chamando LimitedStream(wsgi.input, min(content_length, max_content_length))
. min(content_length, max_content_length)
sempre será Nenhum se usar codificação em partes.
Em uma tentativa de progredir, tentei usar LimitedStream(stream, content_length or max_content_length)
, mas acabei obtendo uma exceção ClientDisconnected
, porque não podemos dizer a diferença entre a desconexão de um cliente e a solicitação em partes simplesmente realizada , como wsgi.input.read()
apenas retorna uma string de comprimento 0 em ambos os casos.
Isso é mais do que um simples bug com min
. Depois de consertar isso, o problema é que fazer wsgi.input.read(max_content_length)
com blocos de Werkzeug para sempre se houver menos de max_content_length
para ler. Ou usando Gunicorn, que oferece suporte a fragmentos analisando e armazenando em buffer a mensagem inteira, o comprimento sai para menos de max_content_length
, então LimitedStream
pensa que o cliente desconectou.
Eu testei isso no Django apenas para ter certeza de que não estamos fazendo algo estranho, ele vê um fluxo vazio também.
A maneira mais simples de avançar é fornecer um middleware que configure environ['wsgi.input_terminated']
e dizer às pessoas para usá-lo quando usarem um servidor que suporte transferência em partes.
Qual wsgi suporta atualmente input_terminated
? Depois de queimar o dia todo na depuração de porque os dados estão vazios, então porque o stream está vazio e então perceber que é devido à codificação de stream em partes, agora não consigo encontrar nada que suporte isto: /
Além de verificar environ.get('wsgi.input_terminated')
, devemos também verificar environ.get('HTTP_TRANSFER_ENCODING') == 'chunked'
e, nesse caso, também retornar o fluxo não empacotado diretamente? Isso corrige problemas como um simples curl -H 'Transfer-Encoding: chunked' ...
retornando um fluxo vazio.
Por RFC2616
4.4.2
Se um campo de cabeçalho Transfer-Encoding (seção 14.41) estiver presente e
tem qualquer valor diferente de "identidade", então o comprimento da transferência é
definido pelo uso da codificação de transferência "fragmentada" (seção 3.6),
a menos que a mensagem seja encerrada com o fechamento da conexão.
4.4.3
Se um campo de cabeçalho Content-Length (seção 14.13) estiver presente, seu
valor decimal em OCTETs representa o comprimento da entidade e o
comprimento de transferência. O campo de cabeçalho Content-Length NÃO DEVE ser enviado
se esses dois comprimentos forem diferentes (ou seja, se um Transfer-Encoding
campo de cabeçalho está presente). Se uma mensagem for recebida com um
Campo de cabeçalho Transfer-Encoding e campo de cabeçalho Content-Length,
o último DEVE ser ignorado.
... observando que Transfer-Encoding
de chunked
exige que qualquer cabeçalho Content-Length
seja ignorado e, portanto, nenhum processamento de fluxo deve ser feito com base nele. Este é o caso atualmente, a menos que wsgi.input_terminated
seja definido.
Deve realmente ser necessário definir wsgi.input_terminated
para que a codificação normal em partes, por exemplo, de uma carga útil JSON de 10 bytes, funcione?
Comentários muito úteis
Qual wsgi suporta atualmente
input_terminated
? Depois de queimar o dia todo na depuração de porque os dados estão vazios, então porque o stream está vazio e então perceber que é devido à codificação de stream em partes, agora não consigo encontrar nada que suporte isto: /