jnunemaker-httparty 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -1
- data/Manifest.txt +2 -1
- data/examples/google.rb +1 -0
- data/httparty.gemspec +7 -5
- data/lib/httparty.rb +31 -105
- data/lib/httparty/request.rb +104 -0
- data/lib/httparty/version.rb +1 -1
- data/spec/httparty/request_spec.rb +107 -0
- data/spec/httparty_spec.rb +26 -127
- data/spec/spec.opts +3 -1
- metadata +4 -3
data/History.txt
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
+
== 0.1.5 2008-11-14
|
2
|
+
* 2 major enhancements
|
3
|
+
* Refactored send request method out into its own object.
|
4
|
+
* Added :html format if you just want to do that.
|
5
|
+
|
1
6
|
== 0.1.4 2008-11-08
|
2
|
-
*
|
7
|
+
* 3 major enhancements:
|
3
8
|
* Removed some cruft
|
4
9
|
* Added ability to follow redirects automatically and turn that off (Alex Vollmer)
|
5
10
|
|
data/Manifest.txt
CHANGED
@@ -13,13 +13,14 @@ examples/twitter.rb
|
|
13
13
|
examples/whoismyrep.rb
|
14
14
|
httparty.gemspec
|
15
15
|
lib/httparty.rb
|
16
|
+
lib/httparty/request.rb
|
16
17
|
lib/httparty/version.rb
|
17
18
|
script/console
|
18
19
|
script/destroy
|
19
20
|
script/generate
|
20
21
|
script/txt2html
|
21
22
|
setup.rb
|
22
|
-
spec/
|
23
|
+
spec/httparty/request_spec.rb
|
23
24
|
spec/httparty_spec.rb
|
24
25
|
spec/spec.opts
|
25
26
|
spec/spec_helper.rb
|
data/examples/google.rb
CHANGED
data/httparty.gemspec
CHANGED
@@ -1,28 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
1
3
|
Gem::Specification.new do |s|
|
2
4
|
s.name = %q{httparty}
|
3
|
-
s.version = "0.1.
|
5
|
+
s.version = "0.1.5"
|
4
6
|
|
5
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
8
|
s.authors = ["John Nunemaker"]
|
7
|
-
s.date = %q{2008-11-
|
9
|
+
s.date = %q{2008-11-14}
|
8
10
|
s.description = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
|
9
11
|
s.email = ["nunemaker@gmail.com"]
|
10
12
|
s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "PostInstall.txt", "README.txt"]
|
11
|
-
s.files = ["History.txt", "License.txt", "Manifest.txt", "PostInstall.txt", "README.txt", "Rakefile", "config/hoe.rb", "config/requirements.rb", "examples/aaws.rb", "examples/delicious.rb", "examples/google.rb", "examples/twitter.rb", "examples/whoismyrep.rb", "httparty.gemspec", "lib/httparty.rb", "lib/httparty/version.rb", "script/console", "script/destroy", "script/generate", "script/txt2html", "setup.rb", "spec/
|
13
|
+
s.files = ["History.txt", "License.txt", "Manifest.txt", "PostInstall.txt", "README.txt", "Rakefile", "config/hoe.rb", "config/requirements.rb", "examples/aaws.rb", "examples/delicious.rb", "examples/google.rb", "examples/twitter.rb", "examples/whoismyrep.rb", "httparty.gemspec", "lib/httparty.rb", "lib/httparty/request.rb", "lib/httparty/version.rb", "script/console", "script/destroy", "script/generate", "script/txt2html", "setup.rb", "spec/httparty/request_spec.rb", "spec/httparty_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/deployment.rake", "tasks/environment.rake", "tasks/website.rake", "website/css/common.css", "website/index.html"]
|
12
14
|
s.has_rdoc = true
|
13
15
|
s.homepage = %q{http://httparty.rubyforge.org}
|
14
16
|
s.post_install_message = %q{When you HTTParty, you must party hard!}
|
15
17
|
s.rdoc_options = ["--main", "README.txt"]
|
16
18
|
s.require_paths = ["lib"]
|
17
19
|
s.rubyforge_project = %q{httparty}
|
18
|
-
s.rubygems_version = %q{1.
|
20
|
+
s.rubygems_version = %q{1.3.1}
|
19
21
|
s.summary = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
|
20
22
|
|
21
23
|
if s.respond_to? :specification_version then
|
22
24
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
25
|
s.specification_version = 2
|
24
26
|
|
25
|
-
if
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
28
|
s.add_runtime_dependency(%q<activesupport>, [">= 2.1"])
|
27
29
|
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
28
30
|
else
|
data/lib/httparty.rb
CHANGED
@@ -8,162 +8,88 @@ require 'active_support'
|
|
8
8
|
directory = File.dirname(__FILE__)
|
9
9
|
$:.unshift(directory) unless $:.include?(directory) || $:.include?(File.expand_path(directory))
|
10
10
|
|
11
|
+
require 'httparty/request'
|
12
|
+
|
11
13
|
module HTTParty
|
12
14
|
class UnsupportedFormat < StandardError; end
|
13
15
|
class RedirectionTooDeep < StandardError; end
|
16
|
+
|
17
|
+
AllowedFormats = {:xml => 'text/xml', :json => 'application/json', :html => 'text/html'}
|
14
18
|
|
15
19
|
def self.included(base)
|
16
20
|
base.extend ClassMethods
|
17
21
|
end
|
18
22
|
|
19
|
-
|
20
|
-
|
21
|
-
|
23
|
+
module ClassMethods
|
24
|
+
def default_options
|
25
|
+
@@default_options ||= {}
|
26
|
+
end
|
27
|
+
|
22
28
|
#
|
23
29
|
# Set an http proxy
|
24
30
|
#
|
25
31
|
# class Twitter
|
26
32
|
# include HTTParty
|
27
|
-
# http_proxy http://myProxy, 1080
|
33
|
+
# http_proxy 'http://myProxy', 1080
|
28
34
|
# ....
|
29
35
|
def http_proxy(addr=nil, port = nil)
|
30
|
-
|
31
|
-
|
36
|
+
default_options[:http_proxyaddr] = addr
|
37
|
+
default_options[:http_proxyport] = port
|
32
38
|
end
|
33
39
|
|
34
|
-
def base_uri(
|
35
|
-
return
|
36
|
-
|
40
|
+
def base_uri(uri=nil)
|
41
|
+
return default_options[:base_uri] unless uri
|
42
|
+
default_options[:base_uri] = normalize_base_uri(uri)
|
37
43
|
end
|
38
|
-
|
39
|
-
# Warning: This is not thread safe most likely and
|
40
|
-
# only works if you use one set of credentials. I
|
41
|
-
# leave it because it is convenient on some occasions.
|
44
|
+
|
42
45
|
def basic_auth(u, p)
|
43
|
-
|
46
|
+
default_options[:basic_auth] = {:username => u, :password => p}
|
44
47
|
end
|
45
48
|
|
46
|
-
# Updates the default query string parameters
|
47
|
-
# that should be appended to each request.
|
48
49
|
def default_params(h={})
|
49
50
|
raise ArgumentError, 'Default params must be a hash' unless h.is_a?(Hash)
|
50
|
-
|
51
|
-
|
52
|
-
@default_params.merge!(h)
|
51
|
+
default_options[:default_params] ||= {}
|
52
|
+
default_options[:default_params].merge!(h)
|
53
53
|
end
|
54
54
|
|
55
55
|
def headers(h={})
|
56
56
|
raise ArgumentError, 'Headers must be a hash' unless h.is_a?(Hash)
|
57
|
-
|
58
|
-
|
59
|
-
@headers.merge!(h)
|
57
|
+
default_options[:headers] ||= {}
|
58
|
+
default_options[:headers].merge!(h)
|
60
59
|
end
|
61
60
|
|
62
61
|
def format(f)
|
63
62
|
raise UnsupportedFormat, "Must be one of: #{AllowedFormats.keys.join(', ')}" unless AllowedFormats.key?(f)
|
64
|
-
|
63
|
+
default_options[:format] = f
|
65
64
|
end
|
66
65
|
|
67
|
-
# TODO: spec out this
|
68
66
|
def get(path, options={})
|
69
|
-
|
67
|
+
perform_request Net::HTTP::Get, path, options
|
70
68
|
end
|
71
69
|
|
72
|
-
# TODO: spec out this
|
73
70
|
def post(path, options={})
|
74
|
-
|
71
|
+
perform_request Net::HTTP::Post, path, options
|
75
72
|
end
|
76
73
|
|
77
|
-
# TODO: spec out this
|
78
74
|
def put(path, options={})
|
79
|
-
|
75
|
+
perform_request Net::HTTP::Put, path, options
|
80
76
|
end
|
81
77
|
|
82
|
-
# TODO: spec out this
|
83
78
|
def delete(path, options={})
|
84
|
-
|
79
|
+
perform_request Net::HTTP::Delete, path, options
|
85
80
|
end
|
86
|
-
|
87
|
-
private
|
88
|
-
def http(uri) #:nodoc:
|
89
|
-
http = Net::HTTP.new(uri.host, uri.port, @http_proxyaddr, @http_proxyport)
|
90
|
-
http.use_ssl = (uri.port == 443)
|
91
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
92
|
-
http
|
93
|
-
end
|
94
|
-
|
95
|
-
# FIXME: this method is doing way to much and needs to be split up
|
96
|
-
# options can be any or all of:
|
97
|
-
# query => hash of keys/values or a query string (foo=bar&baz=poo)
|
98
|
-
# body => hash of keys/values or a query string (foo=bar&baz=poo)
|
99
|
-
# headers => hash of headers to send request with
|
100
|
-
# basic_auth => :username and :password to use as basic http authentication (overrides @auth class instance variable)
|
101
|
-
# Raises exception Net::XXX (http error code) if an http error occured
|
102
|
-
def send_request(method, path, options={}) #:nodoc:
|
103
|
-
options = {:limit => 5}.merge(options)
|
104
|
-
options[:limit] = 0 if options.delete(:no_follow)
|
105
|
-
|
106
|
-
raise HTTParty::RedirectionTooDeep, 'HTTP redirects too deep' if options[:limit].to_i <= 0
|
107
|
-
raise ArgumentError, 'only get, post, put and delete methods are supported' unless %w[get post put delete].include?(method.to_s)
|
108
|
-
raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash)
|
109
|
-
raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].is_a?(Hash)
|
110
|
-
|
111
|
-
path = URI.parse(path)
|
112
|
-
uri = path.relative? ? URI.parse("#{base_uri}#{path}") : path
|
113
|
-
existing_query = uri.query ? "#{uri.query}&" : ''
|
114
|
-
uri.query = if options[:query].blank?
|
115
|
-
existing_query + default_params.to_query
|
116
|
-
else
|
117
|
-
existing_query + (options[:query].is_a?(Hash) ? default_params.merge(options[:query]).to_query : options[:query])
|
118
|
-
end
|
119
|
-
|
120
|
-
klass = Net::HTTP.const_get method.to_s.downcase.capitalize
|
121
|
-
request = klass.new(uri.request_uri)
|
122
|
-
request.body = options[:body].is_a?(Hash) ? options[:body].to_query : options[:body] unless options[:body].blank?
|
123
|
-
basic_auth = options.delete(:basic_auth) || @auth
|
124
|
-
request.initialize_http_header headers.merge(options[:headers] || {})
|
125
|
-
request.basic_auth(basic_auth[:username], basic_auth[:password]) if basic_auth
|
126
|
-
response = http(uri).request(request)
|
127
|
-
@format ||= format_from_mimetype(response['content-type'])
|
128
|
-
|
129
|
-
case response
|
130
|
-
when Net::HTTPSuccess
|
131
|
-
parse_response(response.body)
|
132
|
-
when Net::HTTPRedirection
|
133
|
-
options[:limit] -= 1
|
134
|
-
send_request(method, response['location'], options)
|
135
|
-
else
|
136
|
-
response.instance_eval { class << self; attr_accessor :body_parsed; end }
|
137
|
-
begin; response.body_parsed = parse_response(response.body); rescue; end
|
138
|
-
response.error! # raises exception corresponding to http error Net::XXX
|
139
|
-
end
|
140
81
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
return nil if body.nil? or body.empty?
|
145
|
-
case @format
|
146
|
-
when :xml
|
147
|
-
Hash.from_xml(body)
|
148
|
-
when :json
|
149
|
-
ActiveSupport::JSON.decode(body)
|
150
|
-
else
|
151
|
-
body
|
152
|
-
end
|
82
|
+
private
|
83
|
+
def perform_request(http_method, path, options) #:nodoc:
|
84
|
+
Request.new(http_method, path, default_options.merge(options)).perform
|
153
85
|
end
|
154
86
|
|
155
|
-
# Makes it so uri is sure to parse stuff like google.com
|
87
|
+
# Makes it so uri is sure to parse stuff like google.com without the http
|
156
88
|
def normalize_base_uri(url) #:nodoc:
|
157
89
|
use_ssl = (url =~ /^https/) || url.include?(':443')
|
158
90
|
url.chop! if url.ends_with?('/')
|
159
91
|
url.gsub!(/^https?:\/\//i, '')
|
160
92
|
"http#{'s' if use_ssl}://#{url}"
|
161
93
|
end
|
162
|
-
|
163
|
-
# Uses the HTTP Content-Type header to determine the format of the response
|
164
|
-
# It compares the MIME type returned to the types stored in the AllowedFormats hash
|
165
|
-
def format_from_mimetype(mimetype) #:nodoc:
|
166
|
-
AllowedFormats.each { |k, v| return k if mimetype.include?(v) }
|
167
|
-
end
|
168
94
|
end
|
169
|
-
end
|
95
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module HTTParty
|
2
|
+
class Request
|
3
|
+
SupportedHTTPMethods = [Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Put, Net::HTTP::Delete]
|
4
|
+
|
5
|
+
attr_accessor :http_method, :path, :options
|
6
|
+
|
7
|
+
def initialize(http_method, path, options={})
|
8
|
+
self.http_method = http_method
|
9
|
+
self.path = path
|
10
|
+
self.options = {
|
11
|
+
:limit => options.delete(:no_follow) ? 0 : 5,
|
12
|
+
:default_params => {},
|
13
|
+
}.merge(options.dup)
|
14
|
+
end
|
15
|
+
|
16
|
+
def path=(uri)
|
17
|
+
@path = URI.parse(uri)
|
18
|
+
end
|
19
|
+
|
20
|
+
def uri
|
21
|
+
uri = path.relative? ? URI.parse("#{options[:base_uri]}#{path}") : path
|
22
|
+
uri.query = query_string(uri)
|
23
|
+
uri
|
24
|
+
end
|
25
|
+
|
26
|
+
def perform
|
27
|
+
validate!
|
28
|
+
handle_response!(get_response(uri))
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def http(uri) #:nodoc:
|
33
|
+
http = Net::HTTP.new(uri.host, uri.port, options[:http_proxyaddr], options[:http_proxyport])
|
34
|
+
http.use_ssl = (uri.port == 443)
|
35
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
36
|
+
http
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_response(uri) #:nodoc:
|
40
|
+
request = http_method.new(uri.request_uri)
|
41
|
+
request.body = options[:body].is_a?(Hash) ? options[:body].to_query : options[:body] unless options[:body].blank?
|
42
|
+
request.initialize_http_header options[:headers]
|
43
|
+
request.basic_auth(options[:basic_auth][:username], options[:basic_auth][:password]) if options[:basic_auth]
|
44
|
+
response = http(uri).request(request)
|
45
|
+
options[:format] ||= format_from_mimetype(response['content-type'])
|
46
|
+
response
|
47
|
+
end
|
48
|
+
|
49
|
+
def query_string(uri) #:nodoc:
|
50
|
+
query_string_parts = []
|
51
|
+
query_string_parts << uri.query unless uri.query.blank?
|
52
|
+
|
53
|
+
if options[:query].is_a?(Hash)
|
54
|
+
query_string_parts << options[:default_params].merge(options[:query]).to_query
|
55
|
+
else
|
56
|
+
query_string_parts << options[:default_params].to_query unless options[:default_params].blank?
|
57
|
+
query_string_parts << options[:query] unless options[:query].blank?
|
58
|
+
end
|
59
|
+
|
60
|
+
query_string_parts.size > 0 ? query_string_parts.join('&') : nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# Raises exception Net::XXX (http error code) if an http error occured
|
64
|
+
def handle_response!(response) #:nodoc:
|
65
|
+
case response
|
66
|
+
when Net::HTTPSuccess
|
67
|
+
parse_response(response.body)
|
68
|
+
when Net::HTTPRedirection
|
69
|
+
options[:limit] -= 1
|
70
|
+
self.path = response['location']
|
71
|
+
perform
|
72
|
+
else
|
73
|
+
response.instance_eval { class << self; attr_accessor :body_parsed; end }
|
74
|
+
begin; response.body_parsed = parse_response(response.body); rescue; end
|
75
|
+
response.error! # raises exception corresponding to http error Net::XXX
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def parse_response(body) #:nodoc:
|
80
|
+
return nil if body.nil? or body.empty?
|
81
|
+
case options[:format]
|
82
|
+
when :xml
|
83
|
+
Hash.from_xml(body)
|
84
|
+
when :json
|
85
|
+
ActiveSupport::JSON.decode(body)
|
86
|
+
else
|
87
|
+
body
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Uses the HTTP Content-Type header to determine the format of the response
|
92
|
+
# It compares the MIME type returned to the types stored in the AllowedFormats hash
|
93
|
+
def format_from_mimetype(mimetype) #:nodoc:
|
94
|
+
AllowedFormats.each { |k, v| return k if mimetype.include?(v) }
|
95
|
+
end
|
96
|
+
|
97
|
+
def validate! #:nodoc:
|
98
|
+
raise HTTParty::RedirectionTooDeep, 'HTTP redirects too deep' if options[:limit].to_i <= 0
|
99
|
+
raise ArgumentError, 'only get, post, put and delete methods are supported' unless SupportedHTTPMethods.include?(http_method)
|
100
|
+
raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash)
|
101
|
+
raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].is_a?(Hash)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/lib/httparty/version.rb
CHANGED
@@ -0,0 +1,107 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe HTTParty::Request do
|
4
|
+
before do
|
5
|
+
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', :format => :xml)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'http' do
|
9
|
+
it "should use ssl for port 443" do
|
10
|
+
@request.send(:http, URI.parse('https://api.foo.com/v1:443')).use_ssl?.should == true
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should not use ssl for port 80' do
|
14
|
+
@request.send(:http, URI.parse('http://foobar.com')).use_ssl?.should == false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'parsing responses' do
|
19
|
+
it 'should handle xml automatically' do
|
20
|
+
xml = %q[<books><book><id>1234</id><name>Foo Bar!</name></book></books>]
|
21
|
+
@request.options[:format] = :xml
|
22
|
+
@request.send(:parse_response, xml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should handle json automatically' do
|
26
|
+
json = %q[{"books": {"book": {"name": "Foo Bar!", "id": "1234"}}}]
|
27
|
+
@request.options[:format] = :json
|
28
|
+
@request.send(:parse_response, json).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not attempt to parse empty responses" do
|
33
|
+
http = Net::HTTP.new('localhost', 80)
|
34
|
+
@request.stub!(:http).and_return(http)
|
35
|
+
response = Net::HTTPNoContent.new("1.1", 204, "No content for you")
|
36
|
+
response.stub!(:body).and_return(nil)
|
37
|
+
http.stub!(:request).and_return(response)
|
38
|
+
|
39
|
+
@request.options[:format] = :xml
|
40
|
+
@request.perform.should be_nil
|
41
|
+
|
42
|
+
response.stub!(:body).and_return("")
|
43
|
+
@request.perform.should be_nil
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "that respond with redirects" do
|
47
|
+
def setup_redirect
|
48
|
+
@http = Net::HTTP.new('localhost', 80)
|
49
|
+
@request.stub!(:http).and_return(@http)
|
50
|
+
@request.stub!(:uri).and_return(URI.parse("http://foo.com/foobar"))
|
51
|
+
@redirect = Net::HTTPFound.new("1.1", 302, "")
|
52
|
+
@redirect['location'] = '/foo'
|
53
|
+
end
|
54
|
+
|
55
|
+
def setup_ok_response
|
56
|
+
@ok = Net::HTTPOK.new("1.1", 200, "Content for you")
|
57
|
+
@ok.stub!(:body).and_return({"foo" => "bar"}.to_xml)
|
58
|
+
@http.should_receive(:request).and_return(@redirect, @ok)
|
59
|
+
@request.options[:format] = :xml
|
60
|
+
end
|
61
|
+
|
62
|
+
def setup_redirect_response
|
63
|
+
@http.stub!(:request).and_return(@redirect)
|
64
|
+
end
|
65
|
+
|
66
|
+
def setup_successful_redirect
|
67
|
+
setup_redirect
|
68
|
+
setup_ok_response
|
69
|
+
end
|
70
|
+
|
71
|
+
def setup_infinite_redirect
|
72
|
+
setup_redirect
|
73
|
+
setup_redirect_response
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should handle redirects for GET transparently" do
|
77
|
+
setup_successful_redirect
|
78
|
+
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should handle redirects for POST transparently" do
|
82
|
+
setup_successful_redirect
|
83
|
+
@request.http_method = Net::HTTP::Post
|
84
|
+
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should handle redirects for DELETE transparently" do
|
88
|
+
setup_successful_redirect
|
89
|
+
@request.http_method = Net::HTTP::Delete
|
90
|
+
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should handle redirects for PUT transparently" do
|
94
|
+
setup_successful_redirect
|
95
|
+
@request.http_method = Net::HTTP::Put
|
96
|
+
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should prevent infinite loops" do
|
100
|
+
setup_infinite_redirect
|
101
|
+
|
102
|
+
lambda do
|
103
|
+
@request.perform
|
104
|
+
end.should raise_error(HTTParty::RedirectionTooDeep)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
data/spec/httparty_spec.rb
CHANGED
@@ -13,6 +13,10 @@ end
|
|
13
13
|
describe HTTParty do
|
14
14
|
|
15
15
|
describe "base uri" do
|
16
|
+
before do
|
17
|
+
Foo.base_uri('api.foo.com/v1')
|
18
|
+
end
|
19
|
+
|
16
20
|
it "should have reader" do
|
17
21
|
Foo.base_uri.should == 'http://api.foo.com/v1'
|
18
22
|
end
|
@@ -65,19 +69,19 @@ describe HTTParty do
|
|
65
69
|
describe "basic http authentication" do
|
66
70
|
it "should work" do
|
67
71
|
Foo.basic_auth 'foobar', 'secret'
|
68
|
-
Foo.
|
72
|
+
Foo.default_options[:basic_auth].should == {:username => 'foobar', :password => 'secret'}
|
69
73
|
end
|
70
74
|
end
|
71
75
|
|
72
76
|
describe "format" do
|
73
77
|
it "should allow xml" do
|
74
78
|
Foo.format :xml
|
75
|
-
Foo.
|
79
|
+
Foo.default_options[:format].should == :xml
|
76
80
|
end
|
77
81
|
|
78
82
|
it "should allow json" do
|
79
83
|
Foo.format :json
|
80
|
-
Foo.
|
84
|
+
Foo.default_options[:format].should == :json
|
81
85
|
end
|
82
86
|
|
83
87
|
it 'should not allow funky format' do
|
@@ -86,136 +90,31 @@ describe HTTParty do
|
|
86
90
|
end.should raise_error(HTTParty::UnsupportedFormat)
|
87
91
|
end
|
88
92
|
end
|
89
|
-
|
90
|
-
describe
|
91
|
-
|
92
|
-
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'should not use ssl for port 80' do
|
96
|
-
Foo.send(:http, URI.parse('http://foobar.com')).use_ssl?.should == false
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
describe 'parsing responses' do
|
101
|
-
it 'should handle xml automatically' do
|
102
|
-
xml = %q[<books><book><id>1234</id><name>Foo Bar!</name></book></books>]
|
103
|
-
Foo.format :xml
|
104
|
-
Foo.send(:parse_response, xml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'should handle json automatically' do
|
108
|
-
json = %q[{"books": {"book": {"name": "Foo Bar!", "id": "1234"}}}]
|
109
|
-
Foo.format :json
|
110
|
-
Foo.send(:parse_response, json).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
describe "sending requests" do
|
115
|
-
it "should not work with request method other than get, post, put, delete" do
|
116
|
-
lambda do
|
117
|
-
Foo.send(:send_request, 'foo', '/foo')
|
118
|
-
end.should raise_error(ArgumentError)
|
119
|
-
end
|
120
|
-
|
121
|
-
it 'should require that :headers is a hash if present' do
|
93
|
+
|
94
|
+
describe "with explicit override of automatic redirect handling" do
|
95
|
+
|
96
|
+
it "should fail with redirected GET" do
|
122
97
|
lambda do
|
123
|
-
Foo.
|
124
|
-
end.should raise_error(
|
98
|
+
Foo.get('/foo', :no_follow => true)
|
99
|
+
end.should raise_error(HTTParty::RedirectionTooDeep)
|
125
100
|
end
|
126
|
-
|
127
|
-
it
|
101
|
+
|
102
|
+
it "should fail with redirected POST" do
|
128
103
|
lambda do
|
129
|
-
Foo.
|
130
|
-
end.should raise_error(
|
104
|
+
Foo.post('/foo', :no_follow => true)
|
105
|
+
end.should raise_error(HTTParty::RedirectionTooDeep)
|
131
106
|
end
|
132
107
|
|
133
|
-
it "should
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
response.stub!(:body).and_return(nil)
|
138
|
-
http.stub!(:request).and_return(response)
|
139
|
-
|
140
|
-
Foo.headers.clear # clear out bogus settings from other specs
|
141
|
-
Foo.format :xml
|
142
|
-
Foo.send(:send_request, 'get', '/bar').should be_nil
|
143
|
-
|
144
|
-
response.stub!(:body).and_return("")
|
145
|
-
Foo.send(:send_request, 'get', 'bar').should be_nil
|
108
|
+
it "should fail with redirected DELETE" do
|
109
|
+
lambda do
|
110
|
+
Foo.delete('/foo', :no_follow => true)
|
111
|
+
end.should raise_error(HTTParty::RedirectionTooDeep)
|
146
112
|
end
|
147
113
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
@redirect = Net::HTTPFound.new("1.1", 302, "")
|
153
|
-
@redirect.stub!(:[]).with('location').and_return('/foo')
|
154
|
-
@ok = Net::HTTPOK.new("1.1", 200, "Content for you")
|
155
|
-
@ok.stub!(:body).and_return({"foo" => "bar"}.to_xml)
|
156
|
-
@http.should_receive(:request).and_return(@redirect, @ok)
|
157
|
-
Foo.headers.clear
|
158
|
-
Foo.format :xml
|
159
|
-
end
|
160
|
-
|
161
|
-
it "should handle redirects for GET transparently" do
|
162
|
-
setup_http
|
163
|
-
Foo.get('/foo/').should == {"hash" => {"foo" => "bar"}}
|
164
|
-
end
|
165
|
-
|
166
|
-
it "should handle redirects for POST transparently" do
|
167
|
-
setup_http
|
168
|
-
Foo.post('/foo/', {:foo => :bar}).should == {"hash" => {"foo" => "bar"}}
|
169
|
-
end
|
170
|
-
|
171
|
-
it "should handle redirects for DELETE transparently" do
|
172
|
-
setup_http
|
173
|
-
Foo.delete('/foo/').should == {"hash" => {"foo" => "bar"}}
|
174
|
-
end
|
175
|
-
|
176
|
-
it "should handle redirects for PUT transparently" do
|
177
|
-
setup_http
|
178
|
-
Foo.put('/foo/').should == {"hash" => {"foo" => "bar"}}
|
179
|
-
end
|
180
|
-
|
181
|
-
it "should prevent infinite loops" do
|
182
|
-
http = Net::HTTP.new('localhost', 80)
|
183
|
-
Foo.stub!(:http).and_return(http)
|
184
|
-
redirect = Net::HTTPFound.new("1.1", "302", "Look, over there!")
|
185
|
-
redirect.stub!(:[]).with('location').and_return('/foo')
|
186
|
-
http.stub!(:request).and_return(redirect)
|
187
|
-
|
188
|
-
lambda do
|
189
|
-
Foo.send(:send_request, 'get', '/foo')
|
190
|
-
end.should raise_error(HTTParty::RedirectionTooDeep)
|
191
|
-
end
|
192
|
-
|
193
|
-
describe "with explicit override of automatic redirect handling" do
|
194
|
-
|
195
|
-
it "should fail with redirected GET" do
|
196
|
-
lambda do
|
197
|
-
Foo.get('/foo', :no_follow => true)
|
198
|
-
end.should raise_error(HTTParty::RedirectionTooDeep)
|
199
|
-
end
|
200
|
-
|
201
|
-
it "should fail with redirected POST" do
|
202
|
-
lambda do
|
203
|
-
Foo.post('/foo', :no_follow => true)
|
204
|
-
end.should raise_error(HTTParty::RedirectionTooDeep)
|
205
|
-
end
|
206
|
-
|
207
|
-
it "should fail with redirected DELETE" do
|
208
|
-
lambda do
|
209
|
-
Foo.delete('/foo', :no_follow => true)
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
it "should fail with redirected PUT" do
|
214
|
-
lambda do
|
215
|
-
Foo.put('/foo', :no_follow => true)
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
114
|
+
it "should fail with redirected PUT" do
|
115
|
+
lambda do
|
116
|
+
Foo.put('/foo', :no_follow => true)
|
117
|
+
end.should raise_error(HTTParty::RedirectionTooDeep)
|
219
118
|
end
|
220
119
|
end
|
221
|
-
end
|
120
|
+
end
|
data/spec/spec.opts
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jnunemaker-httparty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-11-
|
12
|
+
date: 2008-11-14 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -59,13 +59,14 @@ files:
|
|
59
59
|
- examples/whoismyrep.rb
|
60
60
|
- httparty.gemspec
|
61
61
|
- lib/httparty.rb
|
62
|
+
- lib/httparty/request.rb
|
62
63
|
- lib/httparty/version.rb
|
63
64
|
- script/console
|
64
65
|
- script/destroy
|
65
66
|
- script/generate
|
66
67
|
- script/txt2html
|
67
68
|
- setup.rb
|
68
|
-
- spec/
|
69
|
+
- spec/httparty/request_spec.rb
|
69
70
|
- spec/httparty_spec.rb
|
70
71
|
- spec/spec.opts
|
71
72
|
- spec/spec_helper.rb
|