dnclabs-httparty 0.6.1.2010090201

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 (69) hide show
  1. data/.gitignore +7 -0
  2. data/History +216 -0
  3. data/MIT-LICENSE +20 -0
  4. data/Manifest +47 -0
  5. data/README.rdoc +54 -0
  6. data/Rakefile +89 -0
  7. data/VERSION +1 -0
  8. data/bin/httparty +108 -0
  9. data/cucumber.yml +1 -0
  10. data/examples/aaws.rb +32 -0
  11. data/examples/basic.rb +11 -0
  12. data/examples/custom_parsers.rb +67 -0
  13. data/examples/delicious.rb +37 -0
  14. data/examples/google.rb +16 -0
  15. data/examples/rubyurl.rb +14 -0
  16. data/examples/twitter.rb +31 -0
  17. data/examples/whoismyrep.rb +10 -0
  18. data/features/basic_authentication.feature +20 -0
  19. data/features/command_line.feature +7 -0
  20. data/features/deals_with_http_error_codes.feature +26 -0
  21. data/features/digest_authentication.feature +20 -0
  22. data/features/handles_compressed_responses.feature +19 -0
  23. data/features/handles_multiple_formats.feature +34 -0
  24. data/features/steps/env.rb +23 -0
  25. data/features/steps/httparty_response_steps.rb +26 -0
  26. data/features/steps/httparty_steps.rb +27 -0
  27. data/features/steps/mongrel_helper.rb +94 -0
  28. data/features/steps/remote_service_steps.rb +69 -0
  29. data/features/supports_redirection.feature +22 -0
  30. data/features/supports_timeout_option.feature +13 -0
  31. data/httparty.gemspec +146 -0
  32. data/lib/httparty.rb +365 -0
  33. data/lib/httparty/cookie_hash.rb +22 -0
  34. data/lib/httparty/core_extensions.rb +31 -0
  35. data/lib/httparty/exceptions.rb +26 -0
  36. data/lib/httparty/module_inheritable_attributes.rb +34 -0
  37. data/lib/httparty/net_digest_auth.rb +35 -0
  38. data/lib/httparty/parser.rb +141 -0
  39. data/lib/httparty/request.rb +231 -0
  40. data/lib/httparty/response.rb +79 -0
  41. data/spec/fixtures/delicious.xml +23 -0
  42. data/spec/fixtures/empty.xml +0 -0
  43. data/spec/fixtures/google.html +3 -0
  44. data/spec/fixtures/ssl/generate.sh +29 -0
  45. data/spec/fixtures/ssl/generated/1fe462c2.0 +15 -0
  46. data/spec/fixtures/ssl/generated/bogushost.crt +13 -0
  47. data/spec/fixtures/ssl/generated/ca.crt +15 -0
  48. data/spec/fixtures/ssl/generated/ca.key +15 -0
  49. data/spec/fixtures/ssl/generated/selfsigned.crt +14 -0
  50. data/spec/fixtures/ssl/generated/server.crt +13 -0
  51. data/spec/fixtures/ssl/generated/server.key +15 -0
  52. data/spec/fixtures/ssl/openssl-exts.cnf +9 -0
  53. data/spec/fixtures/twitter.json +1 -0
  54. data/spec/fixtures/twitter.xml +403 -0
  55. data/spec/fixtures/undefined_method_add_node_for_nil.xml +2 -0
  56. data/spec/httparty/cookie_hash_spec.rb +71 -0
  57. data/spec/httparty/parser_spec.rb +155 -0
  58. data/spec/httparty/request_spec.rb +430 -0
  59. data/spec/httparty/response_spec.rb +188 -0
  60. data/spec/httparty/ssl_spec.rb +54 -0
  61. data/spec/httparty_spec.rb +570 -0
  62. data/spec/spec.opts +3 -0
  63. data/spec/spec_helper.rb +20 -0
  64. data/spec/support/ssl_test_helper.rb +25 -0
  65. data/spec/support/ssl_test_server.rb +69 -0
  66. data/spec/support/stub_response.rb +30 -0
  67. data/website/css/common.css +47 -0
  68. data/website/index.html +73 -0
  69. metadata +245 -0
@@ -0,0 +1,94 @@
1
+ require 'base64'
2
+ class BasicMongrelHandler < Mongrel::HttpHandler
3
+ attr_accessor :content_type, :custom_headers, :response_body, :response_code, :preprocessor, :username, :password
4
+
5
+ def initialize
6
+ @content_type = "text/html"
7
+ @response_body = ""
8
+ @response_code = 200
9
+ @custom_headers = {}
10
+ end
11
+
12
+ def process(request, response)
13
+ instance_eval &preprocessor if preprocessor
14
+ reply_with(response, response_code, response_body)
15
+ end
16
+
17
+ def reply_with(response, code, response_body)
18
+ response.start(code) do |head, body|
19
+ head["Content-Type"] = content_type
20
+ custom_headers.each { |k,v| head[k] = v }
21
+ body.write(response_body)
22
+ end
23
+ end
24
+ end
25
+
26
+ class DeflateHandler < BasicMongrelHandler
27
+ def process(request, response)
28
+ response.start do |head, body|
29
+ head['Content-Encoding'] = 'deflate'
30
+ body.write Zlib::Deflate.deflate(response_body)
31
+ end
32
+ end
33
+ end
34
+
35
+ class GzipHandler < BasicMongrelHandler
36
+ def process(request, response)
37
+ response.start do |head, body|
38
+ head['Content-Encoding'] = 'gzip'
39
+ body.write gzip(response_body)
40
+ end
41
+ end
42
+
43
+ protected
44
+
45
+ def gzip(string)
46
+ sio = StringIO.new('', 'r+')
47
+ gz = Zlib::GzipWriter.new sio
48
+ gz.write string
49
+ gz.finish
50
+ sio.rewind
51
+ sio.read
52
+ end
53
+ end
54
+
55
+ module BasicAuthentication
56
+ def self.extended(base)
57
+ base.custom_headers["WWW-Authenticate"] = 'Basic Realm="Super Secret Page"'
58
+ end
59
+
60
+ def process(request, response)
61
+ if authorized?(request)
62
+ super
63
+ else
64
+ reply_with(response, 401, "Incorrect. You have 20 seconds to comply.")
65
+ end
66
+ end
67
+
68
+ def authorized?(request)
69
+ request.params["HTTP_AUTHORIZATION"] == "Basic " + Base64.encode64("#{@username}:#{@password}").strip
70
+ end
71
+ end
72
+
73
+ module DigestAuthentication
74
+ def self.extended(base)
75
+ base.custom_headers["WWW-Authenticate"] = 'Digest realm="testrealm@host.com",qop="auth,auth-int",nonce="nonce",opaque="opaque"'
76
+ end
77
+
78
+ def process(request, response)
79
+ if authorized?(request)
80
+ super
81
+ else
82
+ reply_with(response, 401, "Incorrect. You have 20 seconds to comply.")
83
+ end
84
+ end
85
+
86
+ def authorized?(request)
87
+ request.params["HTTP_AUTHORIZATION"] =~ /Digest.*uri=/
88
+ end
89
+ end
90
+
91
+ def new_mongrel_redirector(target_url, relative_path = false)
92
+ target_url = "http://#{@host_and_port}#{target_url}" unless relative_path
93
+ Mongrel::RedirectHandler.new(target_url)
94
+ end
@@ -0,0 +1,69 @@
1
+ Given /a remote service that returns '(.*)'/ do |response_body|
2
+ @handler = BasicMongrelHandler.new
3
+ Given "the response from the service has a body of '#{response_body}'"
4
+ end
5
+
6
+ Given /a remote service that returns a (\d+) status code/ do |code|
7
+ @handler = BasicMongrelHandler.new
8
+ @handler.response_code = code
9
+ end
10
+
11
+ Given /that service is accessed at the path '(.*)'/ do |path|
12
+ @server.register(path, @handler)
13
+ end
14
+
15
+ Given /^that service takes (\d+) seconds to generate a response$/ do |time|
16
+ @server_response_time = time.to_i
17
+ @handler.preprocessor = lambda { sleep time.to_i }
18
+ end
19
+
20
+ Given /^a remote deflate service$/ do
21
+ @handler = DeflateHandler.new
22
+ end
23
+
24
+ Given /^a remote gzip service$/ do
25
+ @handler = GzipHandler.new
26
+ end
27
+
28
+ Given /the response from the service has a Content-Type of '(.*)'/ do |content_type|
29
+ @handler.content_type = content_type
30
+ end
31
+
32
+ Given /the response from the service has a body of '(.*)'/ do |response_body|
33
+ @handler.response_body = response_body
34
+ end
35
+
36
+ Given /the url '(.*)' redirects to '(.*)'/ do |redirection_url, target_url|
37
+ @server.register redirection_url, new_mongrel_redirector(target_url)
38
+ end
39
+
40
+ Given /that service is protected by Basic Authentication/ do
41
+ @handler.extend BasicAuthentication
42
+ end
43
+
44
+ Given /that service is protected by Digest Authentication/ do
45
+ @handler.extend DigestAuthentication
46
+ end
47
+
48
+ Given /that service requires the username '(.*)' with the password '(.*)'/ do |username, password|
49
+ @handler.username = username
50
+ @handler.password = password
51
+ end
52
+
53
+ Given /a restricted page at '(.*)'/ do |url|
54
+ Given "a remote service that returns 'A response I will never see'"
55
+ And "that service is accessed at the path '#{url}'"
56
+ And "that service is protected by Basic Authentication"
57
+ And "that service requires the username 'something' with the password 'secret'"
58
+ end
59
+
60
+ # This joins the server thread, and halts cucumber, so you can actually hit the
61
+ # server with a browser. Runs until you kill it with Ctrl-c
62
+ Given /I want to hit this in a browser/ do
63
+ @server.acceptor.join
64
+ end
65
+
66
+ Then /I wait for the server to recover/ do
67
+ timeout = @request_options[:timeout] || 0
68
+ sleep @server_response_time - timeout
69
+ end
@@ -0,0 +1,22 @@
1
+ Feature: Supports Redirection
2
+
3
+ As a developer
4
+ I want to work with services that may redirect me
5
+ And I want it to follow a reasonable number of redirects
6
+ Because sometimes web services do that
7
+
8
+ Scenario: A service that redirects once
9
+ Given a remote service that returns 'Service Response'
10
+ And that service is accessed at the path '/landing_service.html'
11
+ And the url '/redirector.html' redirects to '/landing_service.html'
12
+ When I call HTTParty#get with '/redirector.html'
13
+ Then the return value should match 'Service Response'
14
+
15
+ # TODO: Look in to why this actually fails...
16
+ Scenario: A service that redirects to a relative URL
17
+
18
+ Scenario: A service that redirects infinitely
19
+ Given the url '/first.html' redirects to '/second.html'
20
+ And the url '/second.html' redirects to '/first.html'
21
+ When I call HTTParty#get with '/first.html'
22
+ Then it should raise an HTTParty::RedirectionTooDeep exception
@@ -0,0 +1,13 @@
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 '/long_running_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 '/long_running_service.html'
12
+ Then it should raise a Timeout::Error exception
13
+ And I wait for the server to recover
data/httparty.gemspec ADDED
@@ -0,0 +1,146 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{httparty}
8
+ s.version = "0.6.1.hmac"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["John Nunemaker", "Sandro Turriate"]
12
+ s.date = %q{2010-08-12}
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/custom_parsers.rb",
33
+ "examples/delicious.rb",
34
+ "examples/google.rb",
35
+ "examples/rubyurl.rb",
36
+ "examples/twitter.rb",
37
+ "examples/whoismyrep.rb",
38
+ "features/basic_authentication.feature",
39
+ "features/command_line.feature",
40
+ "features/deals_with_http_error_codes.feature",
41
+ "features/digest_authentication.feature",
42
+ "features/handles_compressed_responses.feature",
43
+ "features/handles_multiple_formats.feature",
44
+ "features/steps/env.rb",
45
+ "features/steps/httparty_response_steps.rb",
46
+ "features/steps/httparty_steps.rb",
47
+ "features/steps/mongrel_helper.rb",
48
+ "features/steps/remote_service_steps.rb",
49
+ "features/supports_redirection.feature",
50
+ "features/supports_timeout_option.feature",
51
+ "httparty.gemspec",
52
+ "lib/httparty.rb",
53
+ "lib/httparty/cookie_hash.rb",
54
+ "lib/httparty/core_extensions.rb",
55
+ "lib/httparty/exceptions.rb",
56
+ "lib/httparty/module_inheritable_attributes.rb",
57
+ "lib/httparty/net_digest_auth.rb",
58
+ "lib/httparty/parser.rb",
59
+ "lib/httparty/request.rb",
60
+ "lib/httparty/response.rb",
61
+ "spec/fixtures/delicious.xml",
62
+ "spec/fixtures/empty.xml",
63
+ "spec/fixtures/google.html",
64
+ "spec/fixtures/ssl/generate.sh",
65
+ "spec/fixtures/ssl/generated/1fe462c2.0",
66
+ "spec/fixtures/ssl/generated/bogushost.crt",
67
+ "spec/fixtures/ssl/generated/ca.crt",
68
+ "spec/fixtures/ssl/generated/ca.key",
69
+ "spec/fixtures/ssl/generated/selfsigned.crt",
70
+ "spec/fixtures/ssl/generated/server.crt",
71
+ "spec/fixtures/ssl/generated/server.key",
72
+ "spec/fixtures/ssl/openssl-exts.cnf",
73
+ "spec/fixtures/twitter.json",
74
+ "spec/fixtures/twitter.xml",
75
+ "spec/fixtures/undefined_method_add_node_for_nil.xml",
76
+ "spec/httparty/cookie_hash_spec.rb",
77
+ "spec/httparty/parser_spec.rb",
78
+ "spec/httparty/request_spec.rb",
79
+ "spec/httparty/response_spec.rb",
80
+ "spec/httparty/ssl_spec.rb",
81
+ "spec/httparty_spec.rb",
82
+ "spec/spec.opts",
83
+ "spec/spec_helper.rb",
84
+ "spec/support/ssl_test_helper.rb",
85
+ "spec/support/ssl_test_server.rb",
86
+ "spec/support/stub_response.rb",
87
+ "website/css/common.css",
88
+ "website/index.html"
89
+ ]
90
+ s.homepage = %q{http://httparty.rubyforge.org}
91
+ s.post_install_message = %q{When you HTTParty, you must party hard!}
92
+ s.rdoc_options = ["--charset=UTF-8"]
93
+ s.require_paths = ["lib"]
94
+ s.rubyforge_project = %q{httparty}
95
+ s.rubygems_version = %q{1.3.7}
96
+ s.summary = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
97
+ s.test_files = [
98
+ "spec/httparty/cookie_hash_spec.rb",
99
+ "spec/httparty/parser_spec.rb",
100
+ "spec/httparty/request_spec.rb",
101
+ "spec/httparty/response_spec.rb",
102
+ "spec/httparty/ssl_spec.rb",
103
+ "spec/httparty_spec.rb",
104
+ "spec/spec_helper.rb",
105
+ "spec/support/ssl_test_helper.rb",
106
+ "spec/support/ssl_test_server.rb",
107
+ "spec/support/stub_response.rb",
108
+ "examples/aaws.rb",
109
+ "examples/basic.rb",
110
+ "examples/custom_parsers.rb",
111
+ "examples/delicious.rb",
112
+ "examples/google.rb",
113
+ "examples/rubyurl.rb",
114
+ "examples/twitter.rb",
115
+ "examples/whoismyrep.rb"
116
+ ]
117
+
118
+ if s.respond_to? :specification_version then
119
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
120
+ s.specification_version = 3
121
+
122
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
123
+ s.add_runtime_dependency(%q<crack>, ["= 0.1.8"])
124
+ s.add_development_dependency(%q<activesupport>, ["~> 2.3"])
125
+ s.add_development_dependency(%q<cucumber>, ["~> 0.7"])
126
+ s.add_development_dependency(%q<fakeweb>, ["~> 1.2"])
127
+ s.add_development_dependency(%q<mongrel>, ["~> 1.1"])
128
+ s.add_development_dependency(%q<rspec>, ["~> 1.3"])
129
+ else
130
+ s.add_dependency(%q<crack>, ["= 0.1.8"])
131
+ s.add_dependency(%q<activesupport>, ["~> 2.3"])
132
+ s.add_dependency(%q<cucumber>, ["~> 0.7"])
133
+ s.add_dependency(%q<fakeweb>, ["~> 1.2"])
134
+ s.add_dependency(%q<mongrel>, ["~> 1.1"])
135
+ s.add_dependency(%q<rspec>, ["~> 1.3"])
136
+ end
137
+ else
138
+ s.add_dependency(%q<crack>, ["= 0.1.8"])
139
+ s.add_dependency(%q<activesupport>, ["~> 2.3"])
140
+ s.add_dependency(%q<cucumber>, ["~> 0.7"])
141
+ s.add_dependency(%q<fakeweb>, ["~> 1.2"])
142
+ s.add_dependency(%q<mongrel>, ["~> 1.1"])
143
+ s.add_dependency(%q<rspec>, ["~> 1.3"])
144
+ end
145
+ end
146
+
data/lib/httparty.rb ADDED
@@ -0,0 +1,365 @@
1
+ require 'pathname'
2
+ require 'net/http'
3
+ require 'net/https'
4
+ require 'uri'
5
+ require 'zlib'
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
+ require dir + 'httparty/net_digest_auth'
13
+
14
+ module HTTParty
15
+ VERSION = "0.6.1".freeze
16
+ CRACK_DEPENDENCY = "0.1.8".freeze
17
+
18
+ module AllowedFormatsDeprecation
19
+ def const_missing(const)
20
+ if const.to_s =~ /AllowedFormats$/
21
+ Kernel.warn("Deprecated: Use HTTParty::Parser::SupportedFormats")
22
+ HTTParty::Parser::SupportedFormats
23
+ else
24
+ super
25
+ end
26
+ end
27
+ end
28
+
29
+ extend AllowedFormatsDeprecation
30
+
31
+ def self.included(base)
32
+ base.extend ClassMethods
33
+ base.send :include, HTTParty::ModuleInheritableAttributes
34
+ base.send(:mattr_inheritable, :default_options)
35
+ base.send(:mattr_inheritable, :default_cookies)
36
+ base.instance_variable_set("@default_options", {})
37
+ base.instance_variable_set("@default_cookies", CookieHash.new)
38
+ end
39
+
40
+ module ClassMethods
41
+ extend AllowedFormatsDeprecation
42
+
43
+ # Allows setting http proxy information to be used
44
+ #
45
+ # class Foo
46
+ # include HTTParty
47
+ # http_proxy 'http://foo.com', 80
48
+ # end
49
+ def http_proxy(addr=nil, port = nil)
50
+ default_options[:http_proxyaddr] = addr
51
+ default_options[:http_proxyport] = port
52
+ end
53
+
54
+ # Allows setting a base uri to be used for each request.
55
+ # Will normalize uri to include http, etc.
56
+ #
57
+ # class Foo
58
+ # include HTTParty
59
+ # base_uri 'twitter.com'
60
+ # end
61
+ def base_uri(uri=nil)
62
+ return default_options[:base_uri] unless uri
63
+ default_options[:base_uri] = HTTParty.normalize_base_uri(uri)
64
+ end
65
+
66
+ # Allows setting basic authentication username and password.
67
+ #
68
+ # class Foo
69
+ # include HTTParty
70
+ # basic_auth 'username', 'password'
71
+ # end
72
+ def basic_auth(u, p)
73
+ default_options[:basic_auth] = {:username => u, :password => p}
74
+ end
75
+
76
+ # Allows setting digest authentication username and password.
77
+ #
78
+ # class Foo
79
+ # include HTTParty
80
+ # digest_auth 'username', 'password'
81
+ # end
82
+ def digest_auth(u, p)
83
+ default_options[:digest_auth] = {:username => u, :password => p}
84
+ end
85
+
86
+ # Allows setting default parameters to be appended to each request.
87
+ # Great for api keys and such.
88
+ #
89
+ # class Foo
90
+ # include HTTParty
91
+ # default_params :api_key => 'secret', :another => 'foo'
92
+ # end
93
+ def default_params(h={})
94
+ raise ArgumentError, 'Default params must be a hash' unless h.is_a?(Hash)
95
+ default_options[:default_params] ||= {}
96
+ default_options[:default_params].merge!(h)
97
+ end
98
+
99
+ # Allows setting a default timeout for all HTTP calls
100
+ # Timeout is specified in seconds.
101
+ #
102
+ # class Foo
103
+ # include HTTParty
104
+ # default_timeout 10
105
+ # end
106
+ def default_timeout(t)
107
+ raise ArgumentError, 'Timeout must be an integer' unless t && t.is_a?(Integer)
108
+ default_options[:timeout] = t
109
+ end
110
+
111
+ # Set an output stream for debugging, defaults to $stderr.
112
+ # The output stream is passed on to Net::HTTP#set_debug_output.
113
+ #
114
+ # class Foo
115
+ # include HTTParty
116
+ # debug_output $stderr
117
+ # end
118
+ def debug_output(stream = $stderr)
119
+ default_options[:debug_output] = stream
120
+ end
121
+
122
+ # Allows setting HTTP headers to be used for each request.
123
+ #
124
+ # class Foo
125
+ # include HTTParty
126
+ # headers 'Accept' => 'text/html'
127
+ # end
128
+ def headers(h={})
129
+ raise ArgumentError, 'Headers must be a hash' unless h.is_a?(Hash)
130
+ default_options[:headers] ||= {}
131
+ default_options[:headers].merge!(h)
132
+ end
133
+
134
+ def cookies(h={})
135
+ raise ArgumentError, 'Cookies must be a hash' unless h.is_a?(Hash)
136
+ default_cookies.add_cookies(h)
137
+ end
138
+
139
+ # Allows setting the format with which to parse.
140
+ # Must be one of the allowed formats ie: json, xml
141
+ #
142
+ # class Foo
143
+ # include HTTParty
144
+ # format :json
145
+ # end
146
+ def format(f = nil)
147
+ if f.nil?
148
+ default_options[:format]
149
+ else
150
+ parser(Parser) if parser.nil?
151
+ default_options[:format] = f
152
+ validate_format
153
+ end
154
+ end
155
+
156
+ # Declare whether or not to follow redirects. When true, an
157
+ # {HTTParty::RedirectionTooDeep} error will raise upon encountering a
158
+ # redirect. You can then gain access to the response object via
159
+ # HTTParty::RedirectionTooDeep#response.
160
+ #
161
+ # @see HTTParty::ResponseError#response
162
+ #
163
+ # @example
164
+ # class Foo
165
+ # include HTTParty
166
+ # base_uri 'http://google.com'
167
+ # no_follow true
168
+ # end
169
+ #
170
+ # begin
171
+ # Foo.get('/')
172
+ # rescue HTTParty::RedirectionTooDeep => e
173
+ # puts e.response.body
174
+ # end
175
+ def no_follow(value = false)
176
+ default_options[:no_follow] = value
177
+ end
178
+
179
+ # Declare that you wish to maintain the chosen HTTP method across redirects.
180
+ # The default behavior is to follow redirects via the GET method.
181
+ # If you wish to maintain the original method, you can set this option to true.
182
+ #
183
+ # @example
184
+ # class Foo
185
+ # include HTTParty
186
+ # base_uri 'http://google.com'
187
+ # maintain_method_across_redirects true
188
+ # end
189
+
190
+ def maintain_method_across_redirects(value = true)
191
+ default_options[:maintain_method_across_redirects] = value
192
+ end
193
+
194
+ # Allows setting a PEM file to be used
195
+ #
196
+ # class Foo
197
+ # include HTTParty
198
+ # pem File.read('/home/user/my.pem')
199
+ # end
200
+ def pem(pem_contents)
201
+ default_options[:pem] = pem_contents
202
+ end
203
+
204
+ # Allows setting an OpenSSL certificate authority file
205
+ #
206
+ # class Foo
207
+ # include HTTParty
208
+ # ssl_ca_file '/etc/ssl/certs/ca-certificates.crt'
209
+ # end
210
+ def ssl_ca_file(path)
211
+ default_options[:ssl_ca_file] = path
212
+ end
213
+
214
+ # Allows setting an OpenSSL certificate authority path (directory)
215
+ #
216
+ # class Foo
217
+ # include HTTParty
218
+ # ssl_ca_path '/etc/ssl/certs/'
219
+ # end
220
+ def ssl_ca_path(path)
221
+ default_options[:ssl_ca_path] = path
222
+ end
223
+
224
+ # Allows setting a custom parser for the response.
225
+ #
226
+ # class Foo
227
+ # include HTTParty
228
+ # parser Proc.new {|data| ...}
229
+ # end
230
+ def parser(custom_parser = nil)
231
+ if custom_parser.nil?
232
+ default_options[:parser]
233
+ else
234
+ default_options[:parser] = custom_parser
235
+ validate_format
236
+ end
237
+ end
238
+
239
+ # Allows making a get request to a url.
240
+ #
241
+ # class Foo
242
+ # include HTTParty
243
+ # end
244
+ #
245
+ # # Simple get with full url
246
+ # Foo.get('http://foo.com/resource.json')
247
+ #
248
+ # # Simple get with full url and query parameters
249
+ # # ie: http://foo.com/resource.json?limit=10
250
+ # Foo.get('http://foo.com/resource.json', :query => {:limit => 10})
251
+ def get(path, options={})
252
+ perform_request Net::HTTP::Get, path, options
253
+ end
254
+
255
+ # Allows making a post request to a url.
256
+ #
257
+ # class Foo
258
+ # include HTTParty
259
+ # end
260
+ #
261
+ # # Simple post with full url and setting the body
262
+ # Foo.post('http://foo.com/resources', :body => {:bar => 'baz'})
263
+ #
264
+ # # Simple post with full url using :query option,
265
+ # # which gets set as form data on the request.
266
+ # Foo.post('http://foo.com/resources', :query => {:bar => 'baz'})
267
+ def post(path, options={})
268
+ perform_request Net::HTTP::Post, path, options
269
+ end
270
+
271
+ # Perform a PUT request to a path
272
+ def put(path, options={})
273
+ perform_request Net::HTTP::Put, path, options
274
+ end
275
+
276
+ # Perform a DELETE request to a path
277
+ def delete(path, options={})
278
+ perform_request Net::HTTP::Delete, path, options
279
+ end
280
+
281
+ # Perform a HEAD request to a path
282
+ def head(path, options={})
283
+ perform_request Net::HTTP::Head, path, options
284
+ end
285
+
286
+ # Perform an OPTIONS request to a path
287
+ def options(path, options={})
288
+ perform_request Net::HTTP::Options, path, options
289
+ end
290
+
291
+ def default_options #:nodoc:
292
+ @default_options
293
+ end
294
+
295
+ private
296
+
297
+ def perform_request(http_method, path, options) #:nodoc:
298
+ options = default_options.dup.merge(options)
299
+ process_cookies(options)
300
+ Request.new(http_method, path, options).perform
301
+ end
302
+
303
+ def process_cookies(options) #:nodoc:
304
+ return unless options[:cookies] || default_cookies.any?
305
+ options[:headers] ||= headers.dup
306
+ options[:headers]["cookie"] = cookies.merge(options.delete(:cookies) || {}).to_cookie_string
307
+ end
308
+
309
+ def validate_format
310
+ if format && parser.respond_to?(:supports_format?) && !parser.supports_format?(format)
311
+ raise UnsupportedFormat, "'#{format.inspect}' Must be one of: #{parser.supported_formats.map{|f| f.to_s}.sort.join(', ')}"
312
+ end
313
+ end
314
+ end
315
+
316
+ def self.normalize_base_uri(url) #:nodoc:
317
+ normalized_url = url.dup
318
+ use_ssl = (normalized_url =~ /^https/) || normalized_url.include?(':443')
319
+ ends_with_slash = normalized_url =~ /\/$/
320
+
321
+ normalized_url.chop! if ends_with_slash
322
+ normalized_url.gsub!(/^https?:\/\//i, '')
323
+
324
+ "http#{'s' if use_ssl}://#{normalized_url}"
325
+ end
326
+
327
+ class Basement #:nodoc:
328
+ include HTTParty
329
+ end
330
+
331
+ def self.get(*args)
332
+ Basement.get(*args)
333
+ end
334
+
335
+ def self.post(*args)
336
+ Basement.post(*args)
337
+ end
338
+
339
+ def self.put(*args)
340
+ Basement.put(*args)
341
+ end
342
+
343
+ def self.delete(*args)
344
+ Basement.delete(*args)
345
+ end
346
+
347
+ def self.head(*args)
348
+ Basement.head(*args)
349
+ end
350
+
351
+ def self.options(*args)
352
+ Basement.options(*args)
353
+ end
354
+
355
+ end
356
+
357
+ require dir + 'httparty/core_extensions'
358
+ require dir + 'httparty/exceptions'
359
+ require dir + 'httparty/parser'
360
+ require dir + 'httparty/request'
361
+ require dir + 'httparty/response'
362
+
363
+ if Crack::VERSION != HTTParty::CRACK_DEPENDENCY
364
+ warn "warning: HTTParty depends on version #{HTTParty::CRACK_DEPENDENCY} of crack, not #{Crack::VERSION}."
365
+ end