开发者

Ruby CGI Stream Audio

开发者 https://www.devze.com 2022-12-08 16:31 出处:网络
What I want to do is use a CGI script (written in Ruby) to read a binary file off of the filesystem (audio, specifically) and stream it to the browser.

What I want to do is use a CGI script (written in Ruby) to read a binary file off of the filesystem (audio, specifically) and stream it to the browser.

This is how I am doing that so far,

require 'config'

ENV['REQUEST_URI'] =~ /\?(.*)$/
f= $config[:mdir] + '/' + $1.url_decode
f = File.open f, 'rb'

print "Content-Type: audio/mpeg\r\n"#TODO: Make it guess mime type
print "\r\n"

#Outputs file
while b开发者_如何学Clk = f.read(4096)
    $stdout.puts blk
    $stdout.flush
end

f.close

It's not perfect, there are security holes (exposing the whole filesystem..), but it just isn't working right. It's reading the right file, and as far as I can tell, outputting it in 4k blocks like it should. Using Safari, if I go to the URL, it will show a question mark on the audio player. If I use wget to download it, it appears to work and is about the right size, but is corrupted. It begins playing fine, then crackles, and then stops.

How should I go about doing this? Do I need to Base-64 encode, if can I do that without loading the whole file into memory in one go?

Btw, this is only going to be used over local area network, and I want easy setup, so I'm not interested in a dedicated streaming server.


You could just use IO#print instead of IO#puts but this has some disadvantages.

Don't do the file handling in ruby

Ruby is not good in doing stupid tasks very fast. With this code, you will probably not be able to fill your bandwith.

No CGI

All you want to do is expose a part of the filestystem via http, here are some options on how to do it

  • Set your document root to the folder you want to expose.
  • Make a symlink to the folder you want to expose.
  • Write some kind of rule in your webserver config to map certain url's to a folder

Use any of these and the http server will do for you what you want.

X-Sendfile

Some http servers honor a special header called X-Sendfile. If you do

print "X-Sendfile: #{file}"

the server will use the specified file as body. In lighty this works only through fastcgi, so you would need a fastcgi wrapper like: http://cgit.stbuehler.de/gitosis/fcgi-cgi/ . I don't know about apache and others.

Use a c extension

C extensions are good at doing stupid tasks fast. I wrote a c extension which does nothing, but reading from one IO and writing it to another IO. With this c extension you can fill a GIGABIT Lan through ruby: git://johannes.krude.de/io2io

Use it like this:

IO2IO.do(file, STDOUT)


puts is for writing "lines" of "text", and therefore appends a newline to whatever you give it (turning your mpegs into garbage). You want syswrite.

0

精彩评论

暂无评论...
验证码 换一张
取 消