Skip to content

Instantly share code, notes, and snippets.

@epitron
Created May 30, 2013 03:46
Show Gist options
  • Save epitron/92bf23bfceaf07e5da66 to your computer and use it in GitHub Desktop.
Save epitron/92bf23bfceaf07e5da66 to your computer and use it in GitHub Desktop.
A class that emulates a File object, but over HTTP.
require 'net/http'
require 'uri'
module URI
def ssl?; scheme == 'https'; end
end
class WebFile
def self.open(url)
connection = new(url)
if block_given?
yield connection
connection.close
else
connection
end
end
def initialize(url)
@uri = URI(url)
@pos = nil
end
def ensure_connected
return if @read_thread
http = Net::HTTP.start(@uri.host, @uri.port, use_ssl: @uri.ssl?)
@r, @w = IO.pipe
@read_thread = Thread.new do
http.request(Net::HTTP::Get.new @uri.request_uri) do |response|
response.read_body do |chunk|
@w.write chunk
puts "HTTP got #{chunk.size} bytes"
break if Thread.current[:terminate]
end
puts "done!"
break
end
end
end
def read(*args)
ensure_connected
@r.read(*args)
end
def disconnect
if @read_thread
@read_thread[:terminate] = true
@read_thread.join
puts "Thread died"
@read_thread = nil
else
raise "Not connected"
end
end
def close
disconnect
end
def seek(pos)
@pos = pos
end
end
if __FILE__ == $0
WebFile.open('http://chris.ill-logic.com/files/arms-normalized.txt') do |conn|
5.times do
data = conn.read(40)
puts "read #{data.size} bytes"
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment