Preservar dados em buffer após uma resposta HTTP CONNECT
Evite um handshake HTTP CONNECT travado encontrando o limite dos cabeçalhos da resposta e preservando os bytes que chegam depois dele.
Um pequeno wrapper de proxy pode funcionar para HTTPS e depois travar quando reutilizado para um protocolo cujo servidor fala primeiro. A linha suspeita costuma ser a que espera que o buffer de receção termine com \r\n\r\n.
O TCP entrega ao cliente um fluxo. Uma chamada de receção pode devolver metade de uma linha de estado HTTP, uma resposta CONNECT completa, ou essa resposta imediatamente seguida de dados de túnel. Não há promessa de que uma leitura pare no fim dos cabeçalhos.
Encontrar o limite dentro do buffer
Para uma troca HTTP/1.1 CONNECT, acumule bytes até o terminador de cabeçalhos aparecer em qualquer ponto do buffer. Divida na sua primeira ocorrência. Analise a linha de estado e os cabeçalhos da primeira parte; guarde separadamente tudo o que vem depois do limite. Aplique um limite de tamanho de cabeçalhos e um tempo limite durante a espera, e trate uma leitura vazia do socket como uma ligação fechada em vez de outro convite a repetir o ciclo.
Uma resposta 2xx final bem-sucedida coloca a ligação em modo de túnel imediatamente após esses cabeçalhos. Os bytes que a seguem já são bytes de túnel. Não os descarte, não espere por um corpo de resposta CONNECT, e não interprete um campo Content-Length como autorização para consumir parte do novo protocolo. As respostas informativas, se existirem, têm de ser tratadas antes dessa resposta final.
O wrapper tem de entregar os seus restos
Devolver apenas o socket subjacente perde os bytes que o analisador do handshake já retirou dele. O leitor seguinte precisa de um fluxo com buffer que devolva primeiro a cauda guardada e depois retome as leituras do socket. Para um protocolo em que o servidor fala primeiro, perder essa saudação inicial pode deixar ambos os lados à espera indefinidamente.
Inversamente, os bytes de uma resposta CONNECT falhada não são uma saudação de túnel. Um 407 continua a pertencer à troca com o proxy e exige tratamento de autenticação; outro estado sem sucesso exige um caminho de erro apropriado.
Isto é especialmente importante ao adaptar um cliente FTP ou SSH através de um proxy HTTP. O proxy também tem de permitir a porta de destino pedida, e o FTP pode precisar de ligações de dados adicionais. Uma análise correta dos cabeçalhos resolve a entrega do fluxo; não pode conceder autorização CONNECT nem fornecer o segundo canal do FTP.