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:
parent
d385dc3f05
commit
3b83aadc35
4 changed files with 63 additions and 64 deletions
|
@ -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'
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue