Ruby CGI 重定向响应,无需等待脚本结束

发布于 2024-11-05 15:17:37 字数 615 浏览 0 评论 0原文

我正在开发一个 ruby​​ CGI 视频处理工具,并希望在单击 start-ffmpeg-for-an-hour-long-encoding-spree 按钮时将用户重定向到另一个位置。

代码如下:

@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 响应

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

终难愈 2024-11-12 15:17:37

解决此类问题的通常方法是将应用程序分成两个进程。

  1. cgi 部分
  2. 处理部分

通常,处理部分是等待来自众多 cgi 部分的消息的应用程序的单个实例。 cgi部分只是将请求提交给处理部分。可以按照您喜欢的方式进行通信,但通常是使用作业/消息队列来完成。

这样,一旦作业提交到队列,您就可以重定向用户,处理部分最终将开始对您的视频进行转码。

另一个优点是,大量并发请求不会因数十个并发转码操作而使您的计算机过载。您还可以相对轻松地将处理部分移动到一台或多台机器(取决于您选择的通信形式)/

快速 网络搜索将向您展示数十个示例。

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.

睡美人的小仙女 2024-11-12 15:17:37

某些浏览器(如 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 空间)时,浏览器会立即重定向。在 Ubuntu 10.04 中使用 Firefox 4.0 进行测试,在 Windows 7 中使用 Firefox 4.0.1 进行测试。

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.

再可℃爱ぅ一点好了 2024-11-12 15:17:37

好吧,终于明白了。

但它看起来更像是一个黑客而不是一个真正的解决方案:

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

有两个关键的东西让它工作,两者都是必需的:

  1. 设置Content-Lenght大于 0 的值。 1 适用于一个内容空间。
  2. 连接设置为关闭。这很尴尬,因为理论上这在 HTTP 1.1 Keep Alive 连接中可能工作得很好。但这似乎会触发 Firefox 4 中的页面渲染。

在作业提交的 POST 请求之后,我已切换到更正确的 303 See Other 响应(HTTP 303)。但这没有任何效果,它对于 302 响应也能很好地工作。

Well, finally got it.

But it looks more like a hack than a real solution:

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

There are two keys things to make it work, both are needed:

  1. Set Content-Lenght to something greater than 0. 1 Works well with one space of content.
  2. Set Connection to close. This is awkward because this may theoretically works perfectly fine in an HTTP 1.1 Keep Alive connection. But this seems to trigger the page rendering in Firefox 4.

I've switched to a more correct 303 See Other response after the job submission's POST request (HTTP 303). But this has no effect, it works also well with a 302 response.

守望孤独 2024-11-12 15:17:37

不要发送空缓冲区,而是尝试将 Content-Length 标头设置为 0。
对于关闭请求处理,Kernel#fork 应该有所帮助。

经过一些测试。这是需要做的。 Content-Length 由 cgi.out 正确设置。您只需要传递一个空字符串即可将其设置为 0。

另外,正如我在评论中所述,关闭 stdout 可有效关闭连接服务器端。
我用 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

Instead of send an empty buffer, try setting Content-Length header to 0.
For the off request processing, Kernel#fork should help.

After a little bit of testing. This is what is need to be done. Content-Length is set properly by cgi.out. You only need to pass an empty string to set it to 0.

Also, as i stated in a comment, closing stdout effectively close the connection server side.
I tested this code with lighttpd + ree, with firefox and 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文