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?
The usual way to approach this kind of problem is to seperate the application into two processes.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With