httparty 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of httparty might be problematic. Click here for more details.
- data/.gitignore +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +47 -0
- data/History +17 -1
- data/Rakefile +1 -12
- data/examples/basic.rb +21 -0
- data/examples/tripit_sign_in.rb +33 -0
- data/httparty.gemspec +27 -6
- data/lib/httparty.rb +117 -3
- data/lib/httparty/request.rb +81 -47
- data/lib/httparty/response.rb +19 -2
- data/spec/fixtures/ssl/generate.sh +29 -0
- data/spec/fixtures/ssl/generated/1fe462c2.0 +16 -0
- data/spec/fixtures/ssl/generated/bogushost.crt +13 -0
- data/spec/fixtures/ssl/generated/ca.crt +16 -0
- data/spec/fixtures/ssl/generated/ca.key +15 -0
- data/spec/fixtures/ssl/generated/selfsigned.crt +14 -0
- data/spec/fixtures/ssl/generated/server.crt +13 -0
- data/spec/fixtures/ssl/generated/server.key +15 -0
- data/spec/fixtures/ssl/openssl-exts.cnf +9 -0
- data/spec/httparty/parser_spec.rb +5 -4
- data/spec/httparty/request_spec.rb +63 -13
- data/spec/httparty/response_spec.rb +115 -10
- data/spec/httparty/ssl_spec.rb +54 -0
- data/spec/httparty_spec.rb +53 -7
- data/spec/spec_helper.rb +1 -0
- data/spec/support/ssl_test_helper.rb +25 -0
- data/spec/support/ssl_test_server.rb +69 -0
- data/spec/support/stub_response.rb +2 -2
- metadata +58 -7
- data/VERSION +0 -1
data/lib/httparty/request.rb
CHANGED
@@ -11,6 +11,18 @@ module HTTParty
|
|
11
11
|
|
12
12
|
SupportedURISchemes = [URI::HTTP, URI::HTTPS]
|
13
13
|
|
14
|
+
NON_RAILS_QUERY_STRING_NORMALIZER = Proc.new do |query|
|
15
|
+
query.map do |key, value|
|
16
|
+
if value.nil?
|
17
|
+
key
|
18
|
+
elsif value.is_a?(Array)
|
19
|
+
value.map {|v| "#{key}=#{URI.encode(v.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}"}
|
20
|
+
else
|
21
|
+
{key => value}.to_params
|
22
|
+
end
|
23
|
+
end.flatten.sort.join('&')
|
24
|
+
end
|
25
|
+
|
14
26
|
attr_accessor :http_method, :path, :options, :last_response, :redirect
|
15
27
|
|
16
28
|
def initialize(http_method, path, o={})
|
@@ -19,6 +31,7 @@ module HTTParty
|
|
19
31
|
self.options = {
|
20
32
|
:limit => o.delete(:no_follow) ? 1 : 5,
|
21
33
|
:default_params => {},
|
34
|
+
:follow_redirects => true,
|
22
35
|
:parser => Parser
|
23
36
|
}.merge(o)
|
24
37
|
end
|
@@ -53,12 +66,34 @@ module HTTParty
|
|
53
66
|
def perform
|
54
67
|
validate
|
55
68
|
setup_raw_request
|
56
|
-
|
69
|
+
self.last_response = http.request(@raw_request)
|
70
|
+
handle_deflation
|
57
71
|
handle_response
|
58
72
|
end
|
59
73
|
|
60
74
|
private
|
61
75
|
|
76
|
+
def attach_ssl_certificates(http)
|
77
|
+
if http.use_ssl?
|
78
|
+
# Client certificate authentication
|
79
|
+
if options[:pem]
|
80
|
+
http.cert = OpenSSL::X509::Certificate.new(options[:pem])
|
81
|
+
http.key = OpenSSL::PKey::RSA.new(options[:pem], options[:pem_password])
|
82
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
83
|
+
end
|
84
|
+
|
85
|
+
# SSL certificate authority file and/or directory
|
86
|
+
if options[:ssl_ca_file]
|
87
|
+
http.ca_file = options[:ssl_ca_file]
|
88
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
89
|
+
end
|
90
|
+
if options[:ssl_ca_path]
|
91
|
+
http.ca_path = options[:ssl_ca_path]
|
92
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
62
97
|
def http
|
63
98
|
http = Net::HTTP.new(uri.host, uri.port, options[:http_proxyaddr], options[:http_proxyport])
|
64
99
|
http.use_ssl = ssl_implied?
|
@@ -68,13 +103,7 @@ module HTTParty
|
|
68
103
|
http.read_timeout = options[:timeout]
|
69
104
|
end
|
70
105
|
|
71
|
-
|
72
|
-
http.cert = OpenSSL::X509::Certificate.new(options[:pem])
|
73
|
-
http.key = OpenSSL::PKey::RSA.new(options[:pem])
|
74
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
75
|
-
else
|
76
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
77
|
-
end
|
106
|
+
attach_ssl_certificates(http)
|
78
107
|
|
79
108
|
if options[:debug_output]
|
80
109
|
http.set_debug_output(options[:debug_output])
|
@@ -88,7 +117,7 @@ module HTTParty
|
|
88
117
|
end
|
89
118
|
|
90
119
|
def body
|
91
|
-
options[:body].is_a?(Hash) ? options[:body]
|
120
|
+
options[:body].is_a?(Hash) ? normalize_query(options[:body]) : options[:body]
|
92
121
|
end
|
93
122
|
|
94
123
|
def credentials
|
@@ -103,6 +132,18 @@ module HTTParty
|
|
103
132
|
credentials[:password]
|
104
133
|
end
|
105
134
|
|
135
|
+
def normalize_query(query)
|
136
|
+
if query_string_normalizer
|
137
|
+
query_string_normalizer.call(query)
|
138
|
+
else
|
139
|
+
query.to_params
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def query_string_normalizer
|
144
|
+
options[:query_string_normalizer]
|
145
|
+
end
|
146
|
+
|
106
147
|
def setup_raw_request
|
107
148
|
@raw_request = http_method.new(uri.request_uri)
|
108
149
|
@raw_request.body = body if body
|
@@ -118,22 +159,14 @@ module HTTParty
|
|
118
159
|
end
|
119
160
|
end
|
120
161
|
|
121
|
-
def perform_actual_request
|
122
|
-
http.request(@raw_request)
|
123
|
-
end
|
124
|
-
|
125
|
-
def get_response
|
126
|
-
self.last_response = perform_actual_request
|
127
|
-
end
|
128
|
-
|
129
162
|
def query_string(uri)
|
130
163
|
query_string_parts = []
|
131
164
|
query_string_parts << uri.query unless uri.query.nil?
|
132
165
|
|
133
166
|
if options[:query].is_a?(Hash)
|
134
|
-
query_string_parts << options[:default_params].merge(options[:query])
|
167
|
+
query_string_parts << normalize_query(options[:default_params].merge(options[:query]))
|
135
168
|
else
|
136
|
-
query_string_parts << options[:default_params]
|
169
|
+
query_string_parts << normalize_query(options[:default_params]) unless options[:default_params].empty?
|
137
170
|
query_string_parts << options[:query] unless options[:query].nil?
|
138
171
|
end
|
139
172
|
|
@@ -142,26 +175,15 @@ module HTTParty
|
|
142
175
|
|
143
176
|
# Raises exception Net::XXX (http error code) if an http error occured
|
144
177
|
def handle_response
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
Net::
|
150
|
-
|
151
|
-
|
152
|
-
Net::HTTPTemporaryRedirect
|
153
|
-
if last_response.key?('location')
|
154
|
-
options[:limit] -= 1
|
155
|
-
self.path = last_response['location']
|
156
|
-
self.redirect = true
|
157
|
-
self.http_method = Net::HTTP::Get unless options[:maintain_method_across_redirects]
|
158
|
-
capture_cookies(last_response)
|
159
|
-
perform
|
160
|
-
else
|
161
|
-
last_response
|
162
|
-
end
|
178
|
+
if response_redirects?
|
179
|
+
options[:limit] -= 1
|
180
|
+
self.path = last_response['location']
|
181
|
+
self.redirect = true
|
182
|
+
self.http_method = Net::HTTP::Get unless options[:maintain_method_across_redirects]
|
183
|
+
capture_cookies(last_response)
|
184
|
+
perform
|
163
185
|
else
|
164
|
-
Response.new(last_response, parse_response(last_response.body))
|
186
|
+
Response.new(self, last_response, parse_response(last_response.body))
|
165
187
|
end
|
166
188
|
end
|
167
189
|
|
@@ -176,6 +198,18 @@ module HTTParty
|
|
176
198
|
end
|
177
199
|
end
|
178
200
|
|
201
|
+
def response_redirects?
|
202
|
+
case last_response
|
203
|
+
when Net::HTTPMultipleChoice, # 300
|
204
|
+
Net::HTTPMovedPermanently, # 301
|
205
|
+
Net::HTTPFound, # 302
|
206
|
+
Net::HTTPSeeOther, # 303
|
207
|
+
Net::HTTPUseProxy, # 305
|
208
|
+
Net::HTTPTemporaryRedirect
|
209
|
+
options[:follow_redirects] && last_response.key?('location')
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
179
213
|
def parse_response(body)
|
180
214
|
parser.call(body, format)
|
181
215
|
end
|
@@ -198,15 +232,15 @@ module HTTParty
|
|
198
232
|
end
|
199
233
|
end
|
200
234
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
235
|
+
def validate
|
236
|
+
raise HTTParty::RedirectionTooDeep.new(last_response), 'HTTP redirects too deep' if options[:limit].to_i <= 0
|
237
|
+
raise ArgumentError, 'only get, post, put, delete, head, and options methods are supported' unless SupportedHTTPMethods.include?(http_method)
|
238
|
+
raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash)
|
239
|
+
raise ArgumentError, 'only one authentication method, :basic_auth or :digest_auth may be used at a time' if options[:basic_auth] && options[:digest_auth]
|
240
|
+
raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].is_a?(Hash)
|
241
|
+
raise ArgumentError, ':digest_auth must be a hash' if options[:digest_auth] && !options[:digest_auth].is_a?(Hash)
|
242
|
+
raise ArgumentError, ':query must be hash if using HTTP Post' if post? && !options[:query].nil? && !options[:query].is_a?(Hash)
|
243
|
+
end
|
210
244
|
|
211
245
|
def post?
|
212
246
|
Net::HTTP::Post == http_method
|
data/lib/httparty/response.rb
CHANGED
@@ -28,9 +28,15 @@ module HTTParty
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
attr_reader :response, :parsed_response, :body, :headers
|
32
31
|
|
33
|
-
def
|
32
|
+
def self.underscore(string)
|
33
|
+
string.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :request, :response, :parsed_response, :body, :headers
|
37
|
+
|
38
|
+
def initialize(request, response, parsed_response)
|
39
|
+
@request = request
|
34
40
|
@response = response
|
35
41
|
@body = response.body
|
36
42
|
@parsed_response = parsed_response
|
@@ -50,6 +56,17 @@ module HTTParty
|
|
50
56
|
%(#<#{self.class}:0x#{inspect_id} @parsed_response=#{parsed_response.inspect}, @response=#{response.inspect}, @headers=#{headers.inspect}>)
|
51
57
|
end
|
52
58
|
|
59
|
+
CODES_TO_OBJ = Net::HTTPResponse::CODE_CLASS_TO_OBJ.merge Net::HTTPResponse::CODE_TO_OBJ
|
60
|
+
|
61
|
+
CODES_TO_OBJ.each do |response_code, klass|
|
62
|
+
name = klass.name.sub("Net::HTTP", '')
|
63
|
+
define_method("#{underscore(name)}?") do
|
64
|
+
klass === response
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
53
70
|
def method_missing(name, *args, &block)
|
54
71
|
if parsed_response.respond_to?(name)
|
55
72
|
parsed_response.send(name, *args, &block)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
set -e
|
3
|
+
|
4
|
+
if [ -d "generated" ] ; then
|
5
|
+
echo >&2 "error: 'generated' directory already exists. Delete it first."
|
6
|
+
exit 1
|
7
|
+
fi
|
8
|
+
|
9
|
+
mkdir generated
|
10
|
+
|
11
|
+
# Generate the CA private key and certificate
|
12
|
+
openssl req -batch -subj '/CN=INSECURE Test Certificate Authority' -newkey rsa:1024 -new -x509 -days 999999 -keyout generated/ca.key -nodes -out generated/ca.crt
|
13
|
+
|
14
|
+
# Create symlinks for ssl_ca_path
|
15
|
+
c_rehash generated
|
16
|
+
|
17
|
+
# Generate the server private key and self-signed certificate
|
18
|
+
openssl req -batch -subj '/CN=localhost' -newkey rsa:1024 -new -x509 -days 999999 -keyout generated/server.key -nodes -out generated/selfsigned.crt
|
19
|
+
|
20
|
+
# Generate certificate signing request with bogus hostname
|
21
|
+
openssl req -batch -subj '/CN=bogo' -new -days 999999 -key generated/server.key -nodes -out generated/bogushost.csr
|
22
|
+
|
23
|
+
# Sign the certificate requests
|
24
|
+
openssl x509 -CA generated/ca.crt -CAkey generated/ca.key -set_serial 1 -in generated/selfsigned.crt -out generated/server.crt -clrext -extfile openssl-exts.cnf -extensions cert -days 999999
|
25
|
+
openssl x509 -req -CA generated/ca.crt -CAkey generated/ca.key -set_serial 1 -in generated/bogushost.csr -out generated/bogushost.crt -clrext -extfile openssl-exts.cnf -extensions cert -days 999999
|
26
|
+
|
27
|
+
# Remove certificate signing requests
|
28
|
+
rm -f generated/*.csr
|
29
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICbTCCAdagAwIBAgIJAIAeO9TXtJ45MA0GCSqGSIb3DQEBBQUAMC4xLDAqBgNV
|
3
|
+
BAMTI0lOU0VDVVJFIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MCAXDTEwMTAy
|
4
|
+
MDEzNDYyM1oYDzQ3NDgwOTE1MTM0NjIzWjAuMSwwKgYDVQQDEyNJTlNFQ1VSRSBU
|
5
|
+
ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
|
6
|
+
gYkCgYEA3lkBcd352qiIIzqnyvvJj59cx1dnzMyjnuaK2cRH420rBfukLE2MbOVr
|
7
|
+
9nYq/7CdjqXpE8uFAF+UTSIK6MWZ/bidkr2xd/et/Ce2pVIVxH+rt3pJz3wZhC3H
|
8
|
+
Yz+HU4CD2iI9wAzsb6mMV7md1fjlYfir4SBGGPTkcqUJUp2/tQMCAwEAAaOBkDCB
|
9
|
+
jTAdBgNVHQ4EFgQUy0Lz6RgmtpywlBOXdPABQArp358wXgYDVR0jBFcwVYAUy0Lz
|
10
|
+
6RgmtpywlBOXdPABQArp35+hMqQwMC4xLDAqBgNVBAMTI0lOU0VDVVJFIFRlc3Qg
|
11
|
+
Q2VydGlmaWNhdGUgQXV0aG9yaXR5ggkAgB471Ne0njkwDAYDVR0TBAUwAwEB/zAN
|
12
|
+
BgkqhkiG9w0BAQUFAAOBgQCmi3JQm+EIWjkRlyz9sijkYS+Ps4opmd/weeaXwa4E
|
13
|
+
gVBWJGyiduB+kBnfv61+/tDjlrbjBDH5dP8suczHQL8gox4zGgjw64KH4o1ujZYR
|
14
|
+
cEPbhnUpwbXu7yItlajBZfpFefjF5P0Ao2iEzQldDy0D6nQ19h5QANvQxqweTPQp
|
15
|
+
pw==
|
16
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,13 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICBTCCAW6gAwIBAgIBATANBgkqhkiG9w0BAQUFADAuMSwwKgYDVQQDEyNJTlNF
|
3
|
+
Q1VSRSBUZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0xMDEwMjAxMzQ2MjNa
|
4
|
+
GA80NzQ4MDkxNTEzNDYyM1owDzENMAsGA1UEAxMEYm9nbzCBnzANBgkqhkiG9w0B
|
5
|
+
AQEFAAOBjQAwgYkCgYEAr6b0ZBrRrVvPmPbQv36Jnj5jv00ZkhimXrmbv9Z1AdIZ
|
6
|
+
WSsBpMd8TP7exE5OR5/DaxKmiZqVskgRyRkLm52/Dkt7Ncrzr5I3unHnMqsAv/28
|
7
|
+
5fGlYoRxnkCGMse/6NOFgCemRFw/bglxPNAGrFYKStameBRbCm0dCgtlvcwzdf8C
|
8
|
+
AwEAAaNQME4wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUddLPFtGmb0aFWbTl2kAo
|
9
|
+
xD+fd6kwHwYDVR0jBBgwFoAUy0Lz6RgmtpywlBOXdPABQArp358wDQYJKoZIhvcN
|
10
|
+
AQEFBQADgYEAosqpPVsFu6cOIhGFT85Y1wwRUaihO0vWO7ghBU5ScuRU3tuvyJDZ
|
11
|
+
Z/HoAMXV6XZjVZzRosjtPjFbyWkZYjUqJJRMyEaRiGArWe6urKLzwnD6R9O3eNa5
|
12
|
+
7bgFhzZ5WBldJmtq4A3oNqBuvgZkYM6NVKvS4UoakkTliHB21/mDOSY=
|
13
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,16 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICbTCCAdagAwIBAgIJAIAeO9TXtJ45MA0GCSqGSIb3DQEBBQUAMC4xLDAqBgNV
|
3
|
+
BAMTI0lOU0VDVVJFIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MCAXDTEwMTAy
|
4
|
+
MDEzNDYyM1oYDzQ3NDgwOTE1MTM0NjIzWjAuMSwwKgYDVQQDEyNJTlNFQ1VSRSBU
|
5
|
+
ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
|
6
|
+
gYkCgYEA3lkBcd352qiIIzqnyvvJj59cx1dnzMyjnuaK2cRH420rBfukLE2MbOVr
|
7
|
+
9nYq/7CdjqXpE8uFAF+UTSIK6MWZ/bidkr2xd/et/Ce2pVIVxH+rt3pJz3wZhC3H
|
8
|
+
Yz+HU4CD2iI9wAzsb6mMV7md1fjlYfir4SBGGPTkcqUJUp2/tQMCAwEAAaOBkDCB
|
9
|
+
jTAdBgNVHQ4EFgQUy0Lz6RgmtpywlBOXdPABQArp358wXgYDVR0jBFcwVYAUy0Lz
|
10
|
+
6RgmtpywlBOXdPABQArp35+hMqQwMC4xLDAqBgNVBAMTI0lOU0VDVVJFIFRlc3Qg
|
11
|
+
Q2VydGlmaWNhdGUgQXV0aG9yaXR5ggkAgB471Ne0njkwDAYDVR0TBAUwAwEB/zAN
|
12
|
+
BgkqhkiG9w0BAQUFAAOBgQCmi3JQm+EIWjkRlyz9sijkYS+Ps4opmd/weeaXwa4E
|
13
|
+
gVBWJGyiduB+kBnfv61+/tDjlrbjBDH5dP8suczHQL8gox4zGgjw64KH4o1ujZYR
|
14
|
+
cEPbhnUpwbXu7yItlajBZfpFefjF5P0Ao2iEzQldDy0D6nQ19h5QANvQxqweTPQp
|
15
|
+
pw==
|
16
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,15 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIICXgIBAAKBgQDeWQFx3fnaqIgjOqfK+8mPn1zHV2fMzKOe5orZxEfjbSsF+6Qs
|
3
|
+
TYxs5Wv2dir/sJ2OpekTy4UAX5RNIgroxZn9uJ2SvbF39638J7alUhXEf6u3eknP
|
4
|
+
fBmELcdjP4dTgIPaIj3ADOxvqYxXuZ3V+OVh+KvhIEYY9ORypQlSnb+1AwIDAQAB
|
5
|
+
AoGBAL147VFCDlM1gGU865V+wIFCFQbNxedwjxGuda4io/v6oEoF6R3Tq5F0Y27v
|
6
|
+
va6Lq4fOe/LhYGI0EKU2GEPJd3F2wA21r+81InPKAkqYI5CDQtKDDNLviur8ZVKF
|
7
|
+
i3UzutjeYoCqmWeHaKPD6w5DtqeBieem7LTWRyXlFtHZV/nBAkEA8nsMOSd1+JTm
|
8
|
+
ZT4HDsEFQrN8mIFUUioFSHPut2CwzvTEW+hTkLQiog3bua4n7uQOFImR63X9qMsh
|
9
|
+
IjZRJQNmowJBAOq+mQdnRWYKl0SYb++Eb3uW6L4h1zsW375+caKo9omtpeqDW/y0
|
10
|
+
BWyY0q4DPkm3yU26Yr+b2JijISrml9/8PiECQQDHuXyG8y7jktn3GFE94NURbL+6
|
11
|
+
6gPnLX9ufzdoSjc4MDowrbtvHEDOlHWgioeP6L6EQhA0DtrhlnbzNCRARX3bAkEA
|
12
|
+
jQOsF+dwqAjKr/lGnMKY2cxgyf64NZXbGKsKhmUrnK9E0SjR9G8MJx1yyffGzi/q
|
13
|
+
bJf/xAzRw3eTcBsPtwznIQJAHq5MOK7oaUuO+6cbsZYpOYOOkKIvDLiOtdSr7LTI
|
14
|
+
DziH/fpzB0VhCmFhhEQwHhlB4t3m66A9TelHmhrCDsIaLA==
|
15
|
+
-----END RSA PRIVATE KEY-----
|
@@ -0,0 +1,14 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICHTCCAYagAwIBAgIJALT/G+ylQljIMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
|
3
|
+
BAMTCWxvY2FsaG9zdDAgFw0xMDEwMjAxMzQ2MjNaGA80NzQ4MDkxNTEzNDYyM1ow
|
4
|
+
FDESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
|
5
|
+
gQCvpvRkGtGtW8+Y9tC/fomePmO/TRmSGKZeuZu/1nUB0hlZKwGkx3xM/t7ETk5H
|
6
|
+
n8NrEqaJmpWySBHJGQubnb8OS3s1yvOvkje6cecyqwC//bzl8aVihHGeQIYyx7/o
|
7
|
+
04WAJ6ZEXD9uCXE80AasVgpK1qZ4FFsKbR0KC2W9zDN1/wIDAQABo3UwczAdBgNV
|
8
|
+
HQ4EFgQUddLPFtGmb0aFWbTl2kAoxD+fd6kwRAYDVR0jBD0wO4AUddLPFtGmb0aF
|
9
|
+
WbTl2kAoxD+fd6mhGKQWMBQxEjAQBgNVBAMTCWxvY2FsaG9zdIIJALT/G+ylQljI
|
10
|
+
MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAlOCBO54S88mD3VYviER6
|
11
|
+
V+lkd7iWmdas2wUUDeMKA9CxnirWi7ne2U7wQH/5FJ1j3ImSfjb4h/98xiVJE84e
|
12
|
+
Ld7mb61g/M4g4b62kt0HK8/cGUxfuz5zwIfi28qJq3ow6AFEq1fywbJvUAnnamwU
|
13
|
+
cZF/qoVfJhus2mXjYc4hFWg=
|
14
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,13 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICCjCCAXOgAwIBAgIBATANBgkqhkiG9w0BAQUFADAuMSwwKgYDVQQDEyNJTlNF
|
3
|
+
Q1VSRSBUZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0xMDEwMjAxMzQ2MjNa
|
4
|
+
GA80NzQ4MDkxNTEzNDYyM1owFDESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqG
|
5
|
+
SIb3DQEBAQUAA4GNADCBiQKBgQCvpvRkGtGtW8+Y9tC/fomePmO/TRmSGKZeuZu/
|
6
|
+
1nUB0hlZKwGkx3xM/t7ETk5Hn8NrEqaJmpWySBHJGQubnb8OS3s1yvOvkje6cecy
|
7
|
+
qwC//bzl8aVihHGeQIYyx7/o04WAJ6ZEXD9uCXE80AasVgpK1qZ4FFsKbR0KC2W9
|
8
|
+
zDN1/wIDAQABo1AwTjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBR10s8W0aZvRoVZ
|
9
|
+
tOXaQCjEP593qTAfBgNVHSMEGDAWgBTLQvPpGCa2nLCUE5d08AFACunfnzANBgkq
|
10
|
+
hkiG9w0BAQUFAAOBgQCR4Oor0YAvK0tNFrOLtqmC6D0F5IYCyu7komk7JGn9L4nn
|
11
|
+
7VyVxd4MXdc1r1v+WP5JtnA9ZjMmEmH9gl4gwR/Cu+TMkArsq0Z8mREOLNL8pwpx
|
12
|
+
Zxgk0CwacYR9RQcpuJ9nSDzVoO5ecYkb5C9q7gwgqbmCzr7oz/rwTqRwiUZCVQ==
|
13
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,15 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIICXQIBAAKBgQCvpvRkGtGtW8+Y9tC/fomePmO/TRmSGKZeuZu/1nUB0hlZKwGk
|
3
|
+
x3xM/t7ETk5Hn8NrEqaJmpWySBHJGQubnb8OS3s1yvOvkje6cecyqwC//bzl8aVi
|
4
|
+
hHGeQIYyx7/o04WAJ6ZEXD9uCXE80AasVgpK1qZ4FFsKbR0KC2W9zDN1/wIDAQAB
|
5
|
+
AoGALIdgkTgTS6VovVhklwcXEBy04LxE7Tp+gqj/COTvCKUgc/BpHELOCh7ajl1j
|
6
|
+
jti7i5tQyLV9mZKXn6lPvgWBd0w+p6VhM4NFA97CoodEJm2ckFC9zUABCh9dOpbm
|
7
|
+
8KzF7hdpYWgJJchwwZ60tbcP7K1DkiNX6Kk9qKQEWvitMBECQQDpOSzzLldcEU9l
|
8
|
+
ze/nG2+rf6ecaPnKeafY8R2qVils8I7ZJAW3+0bNT5gQs7rT7aWo8vMvrXq++lWb
|
9
|
+
JkNV6hK9AkEAwM5wsmg7REmAaDwgUBq5mNt963/uG2ihAODFS70lYT23UYl5Y3rD
|
10
|
+
s3qU4ntG4DvWIQgPdwdstzDh9fMBVXa1awJBAID1WoOE5k1ETRDP1I2HwDGmPnng
|
11
|
+
Ge75YfQ1LuAXEITqZzJuFrNqv/Waw0zI9M9moqlO3WVJmYusRFWrzKPe8EkCQEwC
|
12
|
+
FlN+275z63csHOD3aCtmfCGW8VtEyBP8iErvagkHt3khZQVepD/hF0ihqLNFY4jq
|
13
|
+
EI6wEp+1WZ8ICYKTpbkCQQDhl5QLdy5Xo3k3agCnB9nktSzs2iqFvsGvfOAW4628
|
14
|
+
iThKTNua6bBvbdiG0Vh2Sv0XBYVJoHB3WnTVgFyPJaaF
|
15
|
+
-----END RSA PRIVATE KEY-----
|
@@ -1,7 +1,5 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
2
|
|
3
|
-
class CustomParser < HTTParty::Parser; end
|
4
|
-
|
5
3
|
describe HTTParty::Parser do
|
6
4
|
describe ".SupportedFormats" do
|
7
5
|
it "returns a hash" do
|
@@ -115,10 +113,13 @@ describe HTTParty::Parser do
|
|
115
113
|
end
|
116
114
|
|
117
115
|
it "raises a useful exception message for subclasses" do
|
118
|
-
|
116
|
+
atom_parser = Class.new(HTTParty::Parser) do
|
117
|
+
def self.name; 'AtomParser'; end
|
118
|
+
end
|
119
|
+
parser = atom_parser.new 'body', :atom
|
119
120
|
expect do
|
120
121
|
parser.send(:parse_supported_format)
|
121
|
-
end.to raise_error(NotImplementedError, "
|
122
|
+
end.to raise_error(NotImplementedError, "AtomParser has not implemented a parsing method for the :atom format.")
|
122
123
|
end
|
123
124
|
end
|
124
125
|
end
|
@@ -5,6 +5,28 @@ describe HTTParty::Request do
|
|
5
5
|
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', :format => :xml)
|
6
6
|
end
|
7
7
|
|
8
|
+
describe "::NON_RAILS_QUERY_STRING_NORMALIZER" do
|
9
|
+
let(:normalizer) { HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER }
|
10
|
+
|
11
|
+
it "doesn't modify strings" do
|
12
|
+
query_string = normalizer["foo=bar&foo=baz"]
|
13
|
+
URI.unescape(query_string).should == "foo=bar&foo=baz"
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when representing an array" do
|
17
|
+
|
18
|
+
it "doesn't include brackets" do
|
19
|
+
query_string = normalizer[{:page => 1, :foo => %w(bar baz)}]
|
20
|
+
URI.unescape(query_string).should == "foo=bar&foo=baz&page=1"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "URI encodes array values" do
|
24
|
+
query_string = normalizer[{:people => ["Bob Marley", "Tim & Jon"]}]
|
25
|
+
query_string.should == "people=Bob%20Marley&people=Tim%20%26%20Jon"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
8
30
|
describe "initialization" do
|
9
31
|
it "sets parser to HTTParty::Parser" do
|
10
32
|
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
|
@@ -74,6 +96,33 @@ describe HTTParty::Request do
|
|
74
96
|
@request.options[:default_params] = {}
|
75
97
|
@request.uri.query.should be_nil
|
76
98
|
end
|
99
|
+
|
100
|
+
it "respects the query string normalization proc" do
|
101
|
+
empty_proc = lambda {|qs| ""}
|
102
|
+
@request.options[:query_string_normalizer] = empty_proc
|
103
|
+
@request.options[:query] = {:foo => :bar}
|
104
|
+
URI.unescape(@request.uri.query).should == ""
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when representing an array" do
|
108
|
+
it "returns a Rails style query string" do
|
109
|
+
@request.options[:query] = {:foo => %w(bar baz)}
|
110
|
+
URI.unescape(@request.uri.query).should == "foo[]=bar&foo[]=baz"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#setup_raw_request" do
|
118
|
+
context "when query_string_normalizer is set" do
|
119
|
+
it "sets the body to the return value of the proc" do
|
120
|
+
@request.options[:query_string_normalizer] = HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER
|
121
|
+
@request.options[:body] = {:page => 1, :foo => %w(bar baz)}
|
122
|
+
@request.send(:setup_raw_request)
|
123
|
+
body = @request.instance_variable_get(:@raw_request).body
|
124
|
+
URI.unescape(body).should == "foo=bar&foo=baz&page=1"
|
125
|
+
end
|
77
126
|
end
|
78
127
|
end
|
79
128
|
|
@@ -111,9 +160,10 @@ describe HTTParty::Request do
|
|
111
160
|
@cert = mock("OpenSSL::X509::Certificate")
|
112
161
|
@key = mock("OpenSSL::PKey::RSA")
|
113
162
|
OpenSSL::X509::Certificate.should_receive(:new).with(pem).and_return(@cert)
|
114
|
-
OpenSSL::PKey::RSA.should_receive(:new).with(pem).and_return(@key)
|
163
|
+
OpenSSL::PKey::RSA.should_receive(:new).with(pem, "password").and_return(@key)
|
115
164
|
|
116
165
|
@request.options[:pem] = pem
|
166
|
+
@request.options[:pem_password] = "password"
|
117
167
|
@pem_http = @request.send(:http)
|
118
168
|
end
|
119
169
|
|
@@ -139,16 +189,6 @@ describe HTTParty::Request do
|
|
139
189
|
request.options[:pem] = :pem_contents
|
140
190
|
request.send(:http)
|
141
191
|
end
|
142
|
-
|
143
|
-
it "should not verify a certificate if scheme is not https" do
|
144
|
-
http = Net::HTTP.new('google.com')
|
145
|
-
Net::HTTP.stub(:new => http)
|
146
|
-
|
147
|
-
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
|
148
|
-
request.options[:pem] = :pem_contents
|
149
|
-
http = request.send(:http)
|
150
|
-
http.verify_mode.should == OpenSSL::SSL::VERIFY_NONE
|
151
|
-
end
|
152
192
|
end
|
153
193
|
|
154
194
|
context "debugging" do
|
@@ -282,9 +322,19 @@ describe HTTParty::Request do
|
|
282
322
|
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
283
323
|
end
|
284
324
|
|
285
|
-
it "
|
325
|
+
it "redirects if a 300 contains a relative location header" do
|
326
|
+
redirect = stub_response '', 300
|
327
|
+
redirect['location'] = '/foo/bar'
|
328
|
+
ok = stub_response('<hash><foo>bar</foo></hash>', 200)
|
329
|
+
@http.stub!(:request).and_return(redirect, ok)
|
330
|
+
response = @request.perform
|
331
|
+
response.request.uri.request_uri.should == "/foo/bar"
|
332
|
+
response.should == {"hash" => {"foo" => "bar"}}
|
333
|
+
end
|
334
|
+
|
335
|
+
it "returns the HTTParty::Response when the 300 does not contain a location header" do
|
286
336
|
net_response = stub_response '', 300
|
287
|
-
@request.perform
|
337
|
+
HTTParty::Response.should === @request.perform
|
288
338
|
end
|
289
339
|
end
|
290
340
|
|