nginx proxy_pass, corrompendo o arquivo pdf quando passado de volta?

1

Eu tenho um problema muito chato, enquanto os PDFs que estou tentando baixar do site ficam corrompidos. Eles são gerados bem (eu posso ver que se eu baixá-lo via SFTP da pasta temp eles são colocados).

    location ~ \.cgi$ {
        #try_files $uri =404;
        gzip off;
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8181;
    }

O código Perl é bastante simples (não vou me incomodar em colocar o código de geração de PDF também, pois isso está funcionando bem);

my $filepath = qq|/home/fatpeter/web/site.com/cgi-bin/hotels/admin/tmp_pdf/| . CORE::time() . q|.pdf|;

$pdf->to_file($filepath);

$file_name =~ s/\-/_/sig;
my $size = -s $filepath;

my $file = \do { local *FH; *FH };
open $file, "<$filepath" or die "Unable to open file '$filepath': $!";
binmode $file;
binmode STDOUT;

print $IN->header($IN->file_headers(
    filename => $file_name,
    mimetype => 'application/pdf',
    inline   => 0,
    size     => $size
));

{
    local $\;
    while (read($file, my $chunk, 4096)) {
        print $chunk;
    }
}

Então, basicamente, o nginx passa a requisição para o Apache2.4, então o Perl roda e cria o PDF. O script então passa o PDF de volta para eles.

[Tue Apr 25 13:41:36.810922 2017] [:error] [pid 2901] :Apache2 IO write: (104) Connection reset by peer at /home/fatpeter/web/site.com/cgi-bin/hotels/invoices.cgi line 285

A linha 285 é o loop while () { } :

    while (read($file, my $chunk, 4096)) {

Não sei por que ele seria interrompido antes de ser baixado. Alguma ideia? Para que vale a pena, o arquivo de teste que estou usando está em 363 KB (372.596 bytes), então não é exatamente enorme! Minhas configurações de proxy no arquivo principal nginx.conf são:

proxy_redirect off; proxy_set_header Host $ host; proxy_set_header X-Real-IP $ remote_addr; proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for; proxy_pass_header Set-Cookie; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffers 32 4k;

Isso é o que o script está enviando como cabeçalhos:

Content-type: application/pdf
Content-Disposition: attachment; filename="foo.pdf"; size=372596
Content-Length: 372596

UPDATE: Curiosamente, agora recebo esta mensagem de erro no Firefox quando faço o download:

C:\Users\Andy\AppData\Local\Temp\Jy4tj5pr.pdf.part could not be saved, because the source file could not be read.

Try again later, or contact the server administrator.

Eu também agora recebo isso no log de acesso:

127.0.0.1 - - [25/Apr/2017:15:29:38 +0000] "GET /cgi-bin/hotels/invoices.cgi?action=download;id=60d90acf677e9c81;invoice=1055;t=french HTTP/1.0" 200 372861 "https://www.example.com/cgi-bin/hotels/invoices.cgi?t=french" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"
81.174.134.133 - - [25/Apr/2017:15:29:38 +0000] "GET /cgi-bin/hotels/invoices.cgi?action=download;id=60d90acf677e9c81;invoice=1055;t=french HTTP/2.0" 200 372616 "https://www.example.com/cgi-bin/hotels/invoices.cgi?t=french" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"

UPDATE 3: OK, estou chegando um pouco mais perto daqui. O problema parece ser com o "chunking" no script:

while (read($file, my $chunk, 4096)) {

Se eu mudar isso para, por exemplo:

while (read($file, my $chunk, 409600)) {

(maior que o tamanho do arquivo em questão), FUNCIONA ! O problema com isso, porém, é o que eu faço com arquivos maiores?

Então aqui está o código de trabalho:

{
    local $\;
    while (read($file, my $chunk, -s $filepath)) {
        print $chunk;
    }
}

Eu simplesmente não gosto da ideia de não ser capaz de mandar de volta em blocos. Existe alguma desvantagem em fazer isso dessa maneira?

    
por Andrew Newby 25.04.2017 / 15:57

0 respostas