Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Ruby IO multiplexer
# MultIO Ruby IO multiplexer
# http://rcrowley.org/2010/07/27/multio-ruby-io-multiplexer.html
require 'stringio'
class MultIO < Array
def <<(io)
if io.respond_to?(:to_str)
io = StringIO.new(io)
end
super io
end
def read(length=nil)
@i ||= 0
data = ""
while (!length || data.length < length) && @i < self.length
data << self[@i].read(length - data.length)
@i += 1 if self[@i].eof?
end
"" == data && eof? ? nil : data
end
def eof?
@i >= self.size
end
alias :eof :eof?
def size
inject(0) do |sum, io|
case io
when StringIO
sum + io.size
when File
sum + io.stat.size
else
raise IOError, "Can't find size of #{io.class}"
end
end
end
end
require 'base64'
require 'multio'
require 'net/http'
require 'openssl'
require 'pp'
require 'uri'
boundary = Base64.encode64(OpenSSL::Random.random_bytes(48)).gsub("\n", "")
multio = MultIO.new
multio << "--#{boundary}\r\n"
multio << "Content-Disposition: form-data; name=\"thing\"\r\n\r\n"
multio << "stuff\r\n"
multio << "--#{boundary}\r\n"
multio << "Content-Disposition: form-data; name=\"file\"; filename=\"#{File.basename(ARGV[0])}\"\r\n"
multio << "Content-Type: application/octet-stream\r\n"
multio << "Content-Length: #{File.size(ARGV[0])}\r\n\r\n"
multio << File.open(ARGV[0], "r")
multio << "--#{boundary}--\r\n"
uri = URI.parse("http://example.com/")
http = Net::HTTP.start(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.path)
request["Content-Type"] = "multipart/form-data; boundary=\"#{boundary}\""
request["Content-Length"] = multio.size
request.body_stream = multio
response = http.request(request)
http.finish
puts response.code
pp response.to_hash
puts response.body
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment