Как заставить современные браузеры отображать строки по мере их поступления
В первые дни веб-браузеров и серверов было возможно создавать сценарии, которые отправляли бы данные в браузер, и браузер отображал их по мере их поступления.
Например, традиционный тестовый скрипт NPH:
#!/usr/local/bin/perl
$server_protocol = $ENV{'SERVER_PROTOCOL'};
$server_software = $ENV{'SERVER_SOFTWARE'};
$|=1;
print "$server_protocol 200 OK", "\n";
print "Server: $server_software", "\n";
print "Content-type: text/plain", "\n\n";
print "OK, Here I go. I am going to count from 1 to 5 !", "\n";
for ($loop=1; $loop <= 5; $loop++) {
print $loop, "\n";
sleep (2);
}
print "All Done!", "\n";
exit (0);
В старые времена Netscape браузер отображал 1, 2, 3, 4, 5, когда они появлялись с 2 секундами между ними.
В современном браузере, таком как Chrome, вы ничего не видите, пока скрипт не завершится и все 5 строк будут отображаться за один раз.
Я вижу, что скрипт работает так, как ожидал telnet
вход на сервер и запуск руководства GET
команда; вывод принимается каждые 2 секунды.
Есть ли какой-либо способ сказать современным браузерам (возможно, через заголовки?) Действовать по-старому и отображать строку по мере ее поступления?
1 ответ
Оказывается, работает чанкованный режим... но вам нужно сначала отправить кучу данных, прежде чем браузер начнет потоковую передачу.
Это описывает данные предварительной порции, определенные посредством тестирования:
Таким образом, полученный код будет выглядеть примерно так:
#!/usr/local/bin/perl
$server_protocol = $ENV{'SERVER_PROTOCOL'};
$server_software = $ENV{'SERVER_SOFTWARE'};
$|=1;
print "$server_protocol 200 OK", "\n";
print "Server: $server_software", "\n";
print "Transfer-Encoding: chunked", "\n";
print "Content-type: text/plain", "\n\n";
sub chunk {
my ($chunk)=@_;
printf("%x\n%s\n", length($chunk), $chunk);
}
# Send 1K of spaces to convince browsers to display data as it comes
chunk(" " x 1024);
chunk("OK, Here I go. I am going to count from 1 to 5 !\r\n");
for ($loop=1; $loop <= 5; $loop++) {
chunk($loop . "\r\n");
sleep (2);
}
chunk("All Done!\r\n");
# We need this to tell the client chunking has ended
chunk("");
(Спасибо не-SO пользователю за помощь в этом)