lib/tap/http/utils.rb in tap-http-0.3.1 vs lib/tap/http/utils.rb in tap-http-0.3.2
- old
+ new
@@ -1,8 +1,9 @@
autoload(:WEBrick, 'webrick')
autoload(:Zlib, 'zlib')
autoload(:StringIO, 'stringio')
+require 'rack'
module Tap
module Http
module Utils
module_function
@@ -135,14 +136,15 @@
params = {}
request.params.each_pair do |key, value|
params[key] = each_member(value) do |obj|
if obj.kind_of?(Hash)
- file = {'Content-Type' => value[:type], 'Filename' => value[:filename]}
- file['Content'] = value[:tempfile].read if keep_content
+ file = {'Content-Type' => obj[:type], 'Filename' => obj[:filename]}
+ file['Content'] = obj[:tempfile].read if keep_content
file
- else value
+ else
+ obj
end
end
end
{
@@ -204,9 +206,102 @@
#--
# Utils.inflate(res.body) if res['content-encoding'] == 'gzip'
#
def inflate(str)
Zlib::GzipReader.new( StringIO.new( str ) ).read
+ end
+
+ EOL = Rack::Utils::Multipart::EOL
+ # Lifted from Rack::Utils::Multipart, and modified to collect
+ # overloaded params and params with names suffixed by '[]' as
+ # arrays.
+ def parse_multipart(env)
+ unless env['CONTENT_TYPE'] =~
+ %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n
+ nil
+ else
+ boundary = "--#{$1}"
+
+ params = {}
+ buf = ""
+ content_length = env['CONTENT_LENGTH'].to_i
+ input = env['rack.input']
+
+ boundary_size = boundary.size + EOL.size
+ bufsize = 16384
+
+ content_length -= boundary_size
+
+ status = input.read(boundary_size)
+ raise EOFError, "bad content body" unless status == boundary + EOL
+
+ rx = /(?:#{EOL})?#{Regexp.quote boundary}(#{EOL}|--)/
+
+ loop {
+ head = nil
+ body = ''
+ filename = content_type = name = nil
+
+ until head && buf =~ rx
+ if !head && i = buf.index("\r\n\r\n")
+ head = buf.slice!(0, i+2) # First \r\n
+ buf.slice!(0, 2) # Second \r\n
+
+ filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1]
+ content_type = head[/Content-Type: (.*)\r\n/ni, 1]
+ name = head[/Content-Disposition:.* name="?([^\";]*)"?/ni, 1]
+
+ if filename
+ body = Tempfile.new("RackMultipart")
+ body.binmode if body.respond_to?(:binmode)
+ end
+
+ next
+ end
+
+ # Save the read body part.
+ if head && (boundary_size+4 < buf.size)
+ body << buf.slice!(0, buf.size - (boundary_size+4))
+ end
+
+ c = input.read(bufsize < content_length ? bufsize : content_length)
+ raise EOFError, "bad content body" if c.nil? || c.empty?
+ buf << c
+ content_length -= c.size
+ end
+
+ # Save the rest.
+ if i = buf.index(rx)
+ body << buf.slice!(0, i)
+ buf.slice!(0, boundary_size+2)
+
+ content_length = -1 if $1 == "--"
+ end
+
+ if filename
+ body.rewind
+ data = {:filename => filename, :type => content_type,
+ :name => name, :tempfile => body, :head => head}
+ else
+ data = body
+ end
+
+ if name
+ case current = params[name]
+ when nil
+ params[name] = (name =~ /\[\]\z/ ? [data] : data)
+ when Array
+ params[name] << data
+ else
+ params[name] = [current, data]
+ end
+ end
+
+ break if buf.empty? || content_length == -1
+ }
+
+ params
+ end
end
end
end
end
\ No newline at end of file