Skip to content

Commit

Permalink
define String#bytesize and use it for 1.9 compatibility. closes nahi#23.
Browse files Browse the repository at this point in the history
  • Loading branch information
nahi committed Dec 3, 2009
1 parent 58bde3a commit 261b280
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 30 deletions.
21 changes: 15 additions & 6 deletions lib/httpclient/auth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -587,9 +587,15 @@ def initialize(*args)
end

def self.escape(str) # :nodoc:
str.gsub(/([^a-zA-Z0-9_.~-]+)/n) {
'%' + $1.unpack('H2' * $1.size).join('%').upcase
}
if str.respond_to?(:force_encoding)
s = str.dup.force_encoding('BINARY').gsub(/([^a-zA-Z0-9_.~-]+)/) {
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
}
else
str.gsub(/([^a-zA-Z0-9_.~-]+)/n) {
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
}
end
end

def escape(str)
Expand Down Expand Up @@ -680,7 +686,8 @@ def calc_cred(req, config)
header['oauth_verifier'] = config.verifier if config.verifier
signature = sign(config, header, req)
header['oauth_signature'] = signature
str = header.map { |k, v| encode_header(k, v) }.join(', ')
# no need to do but we should sort for easier to test.
str = header.sort_by { |k, v| k }.map { |k, v| encode_header(k, v) }.join(', ')
if config.realm
str = %Q(realm="#{config.realm}", ) + str
end
Expand All @@ -700,8 +707,10 @@ def encode_header(k, v)

def encode_param(params)
params.map { |k, v|
%Q(#{escape(k.to_s)}=#{escape(v.to_s)})
}
[v].flatten.map { |vv|
%Q(#{escape(k.to_s)}=#{escape(vv.to_s)})
}
}.flatten
end

def sign(config, header, req)
Expand Down
37 changes: 23 additions & 14 deletions lib/httpclient/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,9 @@ def init_request(body = nil, boundary = nil)
# Initialize this instance as a response.
def init_response(body = nil)
@body = body
if @body.respond_to?(:size)
if @body.respond_to?(:bytesize)
@size = @body.bytesize
elsif @body.respond_to?(:size)
@size = @body.size
else
@size = nil
Expand Down Expand Up @@ -500,7 +502,7 @@ def set_content(body, boundary = nil)
@size = @body.size
else
@body = Message.create_query_part_str(body)
@size = @body.size
@size = @body.bytesize
end
end

Expand All @@ -521,7 +523,7 @@ def dump_chunks(io, dev)
end

def dump_chunk(str)
dump_chunk_size(str.size) + (str + CRLF)
dump_chunk_size(str.bytesize) + (str + CRLF)
end

def dump_last_chunk
Expand Down Expand Up @@ -559,10 +561,10 @@ def add(part)
end
elsif @body[-1].is_a?(String)
@body[-1] += part.to_s
@size += part.to_s.size if @size
@size += part.to_s.bytesize if @size
else
@body << part.to_s
@size += part.to_s.size if @size
@size += part.to_s.bytesize if @size
end
end

Expand Down Expand Up @@ -590,7 +592,8 @@ def build_query_multipart_str(query, boundary)
elsif value.respond_to?(:content_type)
content_type = value.content_type
else
content_type = Message.mime_type(value.path)
path = value.respond_to?(:path) ? value.path : nil
content_type = Message.mime_type(path)
end
headers << %{Content-Disposition: form-data; name="#{attr}"; #{param_str}}
headers << %{Content-Type: #{content_type}}
Expand All @@ -607,7 +610,8 @@ def build_query_multipart_str(query, boundary)

def params_from_file(value)
params = {}
params['filename'] = File.basename(value.path || '')
path = value.respond_to?(:path) ? value.path : nil
params['filename'] = File.basename(path || '')
# Creation time is not available from File::Stat
if value.respond_to?(:mtime)
params['modification-date'] = value.mtime.rfc822
Expand Down Expand Up @@ -742,15 +746,14 @@ def multiparam_query?(query)

# Returns true if the given object is a File. In HTTPClient, a file is;
# * must respond to :read for retrieving String chunks.
# * must respond to :path and returns a path for Content-Disposition.
# * must respond to :pos and :pos= to rewind for reading.
# Rewinding is only needed for following HTTP redirect. Some IO impl
# defines :pos= but raises an Exception for pos= such as StringIO
# but there's no problem as far as using it for non-following methods
# (get/post/etc.)
def file?(obj)
obj.respond_to?(:read) and obj.respond_to?(:path) and
obj.respond_to?(:pos) and obj.respond_to?(:pos=)
obj.respond_to?(:read) and obj.respond_to?(:pos) and
obj.respond_to?(:pos=)
end

def create_query_part_str(query) # :nodoc:
Expand All @@ -764,7 +767,7 @@ def create_query_part_str(query) # :nodoc:
end

def escape_query(query) # :nodoc:
query.collect { |attr, value|
query.sort_by { |attr, value| attr.to_s }.collect { |attr, value|
if value.respond_to?(:read)
value = value.read
end
Expand All @@ -774,9 +777,15 @@ def escape_query(query) # :nodoc:

# from CGI.escape
def escape(str) # :nodoc:
str.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
'%' + $1.unpack('H2' * $1.size).join('%').upcase
}.tr(' ', '+')
if str.respond_to?(:force_encoding)
str.dup.force_encoding('BINARY').gsub(/([^ a-zA-Z0-9_.-]+)/) {
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
}.tr(' ', '+')
else
str.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
}.tr(' ', '+')
end
end

# from CGI.parse
Expand Down
8 changes: 4 additions & 4 deletions lib/httpclient/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -815,8 +815,8 @@ def read_body_length(&block)
buf = nil
end
end
if buf && buf.length > 0
@content_length -= buf.length
if buf && buf.bytesize > 0
@content_length -= buf.bytesize
yield buf
else
@content_length = 0
Expand Down Expand Up @@ -846,7 +846,7 @@ def read_body_chunked(&block)
end

def read_body_rest
if @readbuf and @readbuf.length > 0
if @readbuf and @readbuf.bytesize > 0
yield @readbuf
@readbuf = nil
end
Expand All @@ -859,7 +859,7 @@ def read_body_rest
buf = nil
end
end
if buf && buf.length > 0
if buf && buf.bytesize > 0
yield buf
else
return
Expand Down
7 changes: 7 additions & 0 deletions lib/httpclient/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
require 'uri'


unless ''.respond_to?(:bytesize)
class String
alias bytesize size
end
end


class HTTPClient


Expand Down
9 changes: 5 additions & 4 deletions test/test_auth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,19 +176,20 @@ def test_oauth
c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
c.debug_dev = str = ''
c.get_content('http://photos.example.net/photos', :file => 'vacation.jpg', :size => 'original')
assert(str.index(%q(GET /photos?size=original&file=vacation.jpg)))
assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_nonce="kllo9940pd9333jh", oauth_timestamp="1191242096", oauth_signature_method="HMAC-SHA1", oauth_token="nnch734d00sl2jdk", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D", oauth_version="1.0")))
assert(str.index(%q(GET /photos?file=vacation.jpg&size=original)))
assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_nonce="kllo9940pd9333jh", oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1191242096", oauth_token="nnch734d00sl2jdk", oauth_version="1.0")))
#
c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
c.debug_dev = str = ''
c.get_content('http://photos.example.net/photos?file=vacation.jpg&size=original')
assert(str.index(%q(GET /photos?file=vacation.jpg&size=original)))
assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_nonce="kllo9940pd9333jh", oauth_timestamp="1191242096", oauth_signature_method="HMAC-SHA1", oauth_token="nnch734d00sl2jdk", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D", oauth_version="1.0")))
assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_nonce="kllo9940pd9333jh", oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1191242096", oauth_token="nnch734d00sl2jdk", oauth_version="1.0")))
return
#
c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
c.debug_dev = str = ''
c.post_content('http://photos.example.net/photos', :file => 'vacation.jpg', :size => 'original')
assert(str.index(%q(POST /photos)))
assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_nonce="kllo9940pd9333jh", oauth_timestamp="1191242096", oauth_signature_method="HMAC-SHA1", oauth_token="nnch734d00sl2jdk", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_signature="wPkvxykrw%2BBTdCcGqKr%2B3I%2BPsiM%3D", oauth_version="1.0")))
assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_nonce="kllo9940pd9333jh", oauth_signature="wPkvxykrw%2BBTdCcGqKr%2B3I%2BPsiM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1191242096", oauth_token="nnch734d00sl2jdk", oauth_version="1.0")))
end
end
5 changes: 3 additions & 2 deletions test/test_httpclient.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- encoding: UTF-8 -*-
require 'test/unit'
require 'httpclient'
require 'webrick'
Expand Down Expand Up @@ -1080,7 +1081,7 @@ def test_response

def test_timeout_scheduler
assert_equal('hello', @client.get_content(@url + 'hello'))
status = HTTPClient.timeout_scheduler.instance_eval { @thread.kill; @thread.status }
status = HTTPClient.timeout_scheduler.instance_eval { @thread.kill; @thread.join; @thread.status }
assert(!status) # dead
assert_equal('hello', @client.get_content(@url + 'hello'))
end
Expand Down Expand Up @@ -1264,10 +1265,10 @@ def do_POST(req, res)
end

def do_PUT(req, res)
res.body = 'put'
res["x-query"] = body_response(req)
param = WEBrick::HTTPUtils.parse_query(req.body) || {}
res["x-size"] = (param['txt'] || '').size
res.body = param['txt'] || 'put'
end

def do_DELETE(req, res)
Expand Down

0 comments on commit 261b280

Please sign in to comment.