1
0
Fork 0
mirror of https://github.com/rest-client/rest-client.git synced 2022-11-09 13:49:40 -05:00

Giving a first try

This commit is contained in:
Julien Kirch 2010-01-18 22:15:15 +01:00
parent d385dc3f05
commit 3b83aadc35
4 changed files with 63 additions and 64 deletions

View file

@ -9,12 +9,12 @@ rescue LoadError => e
raise LoadError, "no such file to load -- net/https. Try running apt-get install libopenssl-ruby"
end
require File.dirname(__FILE__) + '/restclient/exceptions'
require File.dirname(__FILE__) + '/restclient/request'
require File.dirname(__FILE__) + '/restclient/mixin/response'
require File.dirname(__FILE__) + '/restclient/response'
require File.dirname(__FILE__) + '/restclient/raw_response'
require File.dirname(__FILE__) + '/restclient/resource'
require File.dirname(__FILE__) + '/restclient/exceptions'
require File.dirname(__FILE__) + '/restclient/payload'
require File.dirname(__FILE__) + '/restclient/net_http_ext'

View file

@ -1,32 +1,54 @@
module RestClient
# This is the base RestClient exception class. Rescue it if you want to
# catch any exception that your request might raise
class Exception < RuntimeError
def message(default=nil)
self.class::ErrorMessage
end
end
attr_accessor :message, :response
# Base RestClient exception when there's a response available
class ExceptionWithResponse < Exception
attr_accessor :response
def initialize(response=nil)
def initialize response = nil
@response = response
end
def http_code
@response.code.to_i if @response
@response.code if @response
end
def http_body
RestClient::Request.decode(@response['content-encoding'], @response.body) if @response
@response
end
def inspect
"#{self.class} : #{http_code} #{message}"
end
end
# We will a create an exception for each status code, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
module Exceptions
# Map http status codes to the corresponding exception class
EXCEPTIONS_MAP = {}
end
{304 => 'Not Modified', 305 => 'Use Proxy',
400 => 'Bad Request', 401 => 'Unauthorized', 403 => 'Forbidden', 404 => 'Resource Not Found',
405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout',
409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed',
413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable',
504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported'}.each_pair do |code, message|
klass = Class.new(Exception) do
send :define_method, :message, Proc.new{message}
message
end
klass = const_set message.gsub(/ /, '').gsub(/-/, ''), klass
Exceptions::EXCEPTIONS_MAP[code] = klass
end
# A redirect was encountered; caught by execute to retry with the new url.
class Redirect < Exception
ErrorMessage = "Redirect"
message = 'Redirect'
attr_accessor :url
@ -35,42 +57,22 @@ module RestClient
end
end
class NotModified < ExceptionWithResponse
ErrorMessage = 'NotModified'
end
# Authorization is required to access the resource specified.
class Unauthorized < ExceptionWithResponse
ErrorMessage = 'Unauthorized'
end
# No resource was found at the given URL.
class ResourceNotFound < ExceptionWithResponse
ErrorMessage = 'Resource not found'
end
# The server broke the connection prior to the request completing. Usually
# this means it crashed, or sometimes that your network connection was
# severed before it could complete.
class ServerBrokeConnection < Exception
ErrorMessage = 'Server broke connection'
message = 'Server broke connection'
end
# The server took too long to respond.
class RequestTimeout < Exception
ErrorMessage = 'Request timed out'
end
# The request failed, meaning the remote HTTP server returned a code other
# than success, unauthorized, or redirect.
#
# The exception message attempts to extract the error from the XML, using
# format returned by Rails: <errors><error>some message</error></errors>
#
# You can get the status code by e.http_code, or see anything about the
# response via e.response. For example, the entire result body (which is
# probably an HTML error page) is e.response.body.
class RequestFailed < ExceptionWithResponse
class RequestFailed < Exception
def message
"HTTP status code #{http_code}"
end
@ -79,6 +81,7 @@ module RestClient
message
end
end
end
# backwards compatibility

View file

@ -3,8 +3,7 @@ module RestClient
module Response
attr_reader :net_http_res
# HTTP status code, always 200 since RestClient throws exceptions for
# other codes.
# HTTP status code
def code
@code ||= @net_http_res.code.to_i
end

View file

@ -20,11 +20,15 @@ module RestClient
# * :timeout and :open_timeout
# * :ssl_client_cert, :ssl_client_key, :ssl_ca_file
class Request
include RestClient::Exceptions
attr_reader :method, :url, :payload, :headers, :processed_headers,
:cookies, :user, :password, :timeout, :open_timeout,
:verify_ssl, :ssl_client_cert, :ssl_client_key, :ssl_ca_file,
:raw_response
def self.execute(args)
new(args).execute
end
@ -152,16 +156,7 @@ module RestClient
net.start do |http|
res = http.request(req, payload) { |http_response| fetch_body(http_response) }
result = process_result(res)
log_response res
if result.kind_of?(String) or @method == :head
Response.new(result, res)
elsif @raw_response
RawResponse.new(@tf, res)
else
Response.new(nil, res)
end
process_result(res)
end
rescue EOFError
raise RestClient::ServerBrokeConnection
@ -201,13 +196,20 @@ module RestClient
http_response
end
def process_result(res)
if res.code =~ /\A2\d{2}\z/
def process_result res
if @raw_response
# We don't decode raw requests
unless @raw_response
self.class.decode res['content-encoding'], res.body if res.body
end
elsif %w(301 302 303).include? res.code
response = RawResponse.new(@tf, res)
else
response = Response.new(Request.decode(res['content-encoding'], res.body), res)
end
log_response response
code = res.code.to_i
if (200...206).include? code
response
elsif (301...303).include? code
url = res.header['Location']
if url !~ /^http/
@ -215,24 +217,19 @@ module RestClient
uri.path = "/#{url}".squeeze('/')
url = uri.to_s
end
raise Redirect, url
elsif res.code == "304"
raise NotModified, res
elsif res.code == "401"
raise Unauthorized, res
elsif res.code == "404"
raise ResourceNotFound, res
elsif EXCEPTIONS_MAP[code]
raise EXCEPTIONS_MAP[code], response
else
raise RequestFailed, res
raise RequestFailed, response
end
end
def self.decode(content_encoding, body)
def self.decode content_encoding, body
if content_encoding == 'gzip' and not body.empty?
Zlib::GzipReader.new(StringIO.new(body)).read
elsif content_encoding == 'deflate'
Zlib::Inflate.new.inflate(body)
Zlib::Inflate.new.inflate body
else
body
end