ddollar-httparty 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
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