Skip to content

Commit

Permalink
If you don't pass a block to a request method, leave the user respons…
Browse files Browse the repository at this point in the history
…ible for closing the socket. This makes it possible for the user to read the body lazily, or in another method.
  • Loading branch information
wycats committed Mar 13, 2011
1 parent c4e593d commit ba657b0
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 30 deletions.
43 changes: 27 additions & 16 deletions lib/net2/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,9 @@ def self.get_print(uri_or_host, path = nil, port = nil)
# print Net::HTTP.get('www.example.com', '/index.html')
#
def self.get(uri_or_host, path = nil, port = nil)
get_response(uri_or_host, path, port).body
get_response(uri_or_host, path, port) do |response|
return response.body
end
end

# Sends a GET request to the target and returns the HTTP response
Expand All @@ -452,15 +454,14 @@ def self.get(uri_or_host, path = nil, port = nil)
def self.get_response(uri_or_host, path = nil, port = nil, &block)
if path
host = uri_or_host
new(host, port || HTTP.default_port).start {|http|
return http.request_get(path, &block)
}
else
uri = uri_or_host
new(uri.hostname, uri.port).start {|http|
return http.request_get(uri.request_uri, &block)
}
host = uri_or_host.hostname
port = uri_or_host.port
path = uri_or_host.request_uri
end

http = new(host, port || HTTP.default_port).start
http.request_get(path, &block)
end

# Posts HTML form data to the specified URI object.
Expand All @@ -485,9 +486,14 @@ def self.post_form(url, params)
req = Post.new(url.path)
req.form_data = params
req.basic_auth url.user, url.password if url.user
new(url.host, url.port).start {|http|
http.request(req)
}
new(url.host, url.port).start do |http|
response = http.request(req)

# we're using the block form, so make sure to read the
# body before the socket is closed.
response.read_body
response
end
end

#
Expand Down Expand Up @@ -1310,9 +1316,14 @@ def transport_request(req)
begin
res = HTTPResponse.read_new(@socket)
end while res.kind_of?(HTTPContinue)
res.reading_body(@socket, req.response_body_permitted?) {
yield res if block_given?
}

res.request = req

if block_given?
res.reading_body(req.response_body_permitted?) do
yield res
end
end
end_transport req, res
res
rescue => exception
Expand All @@ -1333,12 +1344,12 @@ def end_transport(req, res)
@curr_http_version = res.http_version
if @socket.closed?
D 'Conn socket closed'
elsif not res.body and @close_on_empty_response
elsif @close_on_empty_response && !res.body
D 'Conn close'
@socket.close
elsif keep_alive?(req, res)
D 'Conn keep-alive'
else
elsif block_given?
D 'Conn close'
@socket.close
end
Expand Down
35 changes: 21 additions & 14 deletions lib/net2/http/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ class << self
def read_new(sock) #:nodoc: internal use only
httpv, code, msg = read_status_line(sock)
res = response_class(code).new(httpv, code, msg)
each_response_header(sock) do |k,v|
res.add_field k, v
end

each_response_header(sock) { |k,v| res.add_field k, v }
res.socket = sock

res
end

private
private

def read_status_line(sock)
str = sock.readline
m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in.match(str) or
raise HTTPBadResponse, "wrong status line: #{str.dump}"
m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in.match(str)
raise HTTPBadResponse, "wrong status line: #{str.dump}" unless m
m.captures
end

Expand Down Expand Up @@ -53,20 +54,18 @@ def each_response_header(sock)
raise HTTPBadResponse, 'wrong header line format' if value.nil?
end
end

yield key, value if key
end
end

# next is to fix bug in RDoc, where the private inside class << self
# spills out.
public

include HTTPHeader

def initialize(httpv, code, msg) #:nodoc: internal use only
@http_version = httpv
@code = code
@message = msg

initialize_http_header nil
@body = nil
@read = false
Expand All @@ -80,6 +79,10 @@ def initialize(httpv, code, msg) #:nodoc: internal use only
# the response object is an instance of.
attr_reader :code

attr_accessor :socket

attr_accessor :request

# The HTTP result message sent by the server. For example, 'Not Found'.
attr_reader :message
alias msg message # :nodoc: obsolete
Expand Down Expand Up @@ -132,9 +135,9 @@ def read_header #:nodoc:
# body
#

def reading_body(sock, reqmethodallowbody) #:nodoc: internal use only
@socket = sock
@body_exist = reqmethodallowbody && self.class.body_permitted?
def reading_body(request_allows_body) #:nodoc: internal use only
#@socket = sock
@body_exist = request_allows_body && self.class.body_permitted?
begin
yield
self.body # ensure to read body
Expand All @@ -143,6 +146,10 @@ def reading_body(sock, reqmethodallowbody) #:nodoc: internal use only
end
end

def body_exist?
request.response_body_permitted? && self.class.body_permitted?
end

# Gets the entity body returned by the remote HTTP server.
#
# If a block is given, the body is passed to the block, and
Expand Down Expand Up @@ -174,7 +181,7 @@ def read_body(dest = nil, &block)
end
to = procdest(dest, block)
stream_check
if @body_exist
if body_exist?
read_body_0 to
@body = to
else
Expand Down

0 comments on commit ba657b0

Please sign in to comment.