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

Cleaner structure: Response is no more a String, and the mixin is replaced by an abstract_response

This commit is contained in:
Julien Kirch 2010-01-25 22:04:59 +01:00
parent 58ed49a2b5
commit 7563fd5a88
14 changed files with 102 additions and 107 deletions

View file

@ -3,7 +3,7 @@ require 'rake'
require 'jeweler'
Jeweler::Tasks.new do |s|
s.name = "rest-client"
s.name = "rest-client-next"
s.description = "A simple HTTP and REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete."
s.summary = "Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions."
s.author = "Adam Wiggins"

View file

@ -11,7 +11,7 @@ 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/abstract_response'
require File.dirname(__FILE__) + '/restclient/response'
require File.dirname(__FILE__) + '/restclient/raw_response'
require File.dirname(__FILE__) + '/restclient/resource'

View file

@ -0,0 +1,58 @@
module RestClient
class AbstractResponse
attr_reader :net_http_res
# HTTP status code
def code
@code ||= @net_http_res.code.to_i
end
# A hash of the headers, beautified with symbols and underscores.
# e.g. "Content-type" will become :content_type.
def headers
@headers ||= self.class.beautify_headers(@net_http_res.to_hash)
end
# The raw headers.
def raw_headers
@raw_headers ||= @net_http_res.to_hash
end
# Hash of cookies extracted from response headers
def cookies
@cookies ||= (self.headers[:set_cookie] || []).inject({}) do |out, cookie_content|
# correctly parse comma-separated cookies containing HTTP dates (which also contain a comma)
cookie_content.split(/,\s*/).inject([""]) { |array, blob|
blob =~ /expires=.+?$/ ? array.push(blob) : array.last.concat(blob)
array
}.each do |cookie|
next if cookie.empty?
key, *val = cookie.split(";").first.split("=")
out[key] = val.join("=")
end
out
end
end
# Return the default behavior corresponding to the response code:
# the response itself for code in 200..206 and an exception in other cases
def return!
if (200..206).include? code
self
elsif Exceptions::EXCEPTIONS_MAP[code]
raise Exceptions::EXCEPTIONS_MAP[code], self
else
raise RequestFailed, self
end
end
def AbstractResponse.beautify_headers(headers)
headers.inject({}) do |out, (key, value)|
out[key.gsub(/-/, '_').downcase.to_sym] = %w{set-cookie}.include?(key.downcase) ? value : value.first
out
end
end
end
end

View file

@ -19,7 +19,7 @@ module RestClient
end
def http_body
@response
@response.body
end
def inspect

View file

@ -1,64 +0,0 @@
module RestClient
module Mixin
module Response
attr_reader :net_http_res
# HTTP status code
def code
@code ||= @net_http_res.code.to_i
end
# A hash of the headers, beautified with symbols and underscores.
# e.g. "Content-type" will become :content_type.
def headers
@headers ||= self.class.beautify_headers(@net_http_res.to_hash)
end
# The raw headers.
def raw_headers
@raw_headers ||= @net_http_res.to_hash
end
# Hash of cookies extracted from response headers
def cookies
@cookies ||= (self.headers[:set_cookie] || []).inject({}) do |out, cookie_content|
# correctly parse comma-separated cookies containing HTTP dates (which also contain a comma)
cookie_content.split(/,\s*/).inject([""]) { |array, blob|
blob =~ /expires=.+?$/ ? array.push(blob) : array.last.concat(blob)
array
}.each do |cookie|
next if cookie.empty?
key, *val = cookie.split(";").first.split("=")
out[key] = val.join("=")
end
out
end
end
# Return the default behavior corresponding to the response code:
# the response itself for code in 200..206 and an exception in other cases
def return!
if (200..206).include? code
self
elsif Exceptions::EXCEPTIONS_MAP[code]
raise Exceptions::EXCEPTIONS_MAP[code], self
else
raise RequestFailed, self
end
end
def self.included(receiver)
receiver.extend(RestClient::Mixin::Response::ClassMethods)
end
module ClassMethods
def beautify_headers(headers)
headers.inject({}) do |out, (key, value)|
out[key.gsub(/-/, '_').downcase.to_sym] = %w{set-cookie}.include?(key.downcase) ? value : value.first
out
end
end
end
end
end
end

View file

@ -88,7 +88,7 @@ module RestClient
end
def short_inspect
(size > 100 ? "#{size} byte length" : inspect)
(size > 100 ? "#{size} byte(s) length" : inspect)
end
end

View file

@ -1,5 +1,3 @@
require File.dirname(__FILE__) + '/mixin/response'
module RestClient
# The response from RestClient on a raw request looks like a string, but is
# actually one of these. 99% of the time you're making a rest call all you
@ -11,8 +9,7 @@ module RestClient
# In addition, if you do not use the response as a string, you can access
# a Tempfile object at res.file, which contains the path to the raw
# downloaded request body.
class RawResponse
include RestClient::Mixin::Response
class RawResponse < AbstractResponse
attr_reader :file

View file

@ -1,19 +1,31 @@
require File.dirname(__FILE__) + '/mixin/response'
module RestClient
# The response from RestClient looks like a string, but is actually one of
# these. 99% of the time you're making a rest call all you care about is
# the body, but on the occassion you want to fetch the headers you can:
#
# RestClient.get('http://example.com').headers[:content_type]
#
class Response < String
include RestClient::Mixin::Response
# A Response from RestClient, you can access the response body, the code or the headers.
#
class Response < AbstractResponse
def initialize(string, net_http_res)
attr_reader :body
def initialize(body, net_http_res)
@net_http_res = net_http_res
super(string || "")
@body = body || ""
end
def method_missing symbol, *args
if body.respond_to? symbol
warn "[warning] The Response is no more a String, please update your code"
body.send symbol, *args
else
super
end
end
def to_s
body.to_s
end
def inspect
"Code #{code} #{headers[:content_type] ? "#{headers[:content_type] } ": ''} #{body.size} byte(s)"
end
end

BIN
rest-client-next-1.3.0.gem Normal file

Binary file not shown.

View file

@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = %q{rest-client}
s.name = %q{rest-client-next}
s.version = "1.3.0"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Adam Wiggins", "Julien Kirch"]
@ -21,7 +21,7 @@ Gem::Specification.new do |s|
"lib/rest_client.rb",
"lib/restclient.rb",
"lib/restclient/exceptions.rb",
"lib/restclient/mixin/response.rb",
"lib/restclient/abstract_response.rb",
"lib/restclient/net_http_ext.rb",
"lib/restclient/payload.rb",
"lib/restclient/raw_response.rb",
@ -32,7 +32,7 @@ Gem::Specification.new do |s|
"spec/exceptions_spec.rb",
"spec/integration_spec.rb",
"spec/master_shake.jpg",
"spec/mixin/response_spec.rb",
"spec/abstract_response_spec.rb",
"spec/payload_spec.rb",
"spec/raw_response_spec.rb",
"spec/request_spec.rb",

View file

@ -1,18 +1,9 @@
require File.dirname(__FILE__) + '/../base'
require File.dirname(__FILE__) + '/base'
class MockResponse
include RestClient::Mixin::Response
def initialize(body, res)
@net_http_res = res
@body = body
end
end
describe RestClient::Mixin::Response do
describe RestClient::AbstractResponse do
before do
@net_http_res = mock('net http response')
@response = MockResponse.new('abc', @net_http_res)
@response = AbstractResponse.new('abc', @net_http_res)
end
it "fetches the numeric response code" do

View file

@ -10,14 +10,14 @@ describe RestClient do
stub_request(:get, "www.example.com").to_return(:body => body, :status => 200)
response = RestClient.get "www.example.com"
response.code.should == 200
response.should == body
response.body.should == body
end
it "a simple request with gzipped content" do
stub_request(:get, "www.example.com").with(:headers => { 'Accept-Encoding' => 'gzip, deflate' }).to_return(:body => "\037\213\b\b\006'\252H\000\003t\000\313T\317UH\257\312,HM\341\002\000G\242(\r\v\000\000\000", :status => 200, :headers => { 'Content-Encoding' => 'gzip' } )
response = RestClient.get "www.example.com"
response.code.should == 200
response.should == "i'm gziped\n"
response.body.should == "i'm gziped\n"
end
it "a 404" do
@ -29,7 +29,7 @@ describe RestClient do
rescue RestClient::ResourceNotFound => e
e.http_code.should == 404
e.response.code.should == 404
e.response.should == body
e.response.body.should == body
e.http_body.should == body
end
end

View file

@ -45,7 +45,8 @@ describe RestClient::Request do
res.stub!(:code).and_return("200")
res.stub!(:body).and_return('body')
res.stub!(:[]).with('content-encoding').and_return(nil)
@request.process_result(res).should == 'body'
@request.process_result(res).body.should == 'body'
@request.process_result(res).to_s.should == 'body'
end
it "doesn't classify successful requests as failed" do
@ -324,8 +325,8 @@ describe RestClient::Request do
it "logs a post request with a large payload" do
log = RestClient.log = []
RestClient::Request.new(:method => :post, :url => 'http://url', :payload => ('x' * 1000)).log_request
['RestClient.post "http://url", 1000 byte length, "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"1000", "Accept"=>"*/*; q=0.5, application/xml"' + "\n",
'RestClient.post "http://url", 1000 byte length, "Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"1000"' + "\n"].should include(log[0])
['RestClient.post "http://url", 1000 byte(s) length, "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"1000", "Accept"=>"*/*; q=0.5, application/xml"' + "\n",
'RestClient.post "http://url", 1000 byte(s) length, "Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"1000"' + "\n"].should include(log[0])
end
it "logs input headers as a hash" do

View file

@ -7,11 +7,11 @@ describe RestClient::Response do
end
it "behaves like string" do
@response.should == 'abc'
@response.should.to_s == 'abc'
end
it "accepts nil strings and sets it to empty for the case of HEAD" do
RestClient::Response.new(nil, @net_http_res).should == ""
RestClient::Response.new(nil, @net_http_res).should.to_s == ""
end
it "test headers and raw headers" do