Ruby CGI 重定向响应,无需等待脚本结束
我正在开发一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
解决此类问题的通常方法是将应用程序分成两个进程。
通常,处理部分是等待来自众多 cgi 部分的消息的应用程序的单个实例。 cgi部分只是将请求提交给处理部分。可以按照您喜欢的方式进行通信,但通常是使用作业/消息队列来完成。
这样,一旦作业提交到队列,您就可以重定向用户,处理部分最终将开始对您的视频进行转码。
另一个优点是,大量并发请求不会因数十个并发转码操作而使您的计算机过载。您还可以相对轻松地将处理部分移动到一台或多台机器(取决于您选择的通信形式)/
快速 网络搜索将向您展示数十个示例。
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.
某些浏览器(如 Firefox)会在处理数据之前填充缓冲区。
在家庭测试中,我通过发送 4096 个空格来实现这一点:
更新:这是我的完整测试代码:
显然,
'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:
UPDATE: Here is my complete test code:
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.好吧,终于明白了。
但它看起来更像是一个黑客而不是一个真正的解决方案:
有两个关键的东西让它工作,两者都是必需的:
Content-Lenght
大于 0 的值。 1 适用于一个内容空间。连接
设置为关闭
。这很尴尬,因为理论上这在 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:
There are two keys things to make it work, both are needed:
Content-Lenght
to something greater than 0. 1 Works well with one space of content.Connection
toclose
. 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.不要发送空缓冲区,而是尝试将 Content-Length 标头设置为 0。
对于关闭请求处理,Kernel#fork 应该有所帮助。
经过一些测试。这是需要做的。 Content-Length 由 cgi.out 正确设置。您只需要传递一个空字符串即可将其设置为 0。
另外,正如我在评论中所述,关闭 stdout 可有效关闭连接服务器端。
我用 lighttpd + ree、firefox 和 chrome 测试了这段代码。
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.