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 +5 -5
- data/.travis.yml +0 -4
- data/CHANGELOG.md +10 -1
- data/README.md +51 -30
- data/ext/patron/session_ext.c +28 -50
- data/lib/patron/version.rb +1 -1
- data/patron.gemspec +1 -1
- data/spec/patron_spec.rb +1 -1
- data/spec/session_spec.rb +8 -10
- data/spec/session_ssl_spec.rb +4 -19
- data/spec/spec_helper.rb +11 -2
- data/spec/{certs → support/certs}/cacert.pem +0 -0
- data/spec/{certs → support/certs}/privkey.pem +0 -0
- data/spec/support/config.ru +20 -12
- data/spec/support/test_server.rb +12 -6
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e766e45bfa71015943701e1340503df7f915d499cd001475649613175df4006d
|
4
|
+
data.tar.gz: 8b3a7d7fcb6d555dfff1705685c8685b925c900dfec95200816580028ffa9d53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 986e1bb343ea53368a6acb8f7d7ef84a48674408d4a08f7eabe1d2e2c6ff5c90f2afe0683d1e66ab751c72241a25c9f46c8e16c955c97b87c71a0bc2bd7db723
|
7
|
+
data.tar.gz: c285b097c1fc4022fce3484184ac44d471340a496bc246142233e655bfdf0a28653484490ce5b1802fac4d5b396bea8ca03cfd1c803867f7c07ff3d8a789335c
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
### 0.13.
|
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
|
-
##
|
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
|
56
|
-
|
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
|
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
|
|
data/ext/patron/session_ext.c
CHANGED
@@ -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
|
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*
|
205
|
-
VALUE obj = Data_Make_Struct(klass, struct patron_curl_state, NULL, session_free,
|
206
|
-
|
207
|
-
membuffer_init(
|
208
|
-
membuffer_init(
|
209
|
-
cs_list_append(
|
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",
|
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);
|
data/lib/patron/version.rb
CHANGED
data/patron.gemspec
CHANGED
@@ -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"
|
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"
|
data/spec/patron_spec.rb
CHANGED
@@ -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
|
data/spec/session_spec.rb
CHANGED
@@ -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.
|
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
|
-
|
211
|
+
pid = Process.fork do
|
212
212
|
trap('SIGINT') do
|
213
|
-
exit # exit the
|
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",
|
226
|
-
|
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
|
|
data/spec/session_ssl_spec.rb
CHANGED
@@ -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 "/
|
36
|
-
|
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 = '
|
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
|
-
['
|
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
|
data/spec/spec_helper.rb
CHANGED
@@ -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
|
-
|
22
|
-
|
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
|
File without changes
|
data/spec/support/config.ru
CHANGED
@@ -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
|
-
:
|
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 =
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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' => "
|
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('
|
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
|
data/spec/support/test_server.rb
CHANGED
@@ -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.
|
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.
|
11
|
-
certpath = File.
|
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://
|
20
|
+
'ssl://0.0.0.0:%d?key=%s&cert=%s' % [port, keypath, certpath]
|
15
21
|
else
|
16
|
-
'
|
22
|
+
'0.0.0.0'
|
17
23
|
end
|
18
|
-
Rack::Handler::Puma.run(APP, {:Port => port.to_i, :Verbose => true, :Host =>
|
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.
|
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:
|
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: '
|
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: '
|
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.
|
207
|
+
rubygems_version: 2.7.6
|
208
208
|
signing_key:
|
209
209
|
specification_version: 4
|
210
210
|
summary: Patron HTTP Client
|