httsoiree 0.13.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +7 -0
- data/Gemfile +14 -0
- data/Guardfile +16 -0
- data/History +303 -0
- data/MIT-LICENSE +20 -0
- data/README.md +77 -0
- data/Rakefile +12 -0
- data/bin/httparty +117 -0
- data/cucumber.yml +1 -0
- data/examples/aaws.rb +32 -0
- data/examples/basic.rb +28 -0
- data/examples/crack.rb +19 -0
- data/examples/custom_parsers.rb +67 -0
- data/examples/delicious.rb +37 -0
- data/examples/google.rb +16 -0
- data/examples/headers_and_user_agents.rb +6 -0
- data/examples/logging.rb +38 -0
- data/examples/nokogiri_html_parser.rb +22 -0
- data/examples/rubyurl.rb +14 -0
- data/examples/stackexchange.rb +24 -0
- data/examples/tripit_sign_in.rb +33 -0
- data/examples/twitter.rb +31 -0
- data/examples/whoismyrep.rb +10 -0
- data/features/basic_authentication.feature +20 -0
- data/features/command_line.feature +7 -0
- data/features/deals_with_http_error_codes.feature +26 -0
- data/features/digest_authentication.feature +20 -0
- data/features/handles_compressed_responses.feature +27 -0
- data/features/handles_multiple_formats.feature +57 -0
- data/features/steps/env.rb +22 -0
- data/features/steps/httparty_response_steps.rb +52 -0
- data/features/steps/httparty_steps.rb +43 -0
- data/features/steps/mongrel_helper.rb +94 -0
- data/features/steps/remote_service_steps.rb +74 -0
- data/features/supports_read_timeout_option.feature +13 -0
- data/features/supports_redirection.feature +22 -0
- data/features/supports_timeout_option.feature +13 -0
- data/httparty.gemspec +25 -0
- data/lib/httparty/connection_adapter.rb +188 -0
- data/lib/httparty/cookie_hash.rb +22 -0
- data/lib/httparty/core_extensions.rb +32 -0
- data/lib/httparty/exceptions.rb +29 -0
- data/lib/httparty/hash_conversions.rb +51 -0
- data/lib/httparty/logger/apache_logger.rb +22 -0
- data/lib/httparty/logger/curl_logger.rb +48 -0
- data/lib/httparty/logger/logger.rb +18 -0
- data/lib/httparty/module_inheritable_attributes.rb +56 -0
- data/lib/httparty/net_digest_auth.rb +84 -0
- data/lib/httparty/parser.rb +141 -0
- data/lib/httparty/request.rb +339 -0
- data/lib/httparty/response/headers.rb +31 -0
- data/lib/httparty/response.rb +72 -0
- data/lib/httparty/version.rb +3 -0
- data/lib/httparty.rb +618 -0
- data/lib/httsoiree.rb +3 -0
- data/script/release +42 -0
- data/spec/fixtures/delicious.xml +23 -0
- data/spec/fixtures/empty.xml +0 -0
- data/spec/fixtures/google.html +3 -0
- 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/fixtures/twitter.csv +2 -0
- data/spec/fixtures/twitter.json +1 -0
- data/spec/fixtures/twitter.xml +403 -0
- data/spec/fixtures/undefined_method_add_node_for_nil.xml +2 -0
- data/spec/httparty/connection_adapter_spec.rb +370 -0
- data/spec/httparty/cookie_hash_spec.rb +83 -0
- data/spec/httparty/exception_spec.rb +23 -0
- data/spec/httparty/logger/apache_logger_spec.rb +41 -0
- data/spec/httparty/logger/curl_logger_spec.rb +18 -0
- data/spec/httparty/logger/logger_spec.rb +22 -0
- data/spec/httparty/net_digest_auth_spec.rb +152 -0
- data/spec/httparty/parser_spec.rb +165 -0
- data/spec/httparty/request_spec.rb +774 -0
- data/spec/httparty/response_spec.rb +221 -0
- data/spec/httparty/ssl_spec.rb +74 -0
- data/spec/httparty_spec.rb +783 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/ssl_test_helper.rb +47 -0
- data/spec/support/ssl_test_server.rb +80 -0
- data/spec/support/stub_response.rb +43 -0
- data/website/css/common.css +47 -0
- data/website/index.html +73 -0
- metadata +215 -0
@@ -0,0 +1,152 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
describe Net::HTTPHeader::DigestAuthenticator do
|
4
|
+
def setup_digest(response)
|
5
|
+
digest = Net::HTTPHeader::DigestAuthenticator.new("Mufasa",
|
6
|
+
"Circle Of Life", "GET", "/dir/index.html", response)
|
7
|
+
digest.stub(:random).and_return("deadbeef")
|
8
|
+
Digest::MD5.stub(:hexdigest) { |str| "md5(#{str})" }
|
9
|
+
digest
|
10
|
+
end
|
11
|
+
|
12
|
+
def authorization_header
|
13
|
+
@digest.authorization_header.join(", ")
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
context "with an opaque value in the response header" do
|
18
|
+
before do
|
19
|
+
@digest = setup_digest({
|
20
|
+
'www-authenticate' => 'Digest realm="myhost@testrealm.com", opaque="solid"'
|
21
|
+
})
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set opaque" do
|
25
|
+
authorization_header.should include(%Q(opaque="solid"))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "without an opaque valid in the response header" do
|
30
|
+
before do
|
31
|
+
@digest = setup_digest({
|
32
|
+
'www-authenticate' => 'Digest realm="myhost@testrealm.com"'
|
33
|
+
})
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should not set opaque" do
|
37
|
+
authorization_header.should_not include(%Q(opaque=))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "with specified quality of protection (qop)" do
|
42
|
+
before do
|
43
|
+
@digest = setup_digest({
|
44
|
+
'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth"',
|
45
|
+
})
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should set prefix" do
|
49
|
+
authorization_header.should =~ /^Digest /
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should set username" do
|
53
|
+
authorization_header.should include(%Q(username="Mufasa"))
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should set digest-uri" do
|
57
|
+
authorization_header.should include(%Q(uri="/dir/index.html"))
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should set qop" do
|
61
|
+
authorization_header.should include(%Q(qop="auth"))
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should set cnonce" do
|
65
|
+
authorization_header.should include(%Q(cnonce="md5(deadbeef)"))
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should set nonce-count" do
|
69
|
+
authorization_header.should include(%Q(nc=00000001))
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should set response" do
|
73
|
+
request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
|
74
|
+
authorization_header.should include(%Q(response="#{request_digest}"))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
context "with unspecified quality of protection (qop)" do
|
80
|
+
before do
|
81
|
+
@digest = setup_digest({
|
82
|
+
'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE"',
|
83
|
+
})
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should set prefix" do
|
87
|
+
authorization_header.should =~ /^Digest /
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should set username" do
|
91
|
+
authorization_header.should include(%Q(username="Mufasa"))
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should set digest-uri" do
|
95
|
+
authorization_header.should include(%Q(uri="/dir/index.html"))
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should not set qop" do
|
99
|
+
authorization_header.should_not include(%Q(qop=))
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should not set cnonce" do
|
103
|
+
authorization_header.should_not include(%Q(cnonce=))
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should not set nonce-count" do
|
107
|
+
authorization_header.should_not include(%Q(nc=))
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should set response" do
|
111
|
+
request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:md5(GET:/dir/index.html))"
|
112
|
+
authorization_header.should include(%Q(response="#{request_digest}"))
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "with multiple authenticate headers" do
|
117
|
+
before do
|
118
|
+
@digest = setup_digest({
|
119
|
+
'www-authenticate' => 'NTLM, Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth"',
|
120
|
+
})
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should set prefix" do
|
124
|
+
authorization_header.should =~ /^Digest /
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should set username" do
|
128
|
+
authorization_header.should include(%Q(username="Mufasa"))
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should set digest-uri" do
|
132
|
+
authorization_header.should include(%Q(uri="/dir/index.html"))
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should set qop" do
|
136
|
+
authorization_header.should include(%Q(qop="auth"))
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should set cnonce" do
|
140
|
+
authorization_header.should include(%Q(cnonce="md5(deadbeef)"))
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should set nonce-count" do
|
144
|
+
authorization_header.should include(%Q(nc=00000001))
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should set response" do
|
148
|
+
request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
|
149
|
+
authorization_header.should include(%Q(response="#{request_digest}"))
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
describe HTTParty::Parser do
|
4
|
+
describe ".SupportedFormats" do
|
5
|
+
it "returns a hash" do
|
6
|
+
HTTParty::Parser::SupportedFormats.should be_instance_of(Hash)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".call" do
|
11
|
+
it "generates an HTTParty::Parser instance with the given body and format" do
|
12
|
+
HTTParty::Parser.should_receive(:new).with('body', :plain).and_return(stub(parse: nil))
|
13
|
+
HTTParty::Parser.call('body', :plain)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "calls #parse on the parser" do
|
17
|
+
parser = mock('Parser')
|
18
|
+
parser.should_receive(:parse)
|
19
|
+
HTTParty::Parser.stub(new: parser)
|
20
|
+
parser = HTTParty::Parser.call('body', :plain)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".formats" do
|
25
|
+
it "returns the SupportedFormats constant" do
|
26
|
+
HTTParty::Parser.formats.should == HTTParty::Parser::SupportedFormats
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns the SupportedFormats constant for subclasses" do
|
30
|
+
class MyParser < HTTParty::Parser
|
31
|
+
SupportedFormats = {"application/atom+xml" => :atom}
|
32
|
+
end
|
33
|
+
MyParser.formats.should == {"application/atom+xml" => :atom}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".format_from_mimetype" do
|
38
|
+
it "returns a symbol representing the format mimetype" do
|
39
|
+
HTTParty::Parser.format_from_mimetype("text/plain").should == :plain
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns nil when the mimetype is not supported" do
|
43
|
+
HTTParty::Parser.format_from_mimetype("application/atom+xml").should be_nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe ".supported_formats" do
|
48
|
+
it "returns a unique set of supported formats represented by symbols" do
|
49
|
+
HTTParty::Parser.supported_formats.should == HTTParty::Parser::SupportedFormats.values.uniq
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe ".supports_format?" do
|
54
|
+
it "returns true for a supported format" do
|
55
|
+
HTTParty::Parser.stub(supported_formats: [:json])
|
56
|
+
HTTParty::Parser.supports_format?(:json).should be_true
|
57
|
+
end
|
58
|
+
|
59
|
+
it "returns false for an unsupported format" do
|
60
|
+
HTTParty::Parser.stub(supported_formats: [])
|
61
|
+
HTTParty::Parser.supports_format?(:json).should be_false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#parse" do
|
66
|
+
before do
|
67
|
+
@parser = HTTParty::Parser.new('body', :json)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "attempts to parse supported formats" do
|
71
|
+
@parser.stub(supports_format?: true)
|
72
|
+
@parser.should_receive(:parse_supported_format)
|
73
|
+
@parser.parse
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returns the unparsed body when the format is unsupported" do
|
77
|
+
@parser.stub(supports_format?: false)
|
78
|
+
@parser.parse.should == @parser.body
|
79
|
+
end
|
80
|
+
|
81
|
+
it "returns nil for an empty body" do
|
82
|
+
@parser.stub(body: '')
|
83
|
+
@parser.parse.should be_nil
|
84
|
+
end
|
85
|
+
|
86
|
+
it "returns nil for a nil body" do
|
87
|
+
@parser.stub(body: nil)
|
88
|
+
@parser.parse.should be_nil
|
89
|
+
end
|
90
|
+
|
91
|
+
it "returns nil for a 'null' body" do
|
92
|
+
@parser.stub(body: "null")
|
93
|
+
@parser.parse.should be_nil
|
94
|
+
end
|
95
|
+
|
96
|
+
it "returns nil for a body with spaces only" do
|
97
|
+
@parser.stub(body: " ")
|
98
|
+
@parser.parse.should be_nil
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#supports_format?" do
|
103
|
+
it "utilizes the class method to determine if the format is supported" do
|
104
|
+
HTTParty::Parser.should_receive(:supports_format?).with(:json)
|
105
|
+
parser = HTTParty::Parser.new('body', :json)
|
106
|
+
parser.send(:supports_format?)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#parse_supported_format" do
|
111
|
+
it "calls the parser for the given format" do
|
112
|
+
parser = HTTParty::Parser.new('body', :json)
|
113
|
+
parser.should_receive(:json)
|
114
|
+
parser.send(:parse_supported_format)
|
115
|
+
end
|
116
|
+
|
117
|
+
context "when a parsing method does not exist for the given format" do
|
118
|
+
it "raises an exception" do
|
119
|
+
parser = HTTParty::Parser.new('body', :atom)
|
120
|
+
expect do
|
121
|
+
parser.send(:parse_supported_format)
|
122
|
+
end.to raise_error(NotImplementedError, "HTTParty::Parser has not implemented a parsing method for the :atom format.")
|
123
|
+
end
|
124
|
+
|
125
|
+
it "raises a useful exception message for subclasses" do
|
126
|
+
atom_parser = Class.new(HTTParty::Parser) do
|
127
|
+
def self.name; 'AtomParser'; end
|
128
|
+
end
|
129
|
+
parser = atom_parser.new 'body', :atom
|
130
|
+
expect do
|
131
|
+
parser.send(:parse_supported_format)
|
132
|
+
end.to raise_error(NotImplementedError, "AtomParser has not implemented a parsing method for the :atom format.")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "parsers" do
|
138
|
+
subject do
|
139
|
+
HTTParty::Parser.new('body', nil)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "parses xml with MultiXml" do
|
143
|
+
MultiXml.should_receive(:parse).with('body')
|
144
|
+
subject.send(:xml)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "parses json with JSON" do
|
148
|
+
JSON.should_receive(:load).with('body', nil)
|
149
|
+
subject.send(:json)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "parses html by simply returning the body" do
|
153
|
+
subject.send(:html).should == 'body'
|
154
|
+
end
|
155
|
+
|
156
|
+
it "parses plain text by simply returning the body" do
|
157
|
+
subject.send(:plain).should == 'body'
|
158
|
+
end
|
159
|
+
|
160
|
+
it "parses csv with CSV" do
|
161
|
+
CSV.should_receive(:parse).with('body')
|
162
|
+
subject.send(:csv)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|