Since yesterday I reviewed the RestClient::Response
class, it’s time to read the parent class RestClient::AbstractResponse
. There are a few interesting methods in AbstractResponse
but the #return!
method is a good one to review.
The Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
module RestClient class AbstractResponse # Return the default behavior corresponding to the response code: # the response itself for code in 200..206, redirection for 301 and 302 in get and head cases, redirection for 303 and an exception in other cases def return! &block if (200..206).include? code self elsif [301, 302].include? code unless [:get, :head].include? args[:method] raise Exceptions::EXCEPTIONS_MAP[code], self else follow_redirection &block end elsif code == 303 args[:method] = :get args.delete :payload follow_redirection &block elsif Exceptions::EXCEPTIONS_MAP[code] raise Exceptions::EXCEPTIONS_MAP[code], self else raise RequestFailed, self end end end end |
Review
There is a lot of branches here based on the HTTP status code, so I’m going to take it one branch at a time.
200 – 206 Success
1 2 |
if (200..206).include? code self |
The success status codes will just return self
, the Response object.
301 or 302 – Redirect
1 2 3 4 5 6 |
elsif [301, 302].include? code unless [:get, :head].include? args[:method] raise Exceptions::EXCEPTIONS_MAP[code], self else follow_redirection &block end |
301 and 302 responses both have two different responses.
- If the request was using HTTP GET or HTTP HEAD, RestClient will automatically follow the redirect.
- Otherwise it will raise an exception with the message ‘301 – Moved Permanently’ or ‘302 – Found’.
303 – See Other
1 2 3 4 |
elsif code == 303 args[:method] = :get args.delete :payload follow_redirection &block |
The HTTP 303 code is sent so the client will retry their request at a new URI using HTTP GET. RestClient accomplishes this by changing the :method
, deleting the POST/PUT :payload
, and following the redirection.
Other status codes handled by RestClient
1 2 |
elsif Exceptions::EXCEPTIONS_MAP[code] raise Exceptions::EXCEPTIONS_MAP[code], self |
RestClient handles other status codes by throwing an exception. This happens when the request was successful at the transmission level, but it was rejected by the server. The status codes RestClient supports is defined in exceptions.rb.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
STATUSES = {100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 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'} |
Other status codes not handled by RestClient
1 2 3 |
else raise RequestFailed, self end |
Finally, if there is a status code that isn’t handled by RestClient, a RequestFailed
is thrown. This would happen for status 207 (Multi-Status, used in WebDAV) or 307 (Temporary Redirect, HTTP/1.1).
RestClient::AbstractResponse#return!
highlights an important rule when writing multiple if/else or case statements: put the most common cases first. I learned this from Code Complete several years ago and use it every day when writing code. It makes it easier to separate the main and edge case branches of the code.