patron-new 0.4.19

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.
@@ -0,0 +1,50 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Patron HTTP Client: Request class
4
+ ## Copyright (c) 2008 The Hive http://www.thehive.com/
5
+ ##
6
+ ## Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ ## of this software and associated documentation files (the "Software"), to deal
8
+ ## in the Software without restriction, including without limitation the rights
9
+ ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ ## copies of the Software, and to permit persons to whom the Software is
11
+ ## furnished to do so, subject to the following conditions:
12
+ ##
13
+ ## The above copyright notice and this permission notice shall be included in
14
+ ## all copies or substantial portions of the Software.
15
+ ##
16
+ ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ ## THE SOFTWARE.
23
+ ##
24
+ ## -------------------------------------------------------------------
25
+
26
+ require 'cgi'
27
+
28
+ module Patron
29
+ module Util
30
+ extend self
31
+
32
+ def build_query_pairs_from_hash(hash, escape_values=false)
33
+ pairs = []
34
+ recursive = Proc.new do |h, prefix|
35
+ h.each_pair do |k,v|
36
+ key = prefix == '' ? k : "#{prefix}[#{k}]"
37
+ v = CGI::escape(v.to_s) if escape_values
38
+ v.is_a?(Hash) ? recursive.call(v, key) : pairs << "#{key}=#{v}"
39
+ end
40
+ end
41
+ recursive.call(hash, '')
42
+ pairs
43
+ end
44
+
45
+ def build_query_string_from_hash(hash, escape_values=false)
46
+ build_query_pairs_from_hash(hash, escape_values).join('&')
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,3 @@
1
+ module Patron
2
+ VERSION = "0.4.19"
3
+ end
data/patron.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/patron/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "patron-new"
6
+ s.version = Patron::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Phillip Toland"]
9
+ s.email = ["phil.toland@gmail.com"]
10
+ s.homepage = "https://github.com/toland/patron"
11
+ s.summary = "Patron HTTP Client"
12
+ s.description = "Ruby HTTP client library based on libcurl, base on Patron, bug it keep with the github code!"
13
+
14
+ s.required_rubygems_version = ">= 1.2.0"
15
+
16
+ s.add_development_dependency "bundler", ">= 1.0.0"
17
+ s.add_development_dependency "rake-compiler", ">= 0.7.5"
18
+ s.add_development_dependency "rspec", ">= 2.3.0"
19
+ s.add_development_dependency "rcov", ">= 0.9.9"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
23
+ s.require_paths = ["lib", "ext"]
24
+ s.extensions = ["ext/patron/extconf.rb"]
25
+ end
26
+
data/pic.png ADDED
Binary file
data/script/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ cwd = File.dirname(__FILE__)
6
+
7
+ libs = " -I#{cwd + '/../lib'} -I#{cwd + '/../ext'}"
8
+ libs << " -r patron -r irb/completion"
9
+
10
+ puts "Loading Patron"
11
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ ## -------------------------------------------------------------------
3
+ ##
4
+ ## Patron HTTP Client: HTTP test server for integration tests
5
+ ## Copyright (c) 2008 The Hive http://www.thehive.com/
6
+ ##
7
+ ## Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ ## of this software and associated documentation files (the "Software"), to deal
9
+ ## in the Software without restriction, including without limitation the rights
10
+ ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ ## copies of the Software, and to permit persons to whom the Software is
12
+ ## furnished to do so, subject to the following conditions:
13
+ ##
14
+ ## The above copyright notice and this permission notice shall be included in
15
+ ## all copies or substantial portions of the Software.
16
+ ##
17
+ ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ ## THE SOFTWARE.
24
+ ##
25
+ ## -------------------------------------------------------------------
26
+
27
+ root = File.expand_path('../..', __FILE__)
28
+ require File.join(root, %w[spec support test_server.rb])
29
+
30
+ PatronTestServer.start($stderr).join
@@ -0,0 +1,36 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ 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
35
+ djS6lZ9vTEbRM+GhU2PMKfvJbiQ/Y6Q=
36
+ -----END CERTIFICATE-----
@@ -0,0 +1,51 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ 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
38
+ Tmsg4oRHzfquVnr6GK6x7ZHIo5mpHHHdOiyp/UD+anfbbMRItcHkzHDctkaoOKWI
39
+ h3P0mYZ5LIJNVuErhucrP57tr+bOOttus9HLHXTYsjOGV4zSKUSVQTOxnTzZepd8
40
+ zIdo+wKCAQAg/Z80RPYGd/IVmD0NWxDbRhfEXn37XhRr1eIfNLjpktMGQENSiPEI
41
+ FM12S+xSUOC31Hs5u+BNop1kCfd1yuf4NxC8eyMjKO3tM90wc+KUMLeh9TdPZ96J
42
+ dD96eVftTuavTkdFZdWB8wSwxDZX3uV4ir1t6bIKDoyz+yqYM3v3HfweJIq0ox2p
43
+ TS40cDDWnt/ZIk3TyMS1QPWbr0Jl8or0JYmRVp1m8jiDwcsp9tUd9+/5bgKhC3uM
44
+ tY0HjOULzvvHkkul5ADAHyNS7zq9lEwEhIilkhX3M0wX3ZxvXwJPUbgYurcbNmgd
45
+ imp6DpuPJPdbg/8bz9YiaAZOnObnE9lFAoIBAGIdAhDDhqhPIW3xDx54TBfxQFi+
46
+ CeFw1g2duwXAXkBV98nKeLdTo3tL8gusb+32LzgVIq2spWUN72xXX40NJjW1Bxk5
47
+ SGatM1T13BaUFNYtzpM9arDPNr3tCiCSzeVvMKdLfp+Vx9R9arnOgLlGkhRCdEtb
48
+ lXAteE7Twuztvad/M0LGpbjN6BD23KLOfxx9C2TgfMuK/Fjt71ASV+80cq4SS2WK
49
+ fqZQnKfGIRE8wcY2R5g2AwEzubCRzD93pGG3KleQKxrUKNoV32M2ZZcM04l8woZX
50
+ vrkNxM3gbBkhFPAJ9LrmA4YExODUXzWt6Y2mCXuH2Ly60yiLa66HbEfhHrs=
51
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,38 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) 2008 The Hive http://www.thehive.com/
4
+ ##
5
+ ## Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ ## of this software and associated documentation files (the "Software"), to deal
7
+ ## in the Software without restriction, including without limitation the rights
8
+ ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ ## copies of the Software, and to permit persons to whom the Software is
10
+ ## furnished to do so, subject to the following conditions:
11
+ ##
12
+ ## The above copyright notice and this permission notice shall be included in
13
+ ## all copies or substantial portions of the Software.
14
+ ##
15
+ ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ ## THE SOFTWARE.
22
+ ##
23
+ ## -------------------------------------------------------------------
24
+ require File.expand_path("./spec") + '/spec_helper.rb'
25
+
26
+ describe Patron do
27
+
28
+ it "should return the version number of the Patron library" do
29
+ version = Patron.version
30
+ version.should match(%r|^\d+.\d+.\d+$|)
31
+ end
32
+
33
+ it "should return the version number of the libcurl library" do
34
+ version = Patron.libcurl_version
35
+ version.should match(%r|^libcurl/\d+.\d+.\d+|)
36
+ end
37
+
38
+ end
@@ -0,0 +1,104 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) 2008 The Hive http://www.thehive.com/
4
+ ##
5
+ ## Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ ## of this software and associated documentation files (the "Software"), to deal
7
+ ## in the Software without restriction, including without limitation the rights
8
+ ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ ## copies of the Software, and to permit persons to whom the Software is
10
+ ## furnished to do so, subject to the following conditions:
11
+ ##
12
+ ## The above copyright notice and this permission notice shall be included in
13
+ ## all copies or substantial portions of the Software.
14
+ ##
15
+ ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ ## THE SOFTWARE.
22
+ ##
23
+ ## -------------------------------------------------------------------
24
+ require File.expand_path("./spec") + '/spec_helper.rb'
25
+
26
+
27
+ describe Patron::Request do
28
+
29
+ before(:each) do
30
+ @request = Patron::Request.new
31
+ end
32
+
33
+ describe :action do
34
+
35
+ it "should accept :get, :put, :post, :delete and :head" do
36
+ [:get, :put, :post, :delete, :head, :copy].each do |action|
37
+ lambda {@request.action = action}.should_not raise_error
38
+ end
39
+ end
40
+
41
+ it "should raise an exception when assigned a bad value" do
42
+ lambda {@request.action = :foo}.should raise_error(ArgumentError)
43
+ end
44
+
45
+ end
46
+
47
+ describe :timeout do
48
+
49
+ it "should raise an exception when assigned a negative number" do
50
+ lambda {@request.timeout = -1}.should raise_error(ArgumentError)
51
+ end
52
+
53
+ it "should raise an exception when assigned 0" do
54
+ lambda {@request.timeout = 0}.should raise_error(ArgumentError)
55
+ end
56
+
57
+ end
58
+
59
+ describe :max_redirects do
60
+
61
+ it "should raise an error when assigned an integer smaller than -1" do
62
+ lambda {@request.max_redirects = -2}.should raise_error(ArgumentError)
63
+ end
64
+
65
+ end
66
+
67
+ describe :headers do
68
+
69
+ it "should raise an error when assigned something other than a hash" do
70
+ lambda {@request.headers = :foo}.should raise_error(ArgumentError)
71
+ end
72
+
73
+ end
74
+
75
+ describe :buffer_size do
76
+
77
+ it "should raise an exception when assigned a negative number" do
78
+ lambda {@request.buffer_size = -1}.should raise_error(ArgumentError)
79
+ end
80
+
81
+ it "should raise an exception when assigned 0" do
82
+ lambda {@request.buffer_size = 0}.should raise_error(ArgumentError)
83
+ end
84
+
85
+ end
86
+
87
+ describe :eql? do
88
+
89
+ it "should return true when two requests are equal" do
90
+ @request.should eql(Patron::Request.new)
91
+ end
92
+
93
+ it "should return false when two requests are not equal" do
94
+ req = Patron::Request.new
95
+ req.action = :post
96
+ @request.should_not eql(req)
97
+ end
98
+
99
+ end
100
+
101
+ it "should be able to serialize and deserialize itself" do
102
+ Marshal.load(Marshal.dump(@request)).should eql(@request)
103
+ end
104
+ end
@@ -0,0 +1,62 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) 2009 Phillip Toland <phil.toland@gmail.com>
4
+ ##
5
+ ## Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ ## of this software and associated documentation files (the "Software"), to deal
7
+ ## in the Software without restriction, including without limitation the rights
8
+ ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ ## copies of the Software, and to permit persons to whom the Software is
10
+ ## furnished to do so, subject to the following conditions:
11
+ ##
12
+ ## The above copyright notice and this permission notice shall be included in
13
+ ## all copies or substantial portions of the Software.
14
+ ##
15
+ ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ ## THE SOFTWARE.
22
+ ##
23
+ ## -------------------------------------------------------------------
24
+ require File.expand_path("./spec") + '/spec_helper.rb'
25
+ require 'webrick'
26
+ require 'base64'
27
+ require 'fileutils'
28
+
29
+ describe Patron::Response do
30
+ before(:each) do
31
+ @session = Patron::Session.new
32
+ @session.base_url = "http://localhost:9001"
33
+ end
34
+
35
+ it "should strip extra spaces from header values" do
36
+ response = @session.get("/test")
37
+ # All digits, no spaces
38
+ response.headers['Content-Length'].should match(/^\d+$/)
39
+ end
40
+
41
+ it "should return an array of values when multiple header fields have same name" do
42
+ response = @session.get("/repetitiveheader")
43
+ response.headers['Set-Cookie'].should == ["a=1","b=2"]
44
+ end
45
+
46
+ it "should works with non-text files" do
47
+ response = @session.get("/picture")
48
+ response.headers['Content-Type'].should == 'image/png'
49
+ response.body.encoding.should == Encoding::ASCII_8BIT
50
+ end
51
+
52
+ it "should not allow a default charset to be nil" do
53
+ Encoding.stub(:default_internal).and_return("UTF-8")
54
+ expect {
55
+ Patron::Response.new("url", "status", 0, "", "", nil)
56
+ }.to_not raise_error
57
+ end
58
+
59
+ it "should be able to serialize and deserialize itself" do
60
+ Marshal.load(Marshal.dump(@request)).should eql(@request)
61
+ end
62
+ end
@@ -0,0 +1,338 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) 2008 The Hive http://www.thehive.com/
4
+ ##
5
+ ## Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ ## of this software and associated documentation files (the "Software"), to deal
7
+ ## in the Software without restriction, including without limitation the rights
8
+ ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ ## copies of the Software, and to permit persons to whom the Software is
10
+ ## furnished to do so, subject to the following conditions:
11
+ ##
12
+ ## The above copyright notice and this permission notice shall be included in
13
+ ## all copies or substantial portions of the Software.
14
+ ##
15
+ ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ ## THE SOFTWARE.
22
+ ##
23
+ ## -------------------------------------------------------------------
24
+ require File.expand_path("./spec") + '/spec_helper.rb'
25
+ require 'webrick'
26
+ require 'yaml'
27
+ require 'base64'
28
+ require 'fileutils'
29
+
30
+ describe Patron::Session do
31
+
32
+ before(:each) do
33
+ @session = Patron::Session.new
34
+ @session.base_url = "http://localhost:9001"
35
+ end
36
+
37
+ it "should escape and unescape strings symetrically" do
38
+ string = "foo~bar baz/"
39
+ escaped = @session.escape(string)
40
+ unescaped = @session.unescape(escaped)
41
+ unescaped.should == string
42
+ end
43
+
44
+ it "should raise an error when passed an invalid action" do
45
+ lambda { @session.request(:bogus, "/test", {}) }.should raise_error(ArgumentError)
46
+ end
47
+
48
+ it "should raise an error when no URL is provided" do
49
+ @session.base_url = nil
50
+ lambda {@session.get(nil)}.should raise_error(ArgumentError)
51
+ end
52
+
53
+ it "should retrieve a url with :get" do
54
+ response = @session.get("/test")
55
+ body = YAML::load(response.body)
56
+ body.request_method.should == "GET"
57
+ end
58
+
59
+ it 'should ignore #base_url when a full URL is provided' do
60
+ @session.base_url = "http://example.com:123"
61
+ lambda { @session.get("http://localhost:9001/test") }.should_not raise_error(URI::InvalidURIError)
62
+ end
63
+
64
+ it "should download content with :get and a file path" do
65
+ tmpfile = "/tmp/patron_test.yaml"
66
+ response = @session.get_file "/test", tmpfile
67
+ response.body.should be_nil
68
+ body = YAML::load_file(tmpfile)
69
+ body.request_method.should == "GET"
70
+ FileUtils.rm tmpfile
71
+ end
72
+
73
+ it "should download correctly(md5 ok) with get_file" do
74
+ tmpfile = "/tmp/picture"
75
+ response = @session.get_file "/picture", tmpfile
76
+ response.body.should be_nil
77
+ File.size(File.join(File.dirname(__FILE__),"../pic.png")).should == File.size(tmpfile)
78
+ FileUtils.rm tmpfile
79
+ end
80
+
81
+ it "should include custom headers in a request" do
82
+ response = @session.get("/test", {"User-Agent" => "PatronTest"})
83
+ body = YAML::load(response.body)
84
+ body.header["user-agent"].should == ["PatronTest"]
85
+ end
86
+
87
+ it "should include default headers in a request, if they were defined" do
88
+ @session.headers = {"User-Agent" => "PatronTest"}
89
+ response = @session.get("/test")
90
+ body = YAML::load(response.body)
91
+ body.header["user-agent"].should == ["PatronTest"]
92
+ end
93
+
94
+ it "should merge custom headers with session headers" do
95
+ @session.headers["X-Test"] = "Testing"
96
+ response = @session.get("/test", {"User-Agent" => "PatronTest"})
97
+ body = YAML::load(response.body)
98
+ body.header["user-agent"].should == ["PatronTest"]
99
+ body.header["x-test"].should == ["Testing"]
100
+ end
101
+
102
+ it "should raise an exception on timeout" do
103
+ @session.timeout = 1
104
+ lambda {@session.get("/timeout")}.should raise_error(Patron::TimeoutError)
105
+ end
106
+
107
+ it "should follow redirects by default" do
108
+ @session.max_redirects = 1
109
+ response = @session.get("/redirect")
110
+ body = YAML::load(response.body)
111
+ response.status.should == 200
112
+ body.path.should == "/test"
113
+ end
114
+
115
+ it "should include redirect count in response" do
116
+ @session.max_redirects = 1
117
+ response = @session.get("/redirect")
118
+ response.redirect_count.should == 1
119
+ end
120
+
121
+ it "should not follow redirects when configured to do so" do
122
+ @session.max_redirects = 0
123
+ response = @session.get("/redirect")
124
+ response.status.should == 301
125
+ response.body.should be_empty
126
+ end
127
+
128
+ it "should retrieve URL metadata with :head" do
129
+ response = @session.head("/test")
130
+ response.status.should == 200
131
+ response.body.should be_empty
132
+ response.headers.should_not be_empty
133
+ end
134
+
135
+ it "should send a delete request with :delete" do
136
+ response = @session.delete("/test")
137
+ body = YAML::load(response.body)
138
+ body.request_method.should == "DELETE"
139
+ end
140
+
141
+ it "should send a COPY request with :copy" do
142
+ response = @session.copy("/test", "/test2")
143
+ body = YAML::load(response.body)
144
+ body.request_method.should == "COPY"
145
+ end
146
+
147
+ it "should include a Destination header in COPY requests" do
148
+ response = @session.copy("/test", "/test2")
149
+ body = YAML::load(response.body)
150
+ body.header['destination'].first.should == "/test2"
151
+ end
152
+
153
+ it "should upload data with :get" do
154
+ data = "upload data"
155
+ response = @session.request(:get, "/test", {}, :data => data)
156
+ body = YAML::load(response.body)
157
+ body.request_method.should == "GET"
158
+ body.header['content-length'].should == [data.size.to_s]
159
+ end
160
+
161
+ it "should upload data with :put" do
162
+ data = "upload data"
163
+ response = @session.put("/test", data)
164
+ body = YAML::load(response.body)
165
+ body.request_method.should == "PUT"
166
+ body.header['content-length'].should == [data.size.to_s]
167
+ end
168
+
169
+ it "should upload data with :delete" do
170
+ data = "upload data"
171
+ response = @session.request(:delete, "/test", {}, :data => data)
172
+ body = YAML::load(response.body)
173
+ body.request_method.should == "DELETE"
174
+ body.header['content-length'].should == [data.size.to_s]
175
+ end
176
+
177
+ it "should raise when no data is provided to :put" do
178
+ lambda { @session.put("/test", nil) }.should raise_error(ArgumentError)
179
+ end
180
+
181
+ it "should upload a file with :put" do
182
+ response = @session.put_file("/test", "LICENSE")
183
+ body = YAML::load(response.body)
184
+ body.request_method.should == "PUT"
185
+ end
186
+
187
+ it "should raise when no file is provided to :put" do
188
+ lambda { @session.put_file("/test", nil) }.should raise_error(ArgumentError)
189
+ end
190
+
191
+ it "should use chunked encoding when uploading a file with :put" do
192
+ response = @session.put_file("/test", "LICENSE")
193
+ body = YAML::load(response.body)
194
+ body.header['transfer-encoding'].first.should == "chunked"
195
+ end
196
+
197
+ it "should upload data with :post" do
198
+ data = "upload data"
199
+ response = @session.post("/test", data)
200
+ body = YAML::load(response.body)
201
+ body.request_method.should == "POST"
202
+ body.header['content-length'].should == [data.size.to_s]
203
+ end
204
+
205
+ it "should post a hash of arguments as a urlencoded form" do
206
+ data = {:foo => 123, 'baz' => '++hello world++'}
207
+ response = @session.post("/testpost", data)
208
+ body = YAML::load(response.body)
209
+ body['content_type'].should == "application/x-www-form-urlencoded"
210
+ body['body'].should match(/baz=%2B%2Bhello%20world%2B%2B/)
211
+ body['body'].should match(/foo=123/)
212
+ end
213
+
214
+ it "should raise when no data is provided to :post" do
215
+ lambda { @session.post("/test", nil) }.should raise_error(ArgumentError)
216
+ end
217
+
218
+ it "should upload a file with :post" do
219
+ response = @session.post_file("/test", "LICENSE")
220
+ body = YAML::load(response.body)
221
+ body.request_method.should == "POST"
222
+ end
223
+
224
+ it "should upload a multipart with :post" do
225
+ response = @session.post_multipart("/test", { :test_data => "123" }, { :test_file => "LICENSE" } )
226
+ body = YAML::load(response.body)
227
+ body.request_method.should == "POST"
228
+ end
229
+
230
+ it "should raise when no file is provided to :post" do
231
+ lambda { @session.post_file("/test", nil) }.should raise_error(ArgumentError)
232
+ end
233
+
234
+ it "should use chunked encoding when uploading a file with :post" do
235
+ response = @session.post_file("/test", "LICENSE")
236
+ body = YAML::load(response.body)
237
+ body.header['transfer-encoding'].first.should == "chunked"
238
+ end
239
+
240
+ it "should pass credentials as http basic auth" do
241
+ @session.username = "foo"
242
+ @session.password = "bar"
243
+ response = @session.get("/test")
244
+ body = YAML::load(response.body)
245
+ body.header['authorization'].should == [encode_authz("foo", "bar")]
246
+ end
247
+
248
+ it "should handle cookies if set" do
249
+ @session.handle_cookies
250
+ response = @session.get("/setcookie").body
251
+ YAML::load(response).header['cookie'].first.should == "session_id=foo123"
252
+ end
253
+
254
+ it "should not handle cookies by default" do
255
+ response = @session.get("/setcookie").body
256
+ YAML::load(response).header.should_not include('cookie')
257
+ end
258
+
259
+ it "should ignore a wrong Content-Length when asked to" do
260
+ lambda {
261
+ @session.ignore_content_length = true
262
+ @session.get("/wrongcontentlength")
263
+ }.should_not raise_error
264
+ end
265
+
266
+ it "should fail by default with a Content-Length too high" do
267
+ lambda {
268
+ @session.ignore_content_length = nil
269
+ @session.get("/wrongcontentlength")
270
+ }.should raise_error(Patron::PartialFileError)
271
+ end
272
+
273
+ it "should raise exception if cookie store is not writable or readable" do
274
+ lambda { @session.handle_cookies("/trash/clash/foo") }.should raise_error(ArgumentError)
275
+ end
276
+
277
+ it "should work with multiple threads" do
278
+ threads = []
279
+ 3.times do
280
+ threads << Thread.new do
281
+ session = Patron::Session.new
282
+ session.base_url = "http://localhost:9001"
283
+ session.post_file("/test", "LICENSE")
284
+ end
285
+ end
286
+ threads.each {|t| t.join }
287
+ end
288
+
289
+ it "should limit the buffer_size" do
290
+ # Buffer size is tricky to test, as it only affects the buffer size for each
291
+ # read and it's not really visible at this, higher level. It's also only a
292
+ # suggestion rather than a command so it may not even take affect. Currently
293
+ # we just test that the response completes without any issues, it would be nice
294
+ # to have a more robust test here.
295
+ @session.buffer_size = 1
296
+
297
+ body = nil
298
+
299
+ lambda {
300
+ response = @session.get("/test")
301
+ body = YAML::load(response.body)
302
+ }.should_not raise_error
303
+
304
+ body.request_method.should == "GET"
305
+ end
306
+
307
+ it "should serialize query params and append them to the url" do
308
+ response = @session.request(:get, "/test", {}, :query => {:foo => "bar"})
309
+ request = YAML::load(response.body)
310
+ request.parse
311
+ (request.path + '?' + request.query_string).should == "/test?foo=bar"
312
+ end
313
+
314
+ it "should merge parameters in the :query option with pre-existing query parameters" do
315
+ response = @session.request(:get, "/test?foo=bar", {}, :query => {:baz => "quux"})
316
+ request = YAML::load(response.body)
317
+ request.parse
318
+ (request.path + '?' + request.query_string).should == "/test?foo=bar&baz=quux"
319
+ end
320
+
321
+ def encode_authz(user, passwd)
322
+ "Basic " + Base64.encode64("#{user}:#{passwd}").strip
323
+ end
324
+
325
+ # ------------------------------------------------------------------------
326
+ describe 'when debug is enabled' do
327
+ it 'it should not clobber stderr' do
328
+ rdev = STDERR.stat.rdev
329
+
330
+ @session.enable_debug
331
+ STDERR.stat.rdev.should be == rdev
332
+
333
+ @session.enable_debug
334
+ STDERR.stat.rdev.should be == rdev
335
+ end
336
+ end
337
+
338
+ end