Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby CGI redirect response without waiting end of script

I am developing a ruby CGI video processing tool and want to redirect the user to another location upon click on the start-ffmpeg-for-an-hour-long-encoding-spree button.

Here is the code:

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

Doing like this works fine with Safari 5.0.5. But Firefox waits for the script to finish his work before redirecting. And, if your script takes longer to finish than Apache's timeout, it may well be never happening.

I was hoping for a kinf of cgi.close() method. Which exists! But is a CGI::Session method and has nothing to do for me.

Here is another similar question... But not a duplicate! As i need to use stdin, stdout and stderr after the redirect: Returning a response with Ruby CGI before script is finished?

So, how can i send a full CGI response before doing some other tasks with the same script?

like image 862
Arko Avatar asked Mar 11 '26 12:03

Arko


2 Answers

The usual way to approach this kind of problem is to seperate the application into two processes.

  1. The cgi part
  2. The processing part

Often the processing part is a single instance of an application waiting for messages from numerous cgi parts. The cgi part just submits requests to the processing part. The communication can be done however you like, but is often done using a job/message queue.

This way as soon as the job is submitted to the queue you can redirect the user and the processing part will eventually get around to transcoding your video.

Another advantage is that a heap of simultaneous requests will not overload your machine with dozens of concurrent transcoding operations. You can also move the processing part to one or more machines relatively easily (depending on the form of communication you choose)/

A quick web search will show you dozens of examples.

like image 113
Michael Anderson Avatar answered Mar 13 '26 10:03

Michael Anderson


Some browsers (like Firefox) fill a buffer before processing data.

In home tests, I did the trick by sending 4096 spaces:

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

UPDATE: Here is my complete test code:

#!/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'

Obviously, the 'end' never appears, as browser has been redirected before.

When buf is empty, Firefox waits for 10s before redirect. When it's "full" (ie, 4K of spaces), the browser redirects immediately. Tested with Firefox 4.0 in Ubuntu 10.04, and Firefox 4.0.1 in Windows Seven.

like image 42
Sony Santos Avatar answered Mar 13 '26 11:03

Sony Santos