diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | lib/net/http.rb | 55 | ||||
-rw-r--r-- | test/net/http/test_httpheader.rb | 12 |
3 files changed, 69 insertions, 12 deletions
@@ -1,3 +1,17 @@ +Wed Jul 26 21:59:33 2006 Minero Aoki <aamine@loveruby.net> + + * lib/net/http.rb (Net::HTTP#post, request_post, request): should + set Content-Type: x-www-form-urlencoded by default. + + * lib/net/http.rb (Net::HTTPHeader#content_type): should return + nil when there's no Content-Type. + + * lib/net/http.rb (Net::HTTPHeader#sub_type): should return nil + when there's no sub Content-Type (e.g. "Content-Type: text"). + + * lib/net/http.rb (Net::HTTPHeader#type_params): wrongly failed + when there's no Content-Type. + Wed Jul 26 18:38:13 2006 Minero Aoki <aamine@loveruby.net> * ext/strscan/strscan.c (strscan_do_scan): always return nil if diff --git a/lib/net/http.rb b/lib/net/http.rb index f6e8e9dce3..968ea497b5 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -833,6 +833,10 @@ module Net #:nodoc: # end # } # + # You should set Content-Type: header field for POST. + # If no Content-Type: field given, this method uses + # "application/x-www-form-urlencoded" by default. + # def post(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+ res = nil request(Post.new(path, initheader), data) {|r| @@ -843,7 +847,6 @@ module Net #:nodoc: res.value return res, res.body end - res end @@ -1363,35 +1366,60 @@ module Net #:nodoc: r.end - r.begin end + # Returns a content type string such as "text/html". + # This method returns nil if Content-Type: header field does not exist. def content_type - "#{main_type()}/#{sub_type()}" + return nil unless main_type() + if sub_type() + then "#{main_type()}/#{sub_type()}" + else main_type() + end end + # Returns a content type string such as "text". + # This method returns nil if Content-Type: header field does not exist. def main_type return nil unless @header['content-type'] self['Content-Type'].split(';').first.to_s.split('/')[0].to_s.strip end + # Returns a content type string such as "html". + # This method returns nil if Content-Type: header field does not exist + # or sub-type is not given (e.g. "Content-Type: text"). def sub_type return nil unless @header['content-type'] - self['Content-Type'].split(';').first.to_s.split('/')[1].to_s.strip + main, sub = *self['Content-Type'].split(';').first.to_s.split('/') + return nil unless sub + sub.strip end + # Returns content type parameters as a Hash as like + # {"charset" => "iso-2022-jp"}. def type_params result = {} - self['Content-Type'].to_s.split(';')[1..-1].each do |param| + list = self['Content-Type'].to_s.split(';') + list.shift + list.each do |param| k, v = *param.split('=', 2) result[k.strip] = v.strip end result end + # Set Content-Type: header field by +type+ and +params+. + # +type+ must be a String, +params+ must be a Hash. def set_content_type(type, params = {}) @header['content-type'] = [type + params.map{|k,v|"; #{k}=#{v}"}.join('')] end alias content_type= set_content_type + # Set header fields and a body from HTML form data. + # +params+ should be a Hash containing HTML form data. + # Optional argument +sep+ means data record separator. + # + # This method also set Content-Type: header field to + # application/x-www-form-urlencoded. def set_form_data(params, sep = '&') self.body = params.map {|k,v| "#{urlencode(k.to_s)}=#{urlencode(v.to_s)}" }.join(sep) self.content_type = 'application/x-www-form-urlencoded' @@ -1504,20 +1532,17 @@ module Net #:nodoc: def send_request_with_body(sock, ver, path, body) self.content_length = body.length delete 'Transfer-Encoding' - unless main_type() - warn 'net/http: warning: Content-Type did not set; using application/x-www-form-urlencoded' if $VERBOSE - set_content_type 'application/x-www-form-urlencoded' - end + supply_default_content_type write_header sock, ver, path sock.write body end def send_request_with_body_stream(sock, ver, path, f) - raise ArgumentError, "Content-Length not given and Transfer-Encoding is not `chunked'" unless content_length() or chunked? - unless content_type() - warn 'net/http: warning: Content-Type did not set; using application/x-www-form-urlencoded' if $VERBOSE - set_content_type 'application/x-www-form-urlencoded' + unless content_length() or chunked? + raise ArgumentError, + "Content-Length not given and Transfer-Encoding is not `chunked'" end + supply_default_content_type write_header sock, ver, path if chunked? while s = f.read(1024) @@ -1531,6 +1556,12 @@ module Net #:nodoc: end end + def supply_default_content_type + return if content_type() + warn 'net/http: warning: Content-Type did not set; using application/x-www-form-urlencoded' if $VERBOSE + set_content_type 'application/x-www-form-urlencoded' + end + def write_header(sock, ver, path) buf = "#{@method} #{path} HTTP/#{ver}\r\n" each_capitalized do |k,v| diff --git a/test/net/http/test_httpheader.rb b/test/net/http/test_httpheader.rb index 3d5fa141ef..ca2bf9f46e 100644 --- a/test/net/http/test_httpheader.rb +++ b/test/net/http/test_httpheader.rb @@ -167,39 +167,51 @@ class HTTPHeaderTest < Test::Unit::TestCase end def test_content_type + assert_nil @c.content_type @c.content_type = 'text/html' assert_equal 'text/html', @c.content_type @c.content_type = 'application/pdf' assert_equal 'application/pdf', @c.content_type @c.set_content_type 'text/html', {'charset' => 'iso-2022-jp'} assert_equal 'text/html', @c.content_type + @c.content_type = 'text' + assert_equal 'text', @c.content_type end def test_main_type + assert_nil @c.main_type @c.content_type = 'text/html' assert_equal 'text', @c.main_type @c.content_type = 'application/pdf' assert_equal 'application', @c.main_type @c.set_content_type 'text/html', {'charset' => 'iso-2022-jp'} assert_equal 'text', @c.main_type + @c.content_type = 'text' + assert_equal 'text', @c.main_type end def test_sub_type + assert_nil @c.sub_type @c.content_type = 'text/html' assert_equal 'html', @c.sub_type @c.content_type = 'application/pdf' assert_equal 'pdf', @c.sub_type @c.set_content_type 'text/html', {'charset' => 'iso-2022-jp'} assert_equal 'html', @c.sub_type + @c.content_type = 'text' + assert_nil @c.sub_type end def test_type_params + assert_equal({}, @c.type_params) @c.content_type = 'text/html' assert_equal({}, @c.type_params) @c.content_type = 'application/pdf' assert_equal({}, @c.type_params) @c.set_content_type 'text/html', {'charset' => 'iso-2022-jp'} assert_equal({'charset' => 'iso-2022-jp'}, @c.type_params) + @c.content_type = 'text' + assert_equal({}, @c.type_params) end def test_set_content_type |