lib/rev/http_client.rb in rev-0.1.4 vs lib/rev/http_client.rb in rev-0.2.0
- old
+ new
@@ -3,11 +3,10 @@
# Includes portions originally Copyright (C)2005 Zed Shaw
# You can redistribute this under the terms of the Ruby license
# See file LICENSE for details
#++
-require File.dirname(__FILE__) + '/../rev'
require File.dirname(__FILE__) + '/../http11_client'
module Rev
# A simple hash is returned for each request made by HttpClient with
# the headers that were given by the server for that request.
@@ -77,17 +76,17 @@
# redirects will tack on the :80 which is annoying.
def encode_host
remote_host + (remote_port.to_i != 80 ? ":#{remote_port}" : "")
end
- def encode_request(method, uri, query)
- HTTP_REQUEST_HEADER % [method.to_s.upcase, encode_query(uri, query)]
+ def encode_request(method, path, query)
+ HTTP_REQUEST_HEADER % [method.to_s.upcase, encode_query(path, query)]
end
- def encode_query(uri, query)
- return uri unless query
- uri + "?" + query.map { |k, v| encode_param(k, v) }.join('&')
+ def encode_query(path, query)
+ return path unless query
+ path + "?" + query.map { |k, v| encode_param(k, v) }.join('&')
end
# URL encodes a single k=v parameter.
def encode_param(k, v)
escape(k) + "=" + escape(v)
@@ -165,31 +164,25 @@
# Specify hash of cookies (auto-escaped)
#
# body: String
# Specify the request body (you must encode it for now)
#
- def request(method, uri, options = {})
+ def request(method, path, options = {})
+ raise ArgumentError, "invalid request path" unless path[0] == '/'
raise RuntimeError, "request already sent" if @requested
- @method, @uri, @options = method, uri, options
+ @method, @path, @options = method, path, options
@requested = true
return unless @connected
send_request
end
-
- # Requests can be made through method missing by invoking the HTTP method to use, i.e.:
- #
- # httpclient.get(path, options)
- #
- # Valid for: get, post, put, delete, head
- #
- # To use other HTTP methods, invoke the request method directly
- #
- def method_missing(method, *args)
- raise NoMethodError, "method not supported" unless ALLOWED_METHODS.include? method.to_sym
- request method, *args
+
+ # Enable the HttpClient if it has been disabled
+ def enable
+ super
+ dispatch unless @data.empty?
end
# Called when response header has been received
def on_response_header(response_header)
end
@@ -203,26 +196,27 @@
# Called when the request has completed
def on_request_complete
close
end
- # Called when an error occurs during the request
+ # Called when an error occurs dispatching the request
def on_error(reason)
+ close
raise RuntimeError, reason
end
#########
protected
#########
#
# Rev callbacks
#
-
+
def on_connect
@connected = true
- send_request if @method and @uri
+ send_request if @method and @path
end
def on_read(data)
@data << data
dispatch
@@ -254,11 +248,11 @@
# Default to Connection: close
head['connection'] ||= 'close'
# Build the request
- request_header = encode_request(@method, @uri, query)
+ request_header = encode_request(@method, @path, query)
request_header << encode_headers(head)
request_header << encode_cookies(cookies) if cookies
request_header << CRLF
write request_header
@@ -271,11 +265,11 @@
#
# Response processing
#
def dispatch
- while case @state
+ while enabled? and case @state
when :response_header
parse_response_header
when :chunk_header
parse_chunk_header
when :chunk_body
@@ -294,11 +288,17 @@
end
def parse_header(header)
return false if @data.empty?
- @parser_nbytes = @parser.execute(header, @data.to_str, @parser_nbytes)
+ begin
+ @parser_nbytes = @parser.execute(header, @data.to_str, @parser_nbytes)
+ rescue Rev::HttpClientParserError
+ on_error "invalid HTTP format, parsing fails"
+ @state = :invalid
+ end
+
return false unless @parser.finished?
# Clear parsed data from the buffer
@data.read(@parser_nbytes)
@parser.reset
@@ -383,17 +383,20 @@
false
end
def process_body
- # FIXME the proper thing to do here is probably to keep reading until
- # the socket closes, then assume that's the end of the body, provided
- # the server has specified Connection: close
if @bytes_remaining.nil?
- on_error "no content length specified"
- @state = :invalid
+ on_body_data @data.read
+ return false
end
+
+ if @bytes_remaining.zero?
+ on_request_complete
+ @state = :finished
+ return false
+ end
if @data.size < @bytes_remaining
@bytes_remaining -= @data.size
on_body_data @data.read
return false
@@ -411,6 +414,6 @@
end
false
end
end
-end
\ No newline at end of file
+end