ddollar-httparty 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/.gitignore +6 -0
  2. data/History +141 -0
  3. data/MIT-LICENSE +20 -0
  4. data/Manifest +47 -0
  5. data/README.rdoc +54 -0
  6. data/Rakefile +71 -0
  7. data/VERSION +1 -0
  8. data/bin/httparty +98 -0
  9. data/cucumber.yml +1 -0
  10. data/examples/aaws.rb +32 -0
  11. data/examples/basic.rb +11 -0
  12. data/examples/delicious.rb +37 -0
  13. data/examples/google.rb +16 -0
  14. data/examples/rubyurl.rb +14 -0
  15. data/examples/twitter.rb +31 -0
  16. data/examples/whoismyrep.rb +10 -0
  17. data/features/basic_authentication.feature +20 -0
  18. data/features/command_line.feature +7 -0
  19. data/features/deals_with_http_error_codes.feature +26 -0
  20. data/features/handles_multiple_formats.feature +34 -0
  21. data/features/steps/env.rb +16 -0
  22. data/features/steps/httparty_response_steps.rb +26 -0
  23. data/features/steps/httparty_steps.rb +19 -0
  24. data/features/steps/mongrel_helper.rb +56 -0
  25. data/features/steps/remote_service_steps.rb +52 -0
  26. data/features/supports_redirection.feature +22 -0
  27. data/features/supports_timeout_option.feature +12 -0
  28. data/httparty.gemspec +110 -0
  29. data/lib/httparty.rb +216 -0
  30. data/lib/httparty/cookie_hash.rb +22 -0
  31. data/lib/httparty/core_extensions.rb +25 -0
  32. data/lib/httparty/exceptions.rb +7 -0
  33. data/lib/httparty/module_inheritable_attributes.rb +25 -0
  34. data/lib/httparty/parsers.rb +31 -0
  35. data/lib/httparty/request.rb +175 -0
  36. data/lib/httparty/response.rb +18 -0
  37. data/lib/httparty/version.rb +3 -0
  38. data/spec/fixtures/delicious.xml +23 -0
  39. data/spec/fixtures/empty.xml +0 -0
  40. data/spec/fixtures/google.html +3 -0
  41. data/spec/fixtures/twitter.json +1 -0
  42. data/spec/fixtures/twitter.xml +403 -0
  43. data/spec/fixtures/undefined_method_add_node_for_nil.xml +2 -0
  44. data/spec/httparty/cookie_hash_spec.rb +71 -0
  45. data/spec/httparty/request_spec.rb +244 -0
  46. data/spec/httparty/response_spec.rb +62 -0
  47. data/spec/httparty_spec.rb +328 -0
  48. data/spec/spec.opts +2 -0
  49. data/spec/spec_helper.rb +24 -0
  50. data/website/css/common.css +47 -0
  51. data/website/index.html +73 -0
  52. metadata +135 -0
@@ -0,0 +1,12 @@
1
+ Feature: Supports the timeout option
2
+ In order to handle inappropriately slow response times
3
+ As a developer
4
+ I want my request to raise an exception after my specified timeout as elapsed
5
+
6
+ Scenario: A long running response
7
+ Given a remote service that returns '<h1>Some HTML</h1>'
8
+ And that service is accessed at the path '/service.html'
9
+ And that service takes 2 seconds to generate a response
10
+ When I set my HTTParty timeout option to 1
11
+ And I call HTTParty#get with '/service.html'
12
+ Then it should raise a Timeout::Error exception
data/httparty.gemspec ADDED
@@ -0,0 +1,110 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{httparty}
8
+ s.version = "0.4.6"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["John Nunemaker", "Sandro Turriate"]
12
+ s.date = %q{2009-09-22}
13
+ s.default_executable = %q{httparty}
14
+ s.description = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
15
+ s.email = %q{nunemaker@gmail.com}
16
+ s.executables = ["httparty"]
17
+ s.extra_rdoc_files = [
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".gitignore",
22
+ "History",
23
+ "MIT-LICENSE",
24
+ "Manifest",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/httparty",
29
+ "cucumber.yml",
30
+ "examples/aaws.rb",
31
+ "examples/basic.rb",
32
+ "examples/delicious.rb",
33
+ "examples/google.rb",
34
+ "examples/rubyurl.rb",
35
+ "examples/twitter.rb",
36
+ "examples/whoismyrep.rb",
37
+ "features/basic_authentication.feature",
38
+ "features/command_line.feature",
39
+ "features/deals_with_http_error_codes.feature",
40
+ "features/handles_multiple_formats.feature",
41
+ "features/steps/env.rb",
42
+ "features/steps/httparty_response_steps.rb",
43
+ "features/steps/httparty_steps.rb",
44
+ "features/steps/mongrel_helper.rb",
45
+ "features/steps/remote_service_steps.rb",
46
+ "features/supports_redirection.feature",
47
+ "features/supports_timeout_option.feature",
48
+ "httparty.gemspec",
49
+ "lib/httparty.rb",
50
+ "lib/httparty/cookie_hash.rb",
51
+ "lib/httparty/core_extensions.rb",
52
+ "lib/httparty/exceptions.rb",
53
+ "lib/httparty/module_inheritable_attributes.rb",
54
+ "lib/httparty/parsers.rb",
55
+ "lib/httparty/request.rb",
56
+ "lib/httparty/response.rb",
57
+ "lib/httparty/version.rb",
58
+ "spec/fixtures/delicious.xml",
59
+ "spec/fixtures/empty.xml",
60
+ "spec/fixtures/google.html",
61
+ "spec/fixtures/twitter.json",
62
+ "spec/fixtures/twitter.xml",
63
+ "spec/fixtures/undefined_method_add_node_for_nil.xml",
64
+ "spec/httparty/cookie_hash_spec.rb",
65
+ "spec/httparty/request_spec.rb",
66
+ "spec/httparty/response_spec.rb",
67
+ "spec/httparty_spec.rb",
68
+ "spec/spec.opts",
69
+ "spec/spec_helper.rb",
70
+ "website/css/common.css",
71
+ "website/index.html"
72
+ ]
73
+ s.homepage = %q{http://httparty.rubyforge.org}
74
+ s.post_install_message = %q{When you HTTParty, you must party hard!}
75
+ s.rdoc_options = ["--charset=UTF-8"]
76
+ s.require_paths = ["lib"]
77
+ s.rubyforge_project = %q{httparty}
78
+ s.rubygems_version = %q{1.3.5}
79
+ s.summary = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
80
+ s.test_files = [
81
+ "spec/httparty/cookie_hash_spec.rb",
82
+ "spec/httparty/request_spec.rb",
83
+ "spec/httparty/response_spec.rb",
84
+ "spec/httparty_spec.rb",
85
+ "spec/spec_helper.rb",
86
+ "examples/aaws.rb",
87
+ "examples/basic.rb",
88
+ "examples/delicious.rb",
89
+ "examples/google.rb",
90
+ "examples/rubyurl.rb",
91
+ "examples/twitter.rb",
92
+ "examples/whoismyrep.rb"
93
+ ]
94
+
95
+ if s.respond_to? :specification_version then
96
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
97
+ s.specification_version = 3
98
+
99
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
100
+ s.add_runtime_dependency(%q<crack>, [">= 0.1.1"])
101
+ s.add_development_dependency(%q<rspec>, ["= 1.2.8"])
102
+ else
103
+ s.add_dependency(%q<crack>, [">= 0.1.1"])
104
+ s.add_dependency(%q<rspec>, ["= 1.2.8"])
105
+ end
106
+ else
107
+ s.add_dependency(%q<crack>, [">= 0.1.1"])
108
+ s.add_dependency(%q<rspec>, ["= 1.2.8"])
109
+ end
110
+ end
data/lib/httparty.rb ADDED
@@ -0,0 +1,216 @@
1
+ require 'pathname'
2
+ require 'net/http'
3
+ require 'net/https'
4
+ require 'rubygems'
5
+ gem 'crack', '>= 0.1.1'
6
+ require 'crack'
7
+
8
+ dir = Pathname(__FILE__).dirname.expand_path
9
+
10
+ require dir + 'httparty/module_inheritable_attributes'
11
+ require dir + 'httparty/cookie_hash'
12
+
13
+ module HTTParty
14
+
15
+ AllowedFormats = {
16
+ 'text/xml' => :xml,
17
+ 'application/xml' => :xml,
18
+ 'application/json' => :json,
19
+ 'text/json' => :json,
20
+ 'application/javascript' => :json,
21
+ 'text/javascript' => :json,
22
+ 'text/html' => :html,
23
+ 'application/x-yaml' => :yaml,
24
+ 'text/yaml' => :yaml,
25
+ 'text/plain' => :plain
26
+ } unless defined?(AllowedFormats)
27
+
28
+ def self.included(base)
29
+ base.extend ClassMethods
30
+ base.send :include, HTTParty::ModuleInheritableAttributes
31
+ base.send(:mattr_inheritable, :default_options)
32
+ base.send(:mattr_inheritable, :default_cookies)
33
+ base.instance_variable_set("@default_options", {})
34
+ base.instance_variable_set("@default_cookies", CookieHash.new)
35
+ end
36
+
37
+ module ClassMethods
38
+ # Allows setting http proxy information to be used
39
+ #
40
+ # class Foo
41
+ # include HTTParty
42
+ # http_proxy 'http://foo.com', 80
43
+ # end
44
+ def http_proxy(addr=nil, port = nil)
45
+ default_options[:http_proxyaddr] = addr
46
+ default_options[:http_proxyport] = port
47
+ end
48
+
49
+ # Allows setting a base uri to be used for each request.
50
+ # Will normalize uri to include http, etc.
51
+ #
52
+ # class Foo
53
+ # include HTTParty
54
+ # base_uri 'twitter.com'
55
+ # end
56
+ def base_uri(uri=nil)
57
+ return default_options[:base_uri] unless uri
58
+ default_options[:base_uri] = HTTParty.normalize_base_uri(uri)
59
+ end
60
+
61
+ # Allows setting basic authentication username and password.
62
+ #
63
+ # class Foo
64
+ # include HTTParty
65
+ # basic_auth 'username', 'password'
66
+ # end
67
+ def basic_auth(u, p)
68
+ default_options[:basic_auth] = {:username => u, :password => p}
69
+ end
70
+
71
+ # Allows setting default parameters to be appended to each request.
72
+ # Great for api keys and such.
73
+ #
74
+ # class Foo
75
+ # include HTTParty
76
+ # default_params :api_key => 'secret', :another => 'foo'
77
+ # end
78
+ def default_params(h={})
79
+ raise ArgumentError, 'Default params must be a hash' unless h.is_a?(Hash)
80
+ default_options[:default_params] ||= {}
81
+ default_options[:default_params].merge!(h)
82
+ end
83
+
84
+ # Allows setting a base uri to be used for each request.
85
+ #
86
+ # class Foo
87
+ # include HTTParty
88
+ # headers 'Accept' => 'text/html'
89
+ # end
90
+ def headers(h={})
91
+ raise ArgumentError, 'Headers must be a hash' unless h.is_a?(Hash)
92
+ default_options[:headers] ||= {}
93
+ default_options[:headers].merge!(h)
94
+ end
95
+
96
+ def cookies(h={})
97
+ raise ArgumentError, 'Cookies must be a hash' unless h.is_a?(Hash)
98
+ default_cookies.add_cookies(h)
99
+ end
100
+
101
+ # Allows setting the format with which to parse.
102
+ # Must be one of the allowed formats ie: json, xml
103
+ #
104
+ # class Foo
105
+ # include HTTParty
106
+ # format :json
107
+ # end
108
+ def format(f)
109
+ raise UnsupportedFormat, "Must be one of: #{AllowedFormats.values.map { |v| v.to_s }.uniq.sort.join(', ')}" unless AllowedFormats.value?(f)
110
+ default_options[:format] = f
111
+ end
112
+
113
+ # Allows setting a custom parser for the response.
114
+ #
115
+ # class Foo
116
+ # include HTTParty
117
+ # parser Proc.new {|data| ...}
118
+ # end
119
+ def parser(customer_parser)
120
+ default_options[:parser] = customer_parser
121
+ end
122
+
123
+ # Allows making a get request to a url.
124
+ #
125
+ # class Foo
126
+ # include HTTParty
127
+ # end
128
+ #
129
+ # # Simple get with full url
130
+ # Foo.get('http://foo.com/resource.json')
131
+ #
132
+ # # Simple get with full url and query parameters
133
+ # # ie: http://foo.com/resource.json?limit=10
134
+ # Foo.get('http://foo.com/resource.json', :query => {:limit => 10})
135
+ def get(path, options={})
136
+ perform_request Net::HTTP::Get, path, options
137
+ end
138
+
139
+ # Allows making a post request to a url.
140
+ #
141
+ # class Foo
142
+ # include HTTParty
143
+ # end
144
+ #
145
+ # # Simple post with full url and setting the body
146
+ # Foo.post('http://foo.com/resources', :body => {:bar => 'baz'})
147
+ #
148
+ # # Simple post with full url using :query option,
149
+ # # which gets set as form data on the request.
150
+ # Foo.post('http://foo.com/resources', :query => {:bar => 'baz'})
151
+ def post(path, options={})
152
+ perform_request Net::HTTP::Post, path, options
153
+ end
154
+
155
+ def put(path, options={})
156
+ perform_request Net::HTTP::Put, path, options
157
+ end
158
+
159
+ def delete(path, options={})
160
+ perform_request Net::HTTP::Delete, path, options
161
+ end
162
+
163
+ def default_options #:nodoc:
164
+ @default_options
165
+ end
166
+
167
+ private
168
+ def perform_request(http_method, path, options) #:nodoc:
169
+ options = default_options.dup.merge(options)
170
+ process_cookies(options)
171
+ Request.new(http_method, path, options).perform
172
+ end
173
+
174
+ def process_cookies(options) #:nodoc:
175
+ return unless options[:cookies] || default_cookies.any?
176
+ options[:headers] ||= headers.dup
177
+ options[:headers]["cookie"] = cookies.merge(options.delete(:cookies) || {}).to_cookie_string
178
+ end
179
+ end
180
+
181
+ def self.normalize_base_uri(url) #:nodoc:
182
+ normalized_url = url.dup
183
+ use_ssl = (normalized_url =~ /^https/) || normalized_url.include?(':443')
184
+ ends_with_slash = normalized_url =~ /\/$/
185
+
186
+ normalized_url.chop! if ends_with_slash
187
+ normalized_url.gsub!(/^https?:\/\//i, '')
188
+
189
+ "http#{'s' if use_ssl}://#{normalized_url}"
190
+ end
191
+
192
+ class Basement #:nodoc:
193
+ include HTTParty
194
+ end
195
+
196
+ def self.get(*args)
197
+ Basement.get(*args)
198
+ end
199
+
200
+ def self.post(*args)
201
+ Basement.post(*args)
202
+ end
203
+
204
+ def self.put(*args)
205
+ Basement.put(*args)
206
+ end
207
+
208
+ def self.delete(*args)
209
+ Basement.delete(*args)
210
+ end
211
+ end
212
+
213
+ require dir + 'httparty/core_extensions'
214
+ require dir + 'httparty/exceptions'
215
+ require dir + 'httparty/request'
216
+ require dir + 'httparty/response'
@@ -0,0 +1,22 @@
1
+ class HTTParty::CookieHash < Hash #:nodoc:
2
+
3
+ CLIENT_COOKIES = %w{path expires domain path secure HTTPOnly}
4
+
5
+ def add_cookies(value)
6
+ case value
7
+ when Hash
8
+ merge!(value)
9
+ when String
10
+ value.split('; ').each do |cookie|
11
+ array = cookie.split('=')
12
+ self[array[0].to_sym] = array[1]
13
+ end
14
+ else
15
+ raise "add_cookies only takes a Hash or a String"
16
+ end
17
+ end
18
+
19
+ def to_cookie_string
20
+ delete_if { |k, v| CLIENT_COOKIES.include?(k.to_s) }.collect { |k, v| "#{k}=#{v}" }.join("; ")
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ class HTTParty::BasicObject #:nodoc:
2
+ instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval/ }
3
+ end
4
+
5
+ # 1.8.6 has mistyping of transitive in if statement
6
+ require "rexml/document"
7
+ module REXML #:nodoc:
8
+ class Document < Element #:nodoc:
9
+ def write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
10
+ if xml_decl.encoding != "UTF-8" && !output.kind_of?(Output)
11
+ output = Output.new( output, xml_decl.encoding )
12
+ end
13
+ formatter = if indent > -1
14
+ if transitive
15
+ REXML::Formatters::Transitive.new( indent, ie_hack )
16
+ else
17
+ REXML::Formatters::Pretty.new( indent, ie_hack )
18
+ end
19
+ else
20
+ REXML::Formatters::Default.new( ie_hack )
21
+ end
22
+ formatter.write( self, output )
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ module HTTParty
2
+ # Exception raised when you attempt to set a non-existant format
3
+ class UnsupportedFormat < StandardError; end
4
+
5
+ # Exception that is raised when request has redirected too many times
6
+ class RedirectionTooDeep < StandardError; end
7
+ end
@@ -0,0 +1,25 @@
1
+ module HTTParty
2
+ module ModuleInheritableAttributes #:nodoc:
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods #:nodoc:
8
+ def mattr_inheritable(*args)
9
+ @mattr_inheritable_attrs ||= [:mattr_inheritable_attrs]
10
+ @mattr_inheritable_attrs += args
11
+ args.each do |arg|
12
+ module_eval %(class << self; attr_accessor :#{arg} end)
13
+ end
14
+ @mattr_inheritable_attrs
15
+ end
16
+
17
+ def inherited(subclass)
18
+ @mattr_inheritable_attrs.each do |inheritable_attribute|
19
+ instance_var = "@#{inheritable_attribute}"
20
+ subclass.instance_variable_set(instance_var, instance_variable_get(instance_var))
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ module HTTParty
2
+ module Xml
3
+ def self.parse(body)
4
+ Crack::XML.parse(body)
5
+ end
6
+ end
7
+
8
+ module Json
9
+ def self.parse(body)
10
+ Crack::JSON.parse(body)
11
+ end
12
+ end
13
+
14
+ module Yaml
15
+ def self.parse(str)
16
+ ::YAML.load(str)
17
+ end
18
+ end
19
+
20
+ module Html
21
+ def self.parse(str)
22
+ str
23
+ end
24
+ end
25
+
26
+ module Text
27
+ def self.parse(str)
28
+ str
29
+ end
30
+ end
31
+ end