patron 0.13.3 → 0.13.4

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.
@@ -6,6 +6,14 @@ require 'fileutils'
6
6
 
7
7
  describe Patron::Session do
8
8
 
9
+ def yaml_load(str)
10
+ if RUBY_VERSION >= '3.1.0'
11
+ YAML::safe_load(str, permitted_classes: [OpenStruct])
12
+ else
13
+ YAML::load(str)
14
+ end
15
+ end
16
+
9
17
  before(:each) do
10
18
  @session = Patron::Session.new
11
19
  @session.base_url = "https://localhost:9043"
@@ -14,7 +22,7 @@ describe Patron::Session do
14
22
 
15
23
  it "should retrieve a url with :get" do
16
24
  response = @session.get("/test")
17
- body = YAML::load(response.body)
25
+ body = yaml_load(response.body)
18
26
  expect(body.request_method).to be == "GET"
19
27
  end
20
28
 
@@ -22,7 +30,7 @@ describe Patron::Session do
22
30
  tmpfile = "/tmp/patron_test.yaml"
23
31
  response = @session.get_file "/test", tmpfile
24
32
  expect(response.body).to be_nil
25
- body = YAML::load_file(tmpfile)
33
+ body = yaml_load(File.open(tmpfile).read)
26
34
  expect(body.request_method).to be == "GET"
27
35
  FileUtils.rm tmpfile
28
36
  end
@@ -39,7 +47,7 @@ describe Patron::Session do
39
47
  pid = fork do
40
48
  response = @session.get_file "/test", tmpfile
41
49
  expect(response.body).to be_nil
42
- body = YAML::load_file(tmpfile)
50
+ body = yaml_load(File.open(tmpfile).read)
43
51
  expect(body.request_method).to be == "GET"
44
52
  FileUtils.rm tmpfile
45
53
  end
@@ -58,14 +66,14 @@ describe Patron::Session do
58
66
 
59
67
  it "should include custom headers in a request" do
60
68
  response = @session.get("/test", {"User-Agent" => "PatronTest"})
61
- body = YAML::load(response.body)
69
+ body = yaml_load(response.body)
62
70
  expect(body.header["user-agent"]).to be == ["PatronTest"]
63
71
  end
64
72
 
65
73
  it "should merge custom headers with session headers" do
66
74
  @session.headers["X-Test"] = "Testing"
67
75
  response = @session.get("/test", {"User-Agent" => "PatronTest"})
68
- body = YAML::load(response.body)
76
+ body = yaml_load(response.body)
69
77
  expect(body.header["user-agent"]).to be == ["PatronTest"]
70
78
  expect(body.header["x-test"]).to be == ["Testing"]
71
79
  end
@@ -80,7 +88,7 @@ describe Patron::Session do
80
88
  it "should follow redirects by default" do
81
89
  @session.max_redirects = 1
82
90
  response = @session.get("/redirect")
83
- body = YAML::load(response.body)
91
+ body = yaml_load(response.body)
84
92
  expect(response.status).to be == 200
85
93
  expect(body.path).to be == "/test"
86
94
  end
@@ -107,26 +115,26 @@ describe Patron::Session do
107
115
 
108
116
  it "should send a delete request with :delete" do
109
117
  response = @session.delete("/test")
110
- body = YAML::load(response.body)
118
+ body = yaml_load(response.body)
111
119
  expect(body.request_method).to be == "DELETE"
112
120
  end
113
121
 
114
122
  it "should send a COPY request with :copy" do
115
123
  response = @session.copy("/test", "/test2")
116
- body = YAML::load(response.body)
124
+ body = yaml_load(response.body)
117
125
  expect(body.request_method).to be == "COPY"
118
126
  end
119
127
 
120
128
  it "should include a Destination header in COPY requests" do
121
129
  response = @session.copy("/test", "/test2")
122
- body = YAML::load(response.body)
130
+ body = yaml_load(response.body)
123
131
  expect(body.header['destination'].first).to be == "/test2"
124
132
  end
125
133
 
126
134
  it "should upload data with :get" do
127
135
  data = "upload data"
128
136
  response = @session.request(:get, "/test", {}, :data => data)
129
- body = YAML::load(response.body)
137
+ body = yaml_load(response.body)
130
138
  expect(body.request_method).to be == "GET"
131
139
  expect(body.header['content-length']).to be == [data.size.to_s]
132
140
  end
@@ -134,7 +142,7 @@ describe Patron::Session do
134
142
  it "should upload data with :put" do
135
143
  data = "upload data"
136
144
  response = @session.put("/test", data)
137
- body = YAML::load(response.body)
145
+ body = yaml_load(response.body)
138
146
  expect(body.request_method).to be == "PUT"
139
147
  expect(body.header['content-length']).to be == [data.size.to_s]
140
148
  end
@@ -145,7 +153,7 @@ describe Patron::Session do
145
153
 
146
154
  it "should upload a file with :put" do
147
155
  response = @session.put_file("/test", "LICENSE")
148
- body = YAML::load(response.body)
156
+ body = yaml_load(response.body)
149
157
  expect(body.request_method).to be == "PUT"
150
158
  end
151
159
 
@@ -155,14 +163,14 @@ describe Patron::Session do
155
163
 
156
164
  it "should use chunked encoding when uploading a file with :put" do
157
165
  response = @session.put_file("/test", "LICENSE")
158
- body = YAML::load(response.body)
166
+ body = yaml_load(response.body)
159
167
  expect(body.header['transfer-encoding'].first).to be == "chunked"
160
168
  end
161
169
 
162
170
  it "should upload data with :post" do
163
171
  data = "upload data"
164
172
  response = @session.post("/test", data)
165
- body = YAML::load(response.body)
173
+ body = yaml_load(response.body)
166
174
  expect(body.request_method).to be == "POST"
167
175
  expect(body.header['content-length']).to be == [data.size.to_s]
168
176
  end
@@ -170,7 +178,7 @@ describe Patron::Session do
170
178
  it "should post a hash of arguments as a urlencoded form" do
171
179
  data = {:foo => 123, 'baz' => '++hello world++'}
172
180
  response = @session.post("/testpost", data)
173
- body = YAML::load(response.body)
181
+ body = yaml_load(response.body)
174
182
  expect(body['content_type']).to be == "application/x-www-form-urlencoded"
175
183
  expect(body['body']).to match(/baz=%2B%2Bhello%20world%2B%2B/)
176
184
  expect(body['body']).to match(/foo=123/)
@@ -182,13 +190,13 @@ describe Patron::Session do
182
190
 
183
191
  it "should upload a file with :post" do
184
192
  response = @session.post_file("/test", "LICENSE")
185
- body = YAML::load(response.body)
193
+ body = yaml_load(response.body)
186
194
  expect(body.request_method).to be == "POST"
187
195
  end
188
196
 
189
197
  it "should upload a multipart with :post" do
190
198
  response = @session.post_multipart("/test", { :test_data => "123" }, { :test_file => "LICENSE" } )
191
- body = YAML::load(response.body)
199
+ body = yaml_load(response.body)
192
200
  expect(body.request_method).to be == "POST"
193
201
  end
194
202
 
@@ -198,19 +206,19 @@ describe Patron::Session do
198
206
 
199
207
  it "should use chunked encoding when uploading a file with :post" do
200
208
  response = @session.post_file("/test", "LICENSE")
201
- body = YAML::load(response.body)
209
+ body = yaml_load(response.body)
202
210
  expect(body.header['transfer-encoding'].first).to be == "chunked"
203
211
  end
204
212
 
205
213
  it "should handle cookies if set" do
206
214
  @session.handle_cookies
207
215
  response = @session.get("/setcookie").body
208
- expect(YAML::load(response).header['cookie'].first).to be == "session_id=foo123"
216
+ expect(yaml_load(response).header['cookie'].first).to be == "session_id=foo123"
209
217
  end
210
218
 
211
219
  it "should not handle cookies by default" do
212
220
  response = @session.get("/setcookie").body
213
- expect(YAML::load(response).header).to_not include('cookie')
221
+ expect(yaml_load(response).header).to_not include('cookie')
214
222
  end
215
223
 
216
224
  it "should raise exception if cookie store is not writable or readable" do
@@ -241,10 +249,20 @@ describe Patron::Session do
241
249
  @session.insecure = nil
242
250
  @session.cacert = File.join(__dir__, 'support', 'certs', 'cacert.pem')
243
251
  response = @session.get("/test")
244
- body = YAML::load(response.body)
252
+ body = yaml_load(response.body)
245
253
  expect(body.request_method).to be == "GET"
246
254
  end
247
255
 
256
+ it "should allow to specify insecure mode per-request" do
257
+ @session.insecure = false
258
+ expect {
259
+ @session.request(:get, "/test", {}, insecure: true)
260
+ }.not_to raise_error
261
+ expect {
262
+ @session.request(:get, "/test", {})
263
+ }.to raise_error(Patron::Error)
264
+ end
265
+
248
266
  it "should work with different SSL versions" do
249
267
  ['TLSv1_0','TLSv1_1'].each do |version|
250
268
  @session.ssl_version = version
data/spec/spec_helper.rb CHANGED
@@ -18,14 +18,17 @@ $stderr.puts "Build against #{Patron.libcurl_version}"
18
18
 
19
19
  Dir['./spec/support/**/*.rb'].each { |fn| require fn }
20
20
 
21
- http_server_pid = Process.fork { PatronTestServer.start(false, 9001) }
22
- https_server_pid = Process.fork { PatronTestServer.start(true, 9043) }
21
+ http_server = Fork.new { PatronTestServer.start(false, 9001) }
22
+
23
+ sleep 0.1 # Don't interfere the start up output of two processes.
24
+
25
+ https_server = Fork.new { PatronTestServer.start(true, 9043) }
23
26
 
24
27
  RSpec.configure do |c|
25
28
  c.after(:suite) do
26
- Process.kill("INT", http_server_pid)
27
- Process.kill("INT", https_server_pid)
28
- Process.wait(http_server_pid)
29
- Process.wait(https_server_pid)
29
+ http_server.kill("TERM")
30
+ https_server.kill("TERM")
31
+ http_server.wait
32
+ https_server.wait
30
33
  end
31
- end
34
+ end
@@ -67,7 +67,7 @@ TimeoutServlet = Proc.new {|env|
67
67
  SlowServlet = Proc.new {|env|
68
68
  body = Enumerator.new do |y|
69
69
  y.yield 'x'
70
- sleep 20
70
+ sleep 5
71
71
  y.yield 'rest of body'
72
72
  end
73
73
  [200, {'Content-Type' => 'text/plain'}, body]
@@ -102,7 +102,13 @@ RepetitiveHeaderServlet = Proc.new {|env|
102
102
  }
103
103
 
104
104
  PictureServlet = Proc.new {|env|
105
- [200, {'Content-Type' => 'image/png'}, [File.read('./pic.png')]]
105
+ # Rack::File allows us to test Range support as well
106
+ env_with_adjusted_path = env.merge('PATH_INFO' => Rack::Utils.escape('/pic.png'))
107
+ Rack::File.new('./').call(env_with_adjusted_path)
108
+ }
109
+
110
+ RedirectToPictureServlet = Proc.new {|env|
111
+ [307, {'Location' => '/picture'}, []]
106
112
  }
107
113
 
108
114
  WrongContentLengthServlet = Proc.new {|env|
@@ -111,10 +117,11 @@ WrongContentLengthServlet = Proc.new {|env|
111
117
 
112
118
  # Serves a substantial amount of data
113
119
  LargeServlet = Proc.new {|env|
120
+ rng = Random.new
114
121
  len = 15 * 1024 * 1024
115
122
  body = Enumerator.new do |y|
116
123
  15.times do
117
- y.yield(Random.new.bytes(1024 * 1024))
124
+ y.yield(rng.bytes(1024 * 1024))
118
125
  end
119
126
  end
120
127
  [200, {'Content-Type' => 'binary/octet-stream', 'Content-Length' => len.to_s}, body]
@@ -130,6 +137,7 @@ run Rack::URLMap.new({
130
137
  "/redirect" => RedirectServlet,
131
138
  "/evil-redirect" => EvilRedirectServlet,
132
139
  "/picture" => PictureServlet,
140
+ "/redirect-to-picture" => RedirectToPictureServlet,
133
141
  "/very-large" => LargeServlet,
134
142
  "/setcookie" => SetCookieServlet,
135
143
  "/repetitiveheader" => RepetitiveHeaderServlet,
@@ -0,0 +1,70 @@
1
+ require 'thread'
2
+
3
+ class Fork
4
+ def initialize(&block)
5
+ @mu = Mutex.new
6
+ @cond = ConditionVariable.new
7
+ @pstate = nil
8
+ @pid = Process.fork(&block)
9
+ @killed = false
10
+
11
+ # Start monitoring the PID.
12
+ Thread.new { monitor }
13
+
14
+ # Kill the process anyway when the program exits.
15
+ ppid = Process.pid
16
+ at_exit do
17
+ if ppid == Process.pid # Make sure we are not inside another fork spawned by rspec example.
18
+ do_kill("KILL")
19
+ end
20
+ end
21
+ end
22
+
23
+ # Wait for process to exit.
24
+ def wait(timeout = nil)
25
+ @mu.synchronize do
26
+ next @pstate unless @pstate.nil?
27
+
28
+ @cond.wait(@mu, timeout)
29
+ @pstate
30
+ end
31
+ end
32
+
33
+ # Signal the process.
34
+ def kill(sig)
35
+ already_killed = @mu.synchronize do
36
+ old = @killed
37
+ @killed = true
38
+ old
39
+ end
40
+ signaled = do_kill(sig)
41
+ Thread.new { reaper } if signaled && !already_killed
42
+ signaled
43
+ end
44
+
45
+ private
46
+
47
+ # Signal the process.
48
+ def do_kill(sig)
49
+ Process.kill(sig, @pid)
50
+ true
51
+ rescue Errno::ESRCH # No such process
52
+ false
53
+ end
54
+
55
+ # Monitor the process state.
56
+ def monitor
57
+ _, pstate = Process.wait2(@pid)
58
+
59
+ @mu.synchronize do
60
+ @pstate = pstate
61
+ @cond.broadcast
62
+ end
63
+ end
64
+
65
+ # Wait 500 milliseconds and force terminate.
66
+ def reaper
67
+ pstate = wait(0.5)
68
+ do_kill("KILL") unless pstate
69
+ end
70
+ end
metadata CHANGED
@@ -1,136 +1,24 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: patron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.3
4
+ version: 0.13.4
5
5
  platform: ruby
6
6
  authors:
7
- - Phillip Toland
8
- autorequire:
7
+ - Aeryn Riley Dowling-Toland
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2019-05-22 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: rake
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '10'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '10'
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: 2.3.0
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: 2.3.0
55
- - !ruby/object:Gem::Dependency
56
- name: simplecov
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '0.10'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '0.10'
69
- - !ruby/object:Gem::Dependency
70
- name: yard
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 0.9.11
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 0.9.11
83
- - !ruby/object:Gem::Dependency
84
- name: rack
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '1'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '1'
97
- - !ruby/object:Gem::Dependency
98
- name: puma
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '3.11'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '3.11'
111
- - !ruby/object:Gem::Dependency
112
- name: rake-compiler
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
10
+ date: 2025-02-27 00:00:00.000000000 Z
11
+ dependencies: []
125
12
  description: Ruby HTTP client library based on libcurl
126
13
  email:
127
- - phil.toland@gmail.com
14
+ - aeryn.toland@gmail.com
128
15
  executables: []
129
16
  extensions:
130
17
  - ext/patron/extconf.rb
131
18
  extra_rdoc_files: []
132
19
  files:
133
20
  - ".autotest"
21
+ - ".github/workflows/ci.yml"
134
22
  - ".gitignore"
135
23
  - ".rspec"
136
24
  - ".travis.yml"
@@ -176,16 +64,18 @@ files:
176
64
  - spec/support/certs/cacert.pem
177
65
  - spec/support/certs/privkey.pem
178
66
  - spec/support/config.ru
67
+ - spec/support/fork.rb
179
68
  - spec/support/test_server.rb
180
69
  - spec/util_spec.rb
181
70
  homepage: https://github.com/toland/patron
182
- licenses: []
71
+ licenses:
72
+ - MIT
183
73
  metadata:
184
74
  allowed_push_host: https://rubygems.org
185
75
  post_install_message: |2
186
76
 
187
77
  Thank you for installing Patron. On OSX, make sure you are using libCURL with OpenSSL.
188
- SecureTransport-based builds might cause crashes in forking environment.
78
+ SecureTransport-based builds might cause crashes in forking environments.
189
79
 
190
80
  For more info see https://github.com/curl/curl/issues/788
191
81
  rdoc_options: []
@@ -203,9 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
203
93
  - !ruby/object:Gem::Version
204
94
  version: 1.2.0
205
95
  requirements: []
206
- rubyforge_project: patron
207
- rubygems_version: 2.7.6
208
- signing_key:
96
+ rubygems_version: 3.6.2
209
97
  specification_version: 4
210
98
  summary: Patron HTTP Client
211
99
  test_files: []