patron 0.13.1 → 0.13.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cdaf7a10ef1cf673746f7f87ae77a9d939b461fc
4
- data.tar.gz: 772139466802595a3906e24f297da437de3df880
2
+ SHA256:
3
+ metadata.gz: e766e45bfa71015943701e1340503df7f915d499cd001475649613175df4006d
4
+ data.tar.gz: 8b3a7d7fcb6d555dfff1705685c8685b925c900dfec95200816580028ffa9d53
5
5
  SHA512:
6
- metadata.gz: 94787a3fd98f9253862432e8069c5088dfc703f3bb6e69ebb2e60f86d70a489a8cb2c72d2134e690649d0e908ff08068631e0cc148f41b331fca5cf4f95dc6cb
7
- data.tar.gz: 19496dff4f0687cbcd664c3aa81969c5b1a810aba28f87ab9f918a05771a5567d348acdc8b862c2b430e9304854796e034fc9d68361aa2d5b16e2cd0b17bd63b
6
+ metadata.gz: 986e1bb343ea53368a6acb8f7d7ef84a48674408d4a08f7eabe1d2e2c6ff5c90f2afe0683d1e66ab751c72241a25c9f46c8e16c955c97b87c71a0bc2bd7db723
7
+ data.tar.gz: c285b097c1fc4022fce3484184ac44d471340a496bc246142233e655bfdf0a28653484490ce5b1802fac4d5b396bea8ca03cfd1c803867f7c07ff3d8a789335c
@@ -8,7 +8,3 @@ rvm:
8
8
  sudo: false
9
9
  dist: trusty
10
10
  cache: bundler
11
- install:
12
- - gem update --system 2.6.12 # https://github.com/rubygems/rubygems/issues/2024
13
- - gem install bundler
14
- - "bundle install --verbose --jobs=3 --retry=3 --path=${BUNDLE_PATH:-vendor/bundle}"
@@ -1,4 +1,13 @@
1
- ### 0.13.0
1
+ ### 0.13.3
2
+
3
+ * Fix a number of specs that were failing due to use of threads
4
+
5
+ ### 0.13.2
6
+
7
+ * Eagerly initialize libCURL handle when creating the Session instance instead of initializing it lazily
8
+ * Remove special treatment of `Session#reset` and make it the same as `Session#interrupt`
9
+
10
+ ### 0.13.0, 0.13.1
2
11
 
3
12
  * Permit timeouts to be set as a Float of seconds and use `CURLOPT_(CONNECT)TIMEOUT_MS` instead of `CURLOPT_(CONNECT)TIMEOUT` so that
4
13
  sub-second timeouts can be configured, which is useful for performant services using accelerated DNS resolution.
data/README.md CHANGED
@@ -50,10 +50,55 @@ You can ship custom headers with a single request:
50
50
 
51
51
  sess.post("/foo/stuff", "some data", {"Content-Type" => "text/plain"})
52
52
 
53
- ## Known issues
53
+ ## Threading
54
+
55
+ By itself, the `Patron::Session` objects are not thread safe (each `Session` holds a single `curl_state` pointer
56
+ from initialization to garbage collection). At this time, Patron has no support for `curl_multi_*` family of functions
57
+ for doing concurrent requests. However, the actual code that interacts with libCURL does unlock the RVM GIL,
58
+ so using multiple `Session` objects in different threads actually enables a high degree of parallelism.
59
+ For sharing a resource of sessions between threads we recommend using the excellent [connection_pool](https://rubygems.org/gems/connection_pool) gem by Mike Perham.
60
+
61
+ patron_pool = ConnectionPool.new(size: 5, timeout: 5) { Patron::Session.new }
62
+ patron_pool.with do |session|
63
+ session.get(...)
64
+ end
65
+
66
+ Sharing Session objects between requests will also allow you to benefit from persistent connections (connection reuse), see below.
67
+
68
+ ## Persistent connections
69
+
70
+ Patron follows the libCURL guidelines on [connection reuse.](https://ec.haxx.se/libcurl-connectionreuse.html) If you create the Session
71
+ object once and use it for multiple requests, the same libCURL handle is going to be used across these requests and if requests go to
72
+ the same hostname/port/protocol the connection should get reused.
73
+
74
+ ## Performance with parallel requests
75
+
76
+ When performing the libCURL request, Patron goes out of it's way to unlock the GVL (global VM lock) to allow other threads to be scheduled
77
+ in parallel. The GVL is going to be released when the libCURL request starts, and will then be shortly re-acquired to provide the progress
78
+ callback - if the callback has been configured, and then released again until the libCURL request has been performed and the response has
79
+ been read in full. This allows one to execute multiple libCURL requests in parallel, as well as perform other activities on other MRI threads
80
+ that are currently active in the process.
81
+
82
+ ## Requirements
83
+
84
+ Patron uses encoding features of Ruby, so you need at least Ruby 1.9. Also, a
85
+ recent version of libCURL is required. We recommend at least 7.19.4 because
86
+ it [supports limiting the protocols](https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html),
87
+ and that is very important for security - especially if you follow redirects.
88
+
89
+ On OSX the provided libcurl is sufficient if you are not using fork+SSL combination (see below).
90
+ You will have to install the libcurl development packages on Debian or Ubuntu. Other Linux systems are probably
91
+ similar. For Windows we do not have an established build instruction at the moment, unfortunately.
92
+
93
+ Versions of Patron below 1.0 will maintain compatibility down to Ruby 1.9.3,
94
+ versions below 2.0 will maintain compatibility down to Ruby 2.3
95
+
96
+ ## Forking webservers on macOS and SSL
54
97
 
55
- Currently, [an issue is at play](https://github.com/curl/curl/issues/788) with OSX builds of `curl` which use Apple's SecureTransport. Such builds (which Patron is linking to), are causing segfaults when performing HTTPS requests in forked subprocesses. If you need to check whether your
56
- system is affected, run the Patron test suite by performing
98
+ Currently, [an issue is at play](https://github.com/curl/curl/issues/788) with OSX builds of `curl` which use
99
+ Apple's SecureTransport. Such builds (which Patron is linking to), are causing segfaults when performing HTTPS
100
+ requests in forked subprocesses. If you need to check whether your system is affected,
101
+ run the Patron test suite by performing
57
102
 
58
103
  $ bundle install && bundle exec rspec
59
104
 
@@ -69,37 +114,13 @@ When doing so, `curl` will use openssl as it's SSL driver. You also need to
69
114
  change the Patron compile flag:
70
115
 
71
116
 
72
- $ brew install curl --with-openssl && \
73
- gem install patron --with-curl-config=/usr/local/opt/curl/bin/curl-config
117
+ $ brew install curl-openssl && \
118
+ gem install patron -- --with-curl-config=/usr/local/opt/curl-openssl/bin/curl-config
74
119
 
75
120
  You can also save this parameter for all future Bundler-driven gem installs by
76
121
  setting this flag in Bundler proper:
77
122
 
78
- $ bundle config build.patron --with-curl-config=/usr/local/opt/curl/bin/curl-config
79
-
80
- ## Threading
81
-
82
- By itself, the `Patron::Session` objects are not thread safe (each `Session` holds a single `curl_state` pointer
83
- during the request/response cycle). At this time, Patron has no support for `curl_multi_*` family of functions
84
- for doing concurrent requests. However, the actual code that interacts with libCURL does unlock the RVM GIL,
85
- so using multiple `Session` objects in different threads is possible with a high degree of concurrency.
86
- For sharing a resource of sessions between threads we recommend using the excellent [connection_pool](https://rubygems.org/gems/connection_pool) gem by Mike Perham.
87
-
88
- patron_pool = ConnectionPool.new(size: 5, timeout: 5) { Patron::Session.new }
89
- patron_pool.with do |session|
90
- session.get(...)
91
- end
92
-
93
- ## Requirements
94
-
95
- Patron uses encoding features of Ruby, so you need at least Ruby 1.9. Also, a
96
- recent version of libCURL is required. We recommend at least 7.19.4 because
97
- it [supports limiting the protocols](https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html),
98
- and that is very important for security - especially if you follow redirects.
99
-
100
- On OSX the provided libcurl is sufficient. You will have to install the libcurl
101
- development packages on Debian or Ubuntu. Other Linux systems are probably
102
- similar. For Windows we do not have an established build instruction at the moment, unfortunately.
123
+ $ bundle config build.patron --with-curl-config=/usr/local/opt/curl-openssl/bin/curl-config
103
124
 
104
125
  ## Installation
105
126
 
@@ -163,6 +163,7 @@ static void cs_list_remove(struct patron_curl_state *state) {
163
163
  }
164
164
  }
165
165
 
166
+ /* Gets attached to at_exit of the Ruby process to be able to abort all running libCURL requests and quit */
166
167
  static void cs_list_interrupt(VALUE data) {
167
168
  UNUSED_ARGUMENT(data);
168
169
 
@@ -182,7 +183,7 @@ static void session_close_debug_file(struct patron_curl_state *curl) {
182
183
  curl->debug_file = NULL;
183
184
  }
184
185
 
185
- /* Cleans up the Curl handle when the Session object is garbage collected. */
186
+ /* Cleans up the patron_curl_state data when the Session object is garbage collected. */
186
187
  void session_free(struct patron_curl_state *curl) {
187
188
  if (curl->handle) {
188
189
  curl_easy_cleanup(curl->handle);
@@ -201,12 +202,29 @@ void session_free(struct patron_curl_state *curl) {
201
202
 
202
203
  /* Allocates patron_curl_state data needed for a new Session object. */
203
204
  VALUE session_alloc(VALUE klass) {
204
- struct patron_curl_state* curl;
205
- VALUE obj = Data_Make_Struct(klass, struct patron_curl_state, NULL, session_free, curl);
206
-
207
- membuffer_init( &curl->header_buffer );
208
- membuffer_init( &curl->body_buffer );
209
- cs_list_append(curl);
205
+ struct patron_curl_state* state;
206
+ VALUE obj = Data_Make_Struct(klass, struct patron_curl_state, NULL, session_free, state);
207
+
208
+ membuffer_init(&state->header_buffer);
209
+ membuffer_init(&state->body_buffer);
210
+ cs_list_append(state);
211
+
212
+ /*
213
+ Eagerly initialize the curl handle. We initialize it only once and store it
214
+ in the struct until the Session object gets garbage-collected in session_free(). This allows libCURL to
215
+ reuse the TCP connection and can speed things up if the same resource - like a backend service -
216
+ gets accessed over and over with requests.
217
+ */
218
+ state->handle = curl_easy_init();
219
+ curl_easy_setopt(state->handle, CURLOPT_NOSIGNAL, 1);
220
+ curl_easy_setopt(state->handle, CURLOPT_NOPROGRESS, 0);
221
+ #if LIBCURL_VERSION_NUM >= 0x072000
222
+ /* this is libCURLv7.32.0 or later, supports CURLOPT_XFERINFOFUNCTION */
223
+ curl_easy_setopt(state->handle, CURLOPT_XFERINFOFUNCTION, &session_progress_handler);
224
+ #else
225
+ curl_easy_setopt(state->handle, CURLOPT_PROGRESSFUNCTION, &session_progress_handler);
226
+ #endif
227
+ curl_easy_setopt(state->handle, CURLOPT_PROGRESSDATA, state);
210
228
 
211
229
  return obj;
212
230
  }
@@ -215,25 +233,9 @@ VALUE session_alloc(VALUE klass) {
215
233
  static struct patron_curl_state* get_patron_curl_state(VALUE self) {
216
234
  struct patron_curl_state* state;
217
235
  Data_Get_Struct(self, struct patron_curl_state, state);
218
-
219
- if (NULL == state->handle) {
220
- state->handle = curl_easy_init();
221
- curl_easy_setopt(state->handle, CURLOPT_NOSIGNAL, 1);
222
- curl_easy_setopt(state->handle, CURLOPT_NOPROGRESS, 0);
223
- #if LIBCURL_VERSION_NUM >= 0x072000
224
- /* this is libCURLv7.32.0 or later, supports CURLOPT_XFERINFOFUNCTION */
225
- curl_easy_setopt(state->handle, CURLOPT_XFERINFOFUNCTION, &session_progress_handler);
226
- #else
227
- curl_easy_setopt(state->handle, CURLOPT_PROGRESSFUNCTION, &session_progress_handler);
228
- #endif
229
-
230
- curl_easy_setopt(state->handle, CURLOPT_PROGRESSDATA, state);
231
- }
232
-
233
236
  return state;
234
237
  }
235
238
 
236
-
237
239
  /*----------------------------------------------------------------------------*/
238
240
  /* Method implementations */
239
241
 
@@ -887,33 +889,9 @@ static VALUE session_handle_request(VALUE self, VALUE request) {
887
889
  return rb_ensure(&perform_request, self, &cleanup, self);
888
890
  }
889
891
 
890
- /*
891
- * FIXME: figure out how this method should be used at all given Session is not multithreaded.
892
- * FIXME: also: what is the difference with `interrupt()` and also relationship with `cleanup()`?
893
- * Reset the underlying cURL session. This effectively closes all open
894
- * connections and disables debug output. There is no need to call this method
895
- * manually after performing a request, since cleanup is performed automatically
896
- * but the method can be used from another thread
897
- * to abort a request currently in progress.
898
- *
899
- * @return self
900
- */
901
- static VALUE session_reset(VALUE self) {
902
- struct patron_curl_state *state;
903
- Data_Get_Struct(self, struct patron_curl_state, state);
904
-
905
- if (NULL != state->handle) {
906
- cleanup(self);
907
- curl_easy_cleanup(state->handle);
908
- state->handle = NULL;
909
- session_close_debug_file(state);
910
- }
911
-
912
- return self;
913
- }
914
-
915
892
  /* Interrupt any currently executing request. This will cause the current
916
- * request to error and raise an exception.
893
+ * request to error and raise an exception. The method can be called from another thread to
894
+ * abort the request in-flight.
917
895
  *
918
896
  * @return [void] This method always raises
919
897
  */
@@ -1009,7 +987,7 @@ void Init_session_ext() {
1009
987
  rb_define_method(cSession, "unescape", session_unescape, 1);
1010
988
 
1011
989
  rb_define_method(cSession, "handle_request", session_handle_request, 1);
1012
- rb_define_method(cSession, "reset", session_reset, 0);
990
+ rb_define_method(cSession, "reset", session_interrupt, 0);
1013
991
  rb_define_method(cSession, "interrupt", session_interrupt, 0);
1014
992
  rb_define_method(cSession, "add_cookie_file", add_cookie_file, 1);
1015
993
  rb_define_method(cSession, "set_debug_file", set_debug_file, 1);
@@ -1,3 +1,3 @@
1
1
  module Patron
2
- VERSION = "0.13.1"
2
+ VERSION = "0.13.3"
3
3
  end
@@ -36,7 +36,7 @@ SecureTransport-based builds might cause crashes in forking environment.
36
36
  For more info see https://github.com/curl/curl/issues/788
37
37
  }
38
38
  spec.add_development_dependency "rake", "~> 10"
39
- spec.add_development_dependency "bundler", ">= 1"
39
+ spec.add_development_dependency "bundler"
40
40
  spec.add_development_dependency "rspec", ">= 2.3.0"
41
41
  spec.add_development_dependency "simplecov", "~> 0.10"
42
42
  spec.add_development_dependency "yard", "~> 0.9.11"
@@ -10,7 +10,7 @@ describe Patron do
10
10
 
11
11
  it "should return the version number of the Patron library" do
12
12
  version = Patron.version
13
- expect(version).to match(%r|^\d+.\d+.\d+$|)
13
+ expect(version).to match(%r|^\d+.\d+.\d+(\.\w+\.\d+)?$|)
14
14
  end
15
15
 
16
16
  it "should return the version string of the libcurl library" do
@@ -16,9 +16,9 @@ describe Patron::Session do
16
16
  forbidden_protos = %w( smb tftp imap smtp telnet dict ftp sftp scp file gopher )
17
17
  forbidden_protos.each do |forbidden_proto|
18
18
  it "should deny a #{forbidden_proto.upcase} request" do
19
- @session.base_url = nil
20
19
  expect {
21
- @session.get('%s://localhost' % forbidden_proto)
20
+ @session.base_url = '%s://localhost' % forbidden_proto
21
+ @session.get('')
22
22
  }.to raise_error(Patron::UnsupportedProtocol)
23
23
  end
24
24
  end
@@ -208,9 +208,9 @@ describe Patron::Session do
208
208
  end
209
209
 
210
210
  it "is able to terminate the thread that is running a slow request" do
211
- t = Thread.new do
211
+ pid = Process.fork do
212
212
  trap('SIGINT') do
213
- exit # exit the thread
213
+ exit # exit the process
214
214
  end
215
215
  session = Patron::Session.new
216
216
  session.timeout = 40
@@ -222,8 +222,8 @@ describe Patron::Session do
222
222
  # using a signal during that time.
223
223
  started = Time.now.to_i
224
224
  sleep 5 # Less than what it takes for the server to respond
225
- Process.kill("INT", Process.pid) # Signal ourselves...
226
- t.join # wrap up the thread. If Patron is still busy there, this join call will still take 15s.
225
+ Process.kill("INT", pid) # Signal ourselves...
226
+ Process.wait(pid) # wrap up the process. If Patron is still busy there, this call will still take 15s.
227
227
  delta_s = Time.now.to_i - started
228
228
  expect(delta_s).to be_within(2).of(5)
229
229
  end
@@ -458,14 +458,14 @@ describe Patron::Session do
458
458
  it "should ignore a wrong Content-Length when asked to" do
459
459
  expect {
460
460
  @session.ignore_content_length = true
461
- @session.get("/wrongcontentlength")
461
+ @session.get("/wrongcontentlength", { 'Connection' => 'close' })
462
462
  }.to_not raise_error
463
463
  end
464
464
 
465
465
  it "should fail by default with a Content-Length too high" do
466
466
  expect {
467
467
  @session.ignore_content_length = nil
468
- @session.get("/wrongcontentlength")
468
+ @session.get("/wrongcontentlength", { 'Connection' => 'close' })
469
469
  }.to raise_error(Patron::PartialFileError)
470
470
  end
471
471
 
@@ -517,14 +517,12 @@ describe Patron::Session do
517
517
  it "should serialize query params and append them to the url" do
518
518
  response = @session.request(:get, "/test", {}, :query => {:foo => "bar"})
519
519
  request = YAML::load(response.body)
520
- request.parse
521
520
  expect(request.path + '?' + request.query_string).to be == "/test?foo=bar"
522
521
  end
523
522
 
524
523
  it "should merge parameters in the :query option with pre-existing query parameters" do
525
524
  response = @session.request(:get, "/test?foo=bar", {}, :query => {:baz => "quux"})
526
525
  request = YAML::load(response.body)
527
- request.parse
528
526
  expect(request.path + '?' + request.query_string).to be == "/test?foo=bar&baz=quux"
529
527
  end
530
528
 
@@ -32,12 +32,11 @@ describe Patron::Session do
32
32
  it "should download content in a forked subprocess" do
33
33
  # To trigger the bug, we need to perform a request in the master process first
34
34
  tmpfile = "/tmp/patron_test.yaml"
35
- @session.get_file "/test2", tmpfile
36
- File.unlink(tmpfile)
35
+ @session.get_file "/test", tmpfile
36
+ FileUtils.rm tmpfile
37
37
 
38
38
  # and this one segfaults
39
39
  pid = fork do
40
- tmpfile = "/tmp/patron_test.yaml"
41
40
  response = @session.get_file "/test", tmpfile
42
41
  expect(response.body).to be_nil
43
42
  body = YAML::load_file(tmpfile)
@@ -214,20 +213,6 @@ describe Patron::Session do
214
213
  expect(YAML::load(response).header).to_not include('cookie')
215
214
  end
216
215
 
217
- it "should ignore a wrong Content-Length when asked to" do
218
- expect {
219
- @session.ignore_content_length = true
220
- @session.get("/wrongcontentlength")
221
- }.to_not raise_error
222
- end
223
-
224
- it "should fail by default with a Content-Length too high" do
225
- expect {
226
- @session.ignore_content_length = nil
227
- @session.get("/wrongcontentlength")
228
- }.to raise_error(Patron::PartialFileError)
229
- end
230
-
231
216
  it "should raise exception if cookie store is not writable or readable" do
232
217
  expect { @session.handle_cookies("/trash/clash/foo") }.to raise_error(ArgumentError)
233
218
  end
@@ -254,14 +239,14 @@ describe Patron::Session do
254
239
 
255
240
  it "should work when insecure mode is off but certificate is supplied" do
256
241
  @session.insecure = nil
257
- @session.cacert = 'spec/certs/cacert.pem'
242
+ @session.cacert = File.join(__dir__, 'support', 'certs', 'cacert.pem')
258
243
  response = @session.get("/test")
259
244
  body = YAML::load(response.body)
260
245
  expect(body.request_method).to be == "GET"
261
246
  end
262
247
 
263
248
  it "should work with different SSL versions" do
264
- ['SSLv3','TLSv1'].each do |version|
249
+ ['TLSv1_0','TLSv1_1'].each do |version|
265
250
  @session.ssl_version = version
266
251
  response = @session.get("/test")
267
252
  expect(response.status).to be == 200
@@ -18,5 +18,14 @@ $stderr.puts "Build against #{Patron.libcurl_version}"
18
18
 
19
19
  Dir['./spec/support/**/*.rb'].each { |fn| require fn }
20
20
 
21
- Thread.new { PatronTestServer.start(false, 9001) }
22
- Thread.new { PatronTestServer.start(true, 9043) }
21
+ http_server_pid = Process.fork { PatronTestServer.start(false, 9001) }
22
+ https_server_pid = Process.fork { PatronTestServer.start(true, 9043) }
23
+
24
+ RSpec.configure do |c|
25
+ 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)
30
+ end
31
+ end
File without changes
@@ -1,5 +1,6 @@
1
1
  require 'yaml'
2
2
  require 'ostruct'
3
+ require 'zlib'
3
4
 
4
5
  ## HTTP test server for integration tests
5
6
 
@@ -25,7 +26,9 @@ Readback = Proc.new {|env|
25
26
  end
26
27
 
27
28
  fake_webrick_request_object = OpenStruct.new({
28
- :path => req.fullpath,
29
+ :fullpath => req.fullpath,
30
+ :path => req.path,
31
+ :query_string => req.query_string,
29
32
  :request_method => req.request_method.to_s,
30
33
  :header => Hash[req_headers],
31
34
  :body => env['rack.input'].read,
@@ -38,16 +41,20 @@ Readback = Proc.new {|env|
38
41
  GzipServlet = Proc.new {|env|
39
42
  raise "Need to have the right Accept-Encoding: header" unless env['HTTP_ACCEPT_ENCODING']
40
43
 
41
- body = Enumerator.new do |y|
42
- z = Zlib::Deflate.new(Zlib::DEFAULT_COMPRESSION)
43
- 1024.times {
44
- y.yield(z.deflate('Some highly compressible data'))
45
- }
46
- y.yield(z.finish.to_s)
47
- y.yield(z.close.to_s)
44
+ body = []
45
+ content_length = 0
46
+ z = Zlib::Deflate.new(Zlib::DEFAULT_COMPRESSION)
47
+ 1024.times do
48
+ chunk = z.deflate('Some highly compressible data')
49
+ content_length += chunk.bytesize
50
+ body << chunk
48
51
  end
52
+ fin = z.finish.to_s
53
+ body << fin
54
+ content_length += fin.bytesize
55
+ z.close
49
56
 
50
- [200, {'Content-Encoding' => 'deflate', 'Vary' => 'Accept-Encoding'}, body]
57
+ [200, {'Content-Encoding' => 'deflate', 'Content-Length' => content_length.to_s, 'Vary' => 'Accept-Encoding'}, body]
51
58
  }
52
59
 
53
60
  TimeoutServlet = Proc.new {|env|
@@ -67,8 +74,9 @@ SlowServlet = Proc.new {|env|
67
74
  }
68
75
 
69
76
  RedirectServlet = Proc.new {|env|
77
+ url_scheme = env.fetch('rack.url_scheme')
70
78
  port = env.fetch('SERVER_PORT')
71
- [301, {'Location' => "http://localhost:#{port}/test"}, []]
79
+ [301, {'Location' => "#{url_scheme}://localhost:#{port}/test"}, []]
72
80
  }
73
81
 
74
82
  EvilRedirectServlet = Proc.new {|env|
@@ -76,8 +84,8 @@ EvilRedirectServlet = Proc.new {|env|
76
84
  }
77
85
 
78
86
  BodyReadback = Proc.new {|env|
79
- readback = {'method' => env['REQUEST_METHOD'], 'body' => env['rack.input'].read, 'content_type' => env.fetch('HTTP_CONTENT_TYPE')}
80
- [200, {'Content-Type' => 'text/plain'}, [readback]]
87
+ readback = {'method' => env['REQUEST_METHOD'], 'body' => env['rack.input'].read, 'content_type' => env.fetch('CONTENT_TYPE')}
88
+ [200, {'Content-Type' => 'text/plain'}, [OpenStruct.new(readback).to_yaml]]
81
89
  }
82
90
 
83
91
  TestPatchBodyServlet = BodyReadback
@@ -3,18 +3,24 @@ require 'puma'
3
3
  require 'rack/handler/puma'
4
4
 
5
5
  class PatronTestServer
6
- APP = Rack::Builder.new { eval(File.read(File.dirname(__FILE__) + '/config.ru')) }
6
+ APP = Rack::Builder.new { eval(File.read(File.join(__dir__, 'config.ru'))) }
7
7
 
8
8
  def self.start(ssl = false, port = 9001 )
9
+ # Reset the RSpec's SIGINT handler that does not really terminate after
10
+ # the first Ctrl+C pressed.
11
+ # Useful to terminate the forked process before Puma is actually started:
12
+ # it happens when running one particular example that does not need Puma
13
+ # so the specs are in fact finished before the Puma started.
14
+ Signal.trap('INT', 'EXIT')
9
15
  @ssl = ssl
10
- keypath = File.expand_path(File.read(File.dirname(__FILE__) + '/../certs/privkey.pem'))
11
- certpath = File.expand_path(File.read(File.dirname(__FILE__) + '/../certs/cacert.pem'))
16
+ keypath = File.join(__dir__, 'certs', 'privkey.pem')
17
+ certpath = File.join(__dir__, 'certs', 'cacert.pem')
12
18
 
13
19
  host = if ssl
14
- 'ssl://127.0.0.1:%d?key=%s&cert=%s' % [port, keypath, certpath]
20
+ 'ssl://0.0.0.0:%d?key=%s&cert=%s' % [port, keypath, certpath]
15
21
  else
16
- 'tcp://127.0.0.1:%d' % port
22
+ '0.0.0.0'
17
23
  end
18
- Rack::Handler::Puma.run(APP, {:Port => port.to_i, :Verbose => true, :Host => '0.0.0.0'})
24
+ Rack::Handler::Puma.run(APP, {:Port => port.to_i, :Verbose => true, :Host => host})
19
25
  end
20
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: patron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.1
4
+ version: 0.13.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phillip Toland
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-04-10 00:00:00.000000000 Z
11
+ date: 2019-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -160,8 +160,6 @@ files:
160
160
  - pic.png
161
161
  - script/console
162
162
  - script/test_server
163
- - spec/certs/cacert.pem
164
- - spec/certs/privkey.pem
165
163
  - spec/header_parser_spec.rb
166
164
  - spec/patron_spec.rb
167
165
  - spec/request_spec.rb
@@ -175,6 +173,8 @@ files:
175
173
  - spec/session_spec.rb
176
174
  - spec/session_ssl_spec.rb
177
175
  - spec/spec_helper.rb
176
+ - spec/support/certs/cacert.pem
177
+ - spec/support/certs/privkey.pem
178
178
  - spec/support/config.ru
179
179
  - spec/support/test_server.rb
180
180
  - spec/util_spec.rb
@@ -204,7 +204,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
204
204
  version: 1.2.0
205
205
  requirements: []
206
206
  rubyforge_project: patron
207
- rubygems_version: 2.5.2
207
+ rubygems_version: 2.7.6
208
208
  signing_key:
209
209
  specification_version: 4
210
210
  summary: Patron HTTP Client