Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added support for Accept-Encoding (via Request#accept_encoding and Ut…

…ils.select_best_encoding)
  • Loading branch information...
commit 0f2dab573bb53d612bd93cc04327bf147909fb95 1 parent 835cfd6
@qerub qerub authored committed
View
12 lib/rack/request.rb
@@ -193,5 +193,17 @@ def fullpath
path << "?" << query_string unless query_string.empty?
path
end
+
+ def accept_encoding
+ @env["HTTP_ACCEPT_ENCODING"].to_s.split(/,\s*/).map do |part|
+ m = /^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$/.match(part) # From WEBrick
+
+ if m
+ [m[1], (m[2] || 1.0).to_f]
+ else
+ raise "Invalid value for Accept-Encoding: #{part.inspect}"
+ end
+ end
+ end
end
end
View
30 lib/rack/utils.rb
@@ -71,6 +71,36 @@ def escape_html(string)
end
module_function :escape_html
+ 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.
#
View
16 test/spec_rack_request.rb
@@ -381,4 +381,20 @@
res.should.be.ok
end
+
+ specify "should parse Accept-Encoding correctly" do
+ parser = lambda do |x|
+ Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding
+ end
+
+ parser.call(nil).should.equal([])
+
+ parser.call("compress, gzip").should.equal([["compress", 1.0], ["gzip", 1.0]])
+ parser.call("").should.equal([])
+ parser.call("*").should.equal([["*", 1.0]])
+ parser.call("compress;q=0.5, gzip;q=1.0").should.equal([["compress", 0.5], ["gzip", 1.0]])
+ parser.call("gzip;q=1.0, identity; q=0.5, *;q=0").should.equal([["gzip", 1.0], ["identity", 0.5], ["*", 0] ])
+
+ lambda { parser.call("gzip ; q=1.0") }.should.raise(RuntimeError)
+ end
end
View
23 test/spec_rack_utils.rb
@@ -39,6 +39,29 @@
Rack::Utils.build_query("my weird field" => "q1!2\"'w$5&7/z8)?").
should.equal "my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F"
end
+
+ specify "should figure out which encodings are acceptable" do
+ helper = lambda do |a, b|
+ request = Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => a))
+ Rack::Utils.select_best_encoding(a, b)
+ end
+
+ helper.call(%w(), [["x", 1]]).should.equal(nil)
+ helper.call(%w(identity), [["identity", 0.0]]).should.equal(nil)
+ helper.call(%w(identity), [["*", 0.0]]).should.equal(nil)
+
+ helper.call(%w(identity), [["compress", 1.0], ["gzip", 1.0]]).should.equal("identity")
+
+ helper.call(%w(compress gzip identity), [["compress", 1.0], ["gzip", 1.0]]).should.equal("compress")
+ helper.call(%w(compress gzip identity), [["compress", 0.5], ["gzip", 1.0]]).should.equal("gzip")
+
+ helper.call(%w(foo bar identity), []).should.equal("identity")
+ helper.call(%w(foo bar identity), [["*", 1.0]]).should.equal("foo")
+ helper.call(%w(foo bar identity), [["*", 1.0], ["foo", 0.9]]).should.equal("bar")
+
+ helper.call(%w(foo bar identity), [["foo", 0], ["bar", 0]]).should.equal("identity")
+ helper.call(%w(foo bar baz identity), [["*", 0], ["identity", 0.1]]).should.equal("identity")
+ end
end
context "Rack::Utils::HeaderHash" do
Please sign in to comment.
Something went wrong with that request. Please try again.