Ruby CGI перенаправить ответ без ожидания конца сценария - PullRequest
3 голосов
/ 06 мая 2011

Я разрабатываю инструмент обработки видео CGI в ruby ​​и хочу перенаправить пользователя в другое место, нажав кнопку запуска кодирования-запуска-ffmpeg-for-a-hour-long-long.

Вот код:

@cgi.out("status" => "302", "location" => @job.report_url) {''}
@cgi.out{''}
@job.start

Подобные действия хорошо работают с Safari 5.0.5. Но Firefox ждет, пока скрипт завершит свою работу, прежде чем перенаправлять. И если вашему сценарию требуется больше времени для завершения, чем по тайм-ауту Apache, это вполне может никогда не произойти.

Я надеялся на метод cgi.close (). Который существует! Но это метод CGI :: Session и не имеет для меня никакого отношения.

Вот еще один похожий вопрос ... Но не дубликат! Поскольку мне нужно использовать stdin, stdout и stderr после перенаправления: Возвращение ответа с Ruby CGI до завершения сценария?

Итак, как я могу отправить полный CGI-ответ до того, как выполнит некоторые другие задачи с тем же сценарием?

Ответы [ 4 ]

1 голос
/ 10 мая 2011

Ну, наконец-то все поняли.

Но это больше похоже на взлом, чем на реальное решение:

@cgi.out("status" => "303", "Connection" => "close", "Content-Length" => 1, "Location" => @job.report_url) {' '}
@job.start

Есть два ключевых момента, чтобы сделать этоработают, необходимы оба:

  1. Установите для Content-Lenght значение больше 0. 1 Хорошо работает с одним пространством содержимого.
  2. Установите Connection на close.Это неудобно, потому что теоретически это может прекрасно работать в HTTP 1.1 Keep Alive соединении.Но это, кажется, вызывает рендеринг страницы в Firefox 4.

Я перешел на более правильный 303 See Other ответ после запроса POST отправки задания ( HTTP 303 ),Но это не имеет никакого эффекта, оно также хорошо работает с ответом 302.

1 голос
/ 09 мая 2011

Некоторые браузеры (например, Firefox) заполняют буфер перед обработкой данных.

В домашних тестах я добился цели, отправив 4096 пробелов:

@cgi.out("status" => "302", "location" => @job.report_url) { ' ' * 4096 }
@job.start

ОБНОВЛЕНИЕ: Вот мой полный тестовый код:

#!/usr/bin/ruby

require 'cgi'

# change the line below to test; e.g.: buf = ''
buf = ' ' * 4096

cgi = CGI.new
cgi.out('status' => '302', 'location' => 'http://www.example.com') { buf }

sleep 10

puts 'end'

Очевидно, что 'end' никогда не появляется, так как браузер был перенаправлен ранее.

Когда buf пусто, Firefox ждет 10 секунд перед перенаправлением. Когда он «заполнен» (т. Е. 4K пробелов), браузер перенаправляет сразу. Протестировано с Firefox 4.0 в Ubuntu 10.04 и Firefox 4.0.1 в Windows Seven.

1 голос
/ 10 мая 2011

Вместо отправки пустого буфера, попробуйте установить заголовок Content-Length равным 0. Для обработки запроса на отключение должно помочь Kernel # fork.

После небольшого тестирования. Это то, что нужно сделать. Content-Length правильно установлен cgi.out. Вам нужно только передать пустую строку, чтобы установить ее на 0.

Также, как я отмечал в комментарии, закрытие стандартного вывода эффективно закрывает сторону сервера соединений. Я тестировал этот код с lighttpd + ree, с firefox и chrome.

require 'cgi'    
cgi = CGI.new
cgi.out('status' => '302', 'location' => 'http://www.google.com') { "" }
$stdout.close

# here we do a very very long task
sleep 30
exit 0
1 голос
/ 09 мая 2011

Обычный способ решения этой проблемы - разделить приложение на два процесса.

  1. CGI-часть
  2. Обрабатывающая часть

Часто обрабатывающая часть представляет собой отдельный экземпляр приложения, ожидающего сообщения от многочисленных частей cgi.Часть cgi просто отправляет запросы части обработки.Связь может быть осуществлена, как вам нравится, но часто выполняется с использованием очереди заданий / сообщений.

Таким образом, как только задание отправляется в очередь, вы можете перенаправить пользователя, и обрабатывающая часть в итоге получитвозможность перекодировать ваше видео.

Еще одно преимущество заключается в том, что куча одновременных запросов не будет перегружать вашу машину десятками одновременных операций перекодирования.Вы также можете относительно легко переместить обрабатывающую деталь на одну или несколько машин (в зависимости от выбранной вами формы связи) /

Быстрый веб-поиск покажет вам десятки примеров.

...