lib/rack/utils.rb in rack-0.3.0 vs lib/rack/utils.rb in rack-0.4.0
- old
+ new
@@ -21,34 +21,47 @@
[$1.delete('%')].pack('H*')
}
end
module_function :unescape
- # Stolen from Mongrel:
+ # Stolen from Mongrel, with some small modifications:
# Parses a query string by breaking it up at the '&'
# and ';' characters. You can also use this to parse
# cookies by changing the characters used in the second
# parameter (which defaults to '&;').
def parse_query(qs, d = '&;')
params = {}
- (qs||'').split(/[#{d}] */n).inject(params) { |h,p|
- k, v=unescape(p).split('=',2)
+
+ (qs || '').split(/[#{d}] */n).each do |p|
+ k, v = unescape(p).split('=', 2)
+
if cur = params[k]
if cur.class == Array
params[k] << v
else
params[k] = [cur, v]
end
else
params[k] = v
end
- }
-
+ end
+
return params
end
module_function :parse_query
+
+ def build_query(params)
+ params.map { |k, v|
+ if v.class == Array
+ build_query(v.map { |x| [k, x] })
+ else
+ escape(k) + "=" + escape(v)
+ end
+ }.join("&")
+ end
+ module_function :build_query
# Escape ampersands, brackets and quotes to their HTML/XML entities.
def escape_html(string)
string.to_s.gsub("&", "&").
gsub("<", "<").
@@ -56,18 +69,81 @@
gsub("'", "'").
gsub('"', """)
end
module_function :escape_html
- class Context < Proc
- def initialize app_f=nil, app_r=nil
- @for, @app = app_f, app_r
+ def select_best_encoding(available_encodings, accept_encoding)
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
+
+ expanded_accept_encoding =
+ accept_encoding.map { |m, q|
+ if m == "*"
+ (available_encodings - accept_encoding.map { |m2, _| m2 }).map { |m2| [m2, q] }
+ else
+ [[m, q]]
+ end
+ }.inject([]) { |mem, list|
+ mem + list
+ }
+
+ encoding_candidates = expanded_accept_encoding.sort_by { |_, q| -q }.map { |m, _| m }
+
+ unless encoding_candidates.include?("identity")
+ encoding_candidates.push("identity")
end
+
+ expanded_accept_encoding.find_all { |m, q|
+ q == 0.0
+ }.each { |m, _|
+ encoding_candidates.delete(m)
+ }
+
+ return (encoding_candidates & available_encodings)[0]
+ end
+ module_function :select_best_encoding
+
+ # The recommended manner in which to implement a contexting application
+ # is to define a method #context in which a new Context is instantiated.
+ #
+ # As a Context is a glorified block, it is highly recommended that you
+ # define the contextual block within the application's operational scope.
+ # This would typically the application as you're place into Rack's stack.
+ #
+ # class MyObject
+ # ...
+ # def context app
+ # Rack::Utils::Context.new app do |env|
+ # do_stuff
+ # response = app.call(env)
+ # do_more_stuff
+ # end
+ # end
+ # ...
+ # end
+ #
+ # mobj = MyObject.new
+ # app = mobj.context other_app
+ # Rack::Handler::Mongrel.new app
+ class Context < Proc
alias_method :old_inspect, :inspect
+ attr_reader :for, :app
+ def initialize app_f, app_r
+ raise 'running context not provided' unless app_f
+ raise 'running context does not respond to #context' unless app_f.respond_to? :context
+ raise 'application context not provided' unless app_r
+ raise 'application context does not respond to #call' unless app_r.respond_to? :call
+ @for = app_f
+ @app = app_r
+ end
def inspect
"#{old_inspect} ==> #{@for.inspect} ==> #{@app.inspect}"
end
+ def context app_r
+ raise 'new application context not provided' unless app_r
+ raise 'new application context does not respond to #call' unless app_r.respond_to? :call
+ @for.context app_r
+ end
def pretty_print pp
pp.text old_inspect
pp.nest 1 do
pp.breakable
pp.text '=for> '
@@ -185,10 +261,13 @@
filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1]
content_type = head[/Content-Type: (.*)\r\n/ni, 1]
name = head[/Content-Disposition:.* name="?([^\";]*)"?/ni, 1]
- body = Tempfile.new("RackMultipart") if filename
+ if filename
+ body = Tempfile.new("RackMultipart")
+ body.binmode if body.respond_to?(:binmode)
+ end
next
end
# Save the read body part.