summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--NEWS3
-rw-r--r--lib/open-uri.rb33
-rw-r--r--test/open-uri/test_open-uri.rb15
4 files changed, 48 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index a897e661b5..ad4beb49a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Tue Apr 9 19:45:44 2013 Tanaka Akira <akr@fsij.org>
+
+ * lib/open-uri.rb: Support multiple fields with same field
+ name (like Set-Cookie).
+ (OpenURI::Meta#metas): New accessor to obtain fields as a Hash from
+ field name (string) to field values (array of strings).
+ [ruby-core:37734] [Bug #4964] reported by ren li.
+
Tue Apr 9 15:26:12 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* compile.c (iseq_compile_each): append keyword hash to argument array
diff --git a/NEWS b/NEWS
index 8482dc0874..9032a8509c 100644
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,9 @@ with all sufficient information, see the ChangeLog file.
* Pathname#write
* Pathname#binwrite
+* open-uri
+ * Support multiple fields with same field name (like Set-Cookie).
+
* Resolv
* New methods:
* Resolv::DNS.fetch_resource
diff --git a/lib/open-uri.rb b/lib/open-uri.rb
index 47a9b90fd0..32f0662afc 100644
--- a/lib/open-uri.rb
+++ b/lib/open-uri.rb
@@ -336,7 +336,7 @@ module OpenURI
io = buf.io
io.rewind
io.status = [resp.code, resp.message]
- resp.each {|name,value| buf.io.meta_add_field name, value }
+ resp.each_name {|name| buf.io.meta_add_field2 name, resp.get_fields(name) }
case resp
when Net::HTTPSuccess
when Net::HTTPMovedPermanently, # 301
@@ -405,13 +405,14 @@ module OpenURI
obj.extend Meta
obj.instance_eval {
@base_uri = nil
- @meta = {}
+ @meta = {} # name to string. legacy.
+ @metas = {} # name to array of strings.
}
if src
obj.status = src.status
obj.base_uri = src.base_uri
- src.meta.each {|name, value|
- obj.meta_add_field(name, value)
+ src.metas.each {|name, values|
+ obj.meta_add_field2(name, values)
}
end
end
@@ -425,8 +426,16 @@ module OpenURI
# returns a Hash that represents header fields.
# The Hash keys are downcased for canonicalization.
+ # The Hash values are a field body.
+ # If there are multiple field with same field name,
+ # the field values are concatenated with a comma.
attr_reader :meta
+ # returns a Hash that represents header fields.
+ # The Hash keys are downcased for canonicalization.
+ # The Hash value are an array of field values.
+ attr_reader :metas
+
def meta_setup_encoding # :nodoc:
charset = self.charset
enc = nil
@@ -446,15 +455,17 @@ module OpenURI
end
end
- def meta_add_field(name, value) # :nodoc:
+ def meta_add_field2(name, values) # :nodoc:
name = name.downcase
- @meta[name] = value
+ @metas[name] = values
+ @meta[name] = values.join(', ')
meta_setup_encoding if name == 'content-type'
end
# returns a Time that represents the Last-Modified field.
def last_modified
- if v = @meta['last-modified']
+ if vs = @metas['last-modified']
+ v = vs.join(', ')
Time.httpdate(v)
else
nil
@@ -469,9 +480,9 @@ module OpenURI
# :startdoc:
def content_type_parse # :nodoc:
- v = @meta['content-type']
+ vs = @metas['content-type']
# The last (?:;#{RE_LWS}?)? matches extra ";" which violates RFC2045.
- if v && %r{\A#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?/(#{RE_TOKEN})#{RE_LWS}?(#{RE_PARAMETERS})(?:;#{RE_LWS}?)?\z}no =~ v
+ if vs && %r{\A#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?/(#{RE_TOKEN})#{RE_LWS}?(#{RE_PARAMETERS})(?:;#{RE_LWS}?)?\z}no =~ vs.join(', ')
type = $1.downcase
subtype = $2.downcase
parameters = []
@@ -523,8 +534,8 @@ module OpenURI
# as an Array of String.
# The encodings are downcased for canonicalization.
def content_encoding
- v = @meta['content-encoding']
- if v && %r{\A#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?(?:,#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?)*}o =~ v
+ vs = @metas['content-encoding']
+ if vs && %r{\A#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?(?:,#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?)*}o =~ (v = vs.join(', '))
v.scan(RE_TOKEN).map {|content_coding| content_coding.downcase}
else
[]
diff --git a/test/open-uri/test_open-uri.rb b/test/open-uri/test_open-uri.rb
index 740728e9e7..21dd96960a 100644
--- a/test/open-uri/test_open-uri.rb
+++ b/test/open-uri/test_open-uri.rb
@@ -502,6 +502,21 @@ class TestOpenURI < Test::Unit::TestCase
}
end if defined?(Zlib::GzipWriter)
+ def test_multiple_cookies
+ with_http {|srv, dr, url|
+ srv.mount_proc("/mcookie/") {|req, res|
+ res.cookies << "name1=value1; blabla"
+ res.cookies << "name2=value2; blabla"
+ res.body = "foo"
+ }
+ open("#{url}/mcookie/") {|f|
+ assert_equal("foo", f.read)
+ assert_equal(["name1=value1; blabla", "name2=value2; blabla"],
+ f.metas['set-cookie'].sort)
+ }
+ }
+ end
+
# 192.0.2.0/24 is TEST-NET. [RFC3330]
def test_ftp_invalid_request