patron 0.13.3 → 0.14.0

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
2
  SHA256:
3
- metadata.gz: e766e45bfa71015943701e1340503df7f915d499cd001475649613175df4006d
4
- data.tar.gz: 8b3a7d7fcb6d555dfff1705685c8685b925c900dfec95200816580028ffa9d53
3
+ metadata.gz: 355b38921e6368ee1ad7815cd78ad9135630b10c82d60365978747e4189be390
4
+ data.tar.gz: efbebf2f2e6393e93411d5583c9062b3170e0bf4e30ae370d1e998110b19c3c3
5
5
  SHA512:
6
- metadata.gz: 986e1bb343ea53368a6acb8f7d7ef84a48674408d4a08f7eabe1d2e2c6ff5c90f2afe0683d1e66ab751c72241a25c9f46c8e16c955c97b87c71a0bc2bd7db723
7
- data.tar.gz: c285b097c1fc4022fce3484184ac44d471340a496bc246142233e655bfdf0a28653484490ce5b1802fac4d5b396bea8ca03cfd1c803867f7c07ff3d8a789335c
6
+ metadata.gz: 760418bb81862c742f9873caa2513a6ed60093a084145b77e9f21996f041b0e848a0a6914e0248c0dca806bc5313c59eed68afd2546c828218a2e0aa52734ecf
7
+ data.tar.gz: 77510952d581ea162ef55e93260fc8188e58b5f919dd97912c6d7b40863c94e2c517027c6de5fe2b5041431fb9645c85ad674b08f37ce7e2fcdb37b4f16f2da2
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -0,0 +1,79 @@
1
+ name: Tests
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-24.04
8
+ continue-on-error: ${{ matrix.allow-failure || false }}
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby-version: ["2.4", "3.0", "3.4.1", "4.0.5"]
13
+ include:
14
+ - ruby-version: "head"
15
+ allow-failure: true
16
+
17
+ name: Specs - Ruby ${{ matrix.ruby-version }}
18
+ steps:
19
+ - uses: actions/checkout@v7
20
+ - name: Install libcurl
21
+ run: |
22
+ sudo apt-get update
23
+ sudo apt-get -y install libcurl4 libcurl4-openssl-dev
24
+ - name: Set up Ruby ${{ matrix.ruby-version }}
25
+ uses: ruby/setup-ruby@v1
26
+ with:
27
+ ruby-version: ${{ matrix.ruby-version }}
28
+ bundler-cache: true # 'bundle install' and cache
29
+ - name: Run tests
30
+ run: bundle exec rake
31
+
32
+ valgrind:
33
+ runs-on: ubuntu-latest
34
+ name: Specs under valgrind memcheck
35
+ steps:
36
+ - uses: actions/checkout@v7
37
+ - name: Install libcurl and valgrind
38
+ run: |
39
+ sudo apt-get update
40
+ sudo apt-get -y install libcurl4-openssl-dev valgrind
41
+ - name: Set up Ruby
42
+ uses: ruby/setup-ruby@v1
43
+ with:
44
+ ruby-version: "3.4"
45
+ bundler-cache: true
46
+ - name: Compile the extension with debug info
47
+ run: bundle exec rake clobber compile
48
+ env:
49
+ PATRON_EXTRA_CFLAGS: "-g -O1"
50
+ - name: Run the specs under memcheck
51
+ # The ruby process itself is under valgrind (bundle exec only sets up the environment).
52
+ # Specs tagged :timing assert on wall-clock windows that valgrind's slowdown breaks.
53
+ run: |
54
+ bundle exec valgrind --error-exitcode=99 --leak-check=no --undef-value-errors=no \
55
+ --child-silent-after-fork=yes --num-callers=30 \
56
+ --suppressions=spec/support/valgrind.supp \
57
+ ruby -S rspec --tag ~timing
58
+
59
+ malloc-check:
60
+ runs-on: ubuntu-latest
61
+ name: Specs with glibc malloc checking
62
+ steps:
63
+ - uses: actions/checkout@v7
64
+ - name: Install libcurl
65
+ run: |
66
+ sudo apt-get update
67
+ sudo apt-get -y install libcurl4-openssl-dev
68
+ - name: Set up Ruby
69
+ uses: ruby/setup-ruby@v1
70
+ with:
71
+ ruby-version: "3.4"
72
+ bundler-cache: true
73
+ - name: Run tests
74
+ # glibc aborts on heap corruption and fills freed memory with 0xA5, so a use-after-free
75
+ # shows up as garbage data rather than passing by luck
76
+ run: bundle exec rake
77
+ env:
78
+ MALLOC_CHECK_: "3"
79
+ MALLOC_PERTURB_: "165"
data/.travis.yml CHANGED
@@ -1,10 +1,13 @@
1
1
  rvm:
2
- - 1.9.3
3
- - 2.1.5
4
- - 2.2.2
5
- - 2.3.4
6
- - 2.4.1
7
- - 2.5.0
8
- sudo: false
2
+ - 2.3.8
3
+ - 2.4.5
4
+ - 2.5.3
5
+ - 2.6.1
6
+ - ruby-head
7
+
9
8
  dist: trusty
10
9
  cache: bundler
10
+
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: ruby-head
data/CHANGELOG.md CHANGED
@@ -1,6 +1,37 @@
1
+ ### Unreleased
2
+
3
+ ### 0.14.0
4
+
5
+ * Expose libcurl's transfer timings (name lookup, connect, TLS, first byte, total) as `Response#timings`
6
+ * Add `ssl_cert`, `ssl_cert_type`, `ssl_key` and `ssl_key_password` for presenting a client certificate (mutual TLS). Thanks @lenage for the original contribution in #165
7
+ * Raise `Patron::ClientCertificateError` when the client certificate or its key can't be used
8
+ * Accept a `Pathname` for `cacert`
9
+ * Fix a request whose options fail to apply (for example an option of the wrong type) leaking its headers and open files into the next request on the same `Session`
10
+ * Fix the request body being read from freed memory when `upload_data` is not a String (its `#to_s` result was not kept alive during the transfer)
11
+ * Fix multipart field names and values pointing at temporary Strings, and binary multipart values being cut at the first NUL byte
12
+ * Fix an exception raised inside `progress_callback` (including `Timeout.timeout` and `Thread#raise`) unwinding through libcurl; it is now re-raised after the transfer is aborted
13
+ * Raise `Patron::Error` when a second thread uses a `Session` that is already performing a request, instead of corrupting both requests
14
+ * Fix the progress callback being declared with `size_t` arguments where libcurl passes `curl_off_t`
15
+ * Accept `download_byte_limit` above 2 GiB, and Floats for `dns_cache_timeout`, `low_speed_time` and `low_speed_limit`
16
+ * Fix `Session#unescape` cutting the result at a `%00`, and raise instead of crashing when libcurl fails to escape or unescape
17
+ * Reject file paths containing NUL bytes for cookie files, debug output and uploads
18
+ * Raise `NoMemoryError` instead of crashing later when libcurl cannot allocate a Session's handles
19
+ * Register the exception classes the extension looks up at load time with the GC, so heap compaction (`GC.compact`, `GC.auto_compact`) cannot move them out from under `rb_raise`
20
+
21
+ ### 0.13.4
22
+
23
+ * Format README a bit better using code fences
24
+ * Depend explicitly on base64 for running tests
25
+ * Remove C code used for Ruby support below < 2.4 (GVL unlock etc.) and drop support for these versions
26
+ * In tests, close Tempfiles before allowing libcurl to use them (cookie jar)
27
+ * Fix incorrect ptr type in uses of `curl_easy_escape` / `_unescape`
28
+ * Define methods on `Session` as private instance methods from C instead of privatising them from Ruby
29
+ * Speed up the /slow endpoint test
30
+ * Remove use of `curl_easy_reset`. This should fix the bug with sessions resetting each other's state during `session_free`
31
+
1
32
  ### 0.13.3
2
33
 
3
- * Fix a number of specs that were failing due to use of threads
34
+ * Run Puma test servers in separate processes instead of threads
4
35
 
5
36
  ### 0.13.2
6
37
 
data/Gemfile CHANGED
@@ -1,4 +1,18 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in patron.gemspec
3
+ # Runtime dependencies are in the gemspec
4
4
  gemspec
5
+
6
+ # Gems below are only needed for Patron development
7
+ # and tests
8
+ gem "rake", ">= 12.3.3"
9
+ gem "rspec", ">= 2.3.0"
10
+ gem "simplecov", "~> 0.10"
11
+ gem "yard", "~> 0.9.20"
12
+ rack_version = RUBY_VERSION >= "3.3" ? "~> 2.2" : "~> 2.1.4"
13
+ gem "rack", rack_version
14
+ gem "puma", '~> 5.6'
15
+ gem "rake-compiler"
16
+ gem "webrick", "~> 1.8"
17
+ gem "base64"
18
+ gem "ostruct"
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ # Patron
2
+
3
+ [![Tests](https://github.com/toland/patron/actions/workflows/ci.yml/badge.svg)](https://github.com/toland/patron/actions/workflows/ci.yml)
4
+
1
5
  Patron is a Ruby HTTP client library based on libcurl. It does not try to expose
2
6
  the full "power" (read complexity) of libcurl but instead tries to provide a
3
7
  sane API while taking advantage of libcurl under the hood.
@@ -8,47 +12,92 @@ First, you instantiate a Session object. You can set a few
8
12
  default options on the Session instance that will be used by all subsequent
9
13
  requests:
10
14
 
11
- sess = Patron::Session.new
12
- sess.timeout = 10
13
- sess.base_url = "http://myserver.com:9900"
14
- sess.headers['User-Agent'] = 'myapp/1.0'
15
+ ```ruby
16
+ sess = Patron::Session.new
17
+ sess.timeout = 10
18
+ sess.base_url = "http://myserver.com:9900"
19
+ sess.headers['User-Agent'] = 'myapp/1.0'
20
+ ```
15
21
 
16
22
  You can set options with a hash in the constructor:
17
23
 
18
- sess = Patron::Session.new({ :timeout => 10,
19
- :base_url => 'http://myserver.com:9900',
20
- :headers => {'User-Agent' => 'myapp/1.0'} } )
24
+ ```ruby
25
+ sess = Patron::Session.new({ :timeout => 10,
26
+ :base_url => 'http://myserver.com:9900',
27
+ :headers => {'User-Agent' => 'myapp/1.0'} } )
28
+ ```
21
29
 
22
30
  Or the set options in a block:
23
31
 
24
- sess = Patron::Session.new do |patron|
25
- patron.timeout = 10
26
- patron.base_url = 'http://myserver.com:9900'
27
- patron.headers = {'User-Agent' => 'myapp/1.0'}
28
- end
32
+ ```ruby
33
+ sess = Patron::Session.new do |patron|
34
+ patron.timeout = 10
35
+ patron.base_url = 'http://myserver.com:9900'
36
+ patron.headers = {'User-Agent' => 'myapp/1.0'}
37
+ end
38
+ ```
29
39
 
30
40
  Output debug log:
31
41
 
32
- sess.enable_debug "/tmp/patron.debug"
42
+ ```ruby
43
+ sess.enable_debug "/tmp/patron.debug"
44
+ ```
33
45
 
34
46
  The Session is used to make HTTP requests.
35
47
 
36
- resp = sess.get("/foo/bar")
48
+ ```ruby
49
+ resp = sess.get("/foo/bar")
50
+ ```
37
51
 
38
52
  Requests return a Response object:
39
53
 
40
- if resp.status < 400
41
- puts resp.body
42
- end
54
+ ```ruby
55
+ if resp.status < 400
56
+ puts resp.body
57
+ end
58
+ ```
43
59
 
44
60
  The GET, HEAD, PUT, POST and DELETE operations are all supported.
45
61
 
46
- sess.put("/foo/baz", "some data")
47
- sess.delete("/foo/baz")
62
+ ```ruby
63
+ sess.put("/foo/baz", "some data")
64
+ sess.delete("/foo/baz")
65
+ ```
48
66
 
49
67
  You can ship custom headers with a single request:
50
68
 
51
- sess.post("/foo/stuff", "some data", {"Content-Type" => "text/plain"})
69
+ ```ruby
70
+ sess.post("/foo/stuff", "some data", {"Content-Type" => "text/plain"})
71
+ ```
72
+
73
+ libcurl's transfer timings are available on the response, in seconds since the request started:
74
+
75
+ ```ruby
76
+ resp = sess.get("/foo/bar")
77
+ resp.timings # => {namelookup: 0.001, connect: 0.012, appconnect: 0.045, pretransfer: 0.045,
78
+ # starttransfer: 0.210, redirect: 0.0, total: 0.214}
79
+ ```
80
+
81
+ To authenticate with a client certificate (mutual TLS), point Patron at a PKCS#12 bundle:
82
+
83
+ ```ruby
84
+ sess.ssl_cert = "/path/to/client.p12"
85
+ sess.ssl_cert_type = "P12"
86
+ sess.ssl_key_password = "secret"
87
+ ```
88
+
89
+ or at a PEM certificate with a separate private key:
90
+
91
+ ```ruby
92
+ sess.ssl_cert = "/path/to/client.pem"
93
+ sess.ssl_key = "/path/to/client_key.pem"
94
+ sess.ssl_key_password = "secret" # if the key is encrypted
95
+ ```
96
+
97
+ If the certificate or key can't be loaded (wrong password, missing file) the request raises `Patron::ClientCertificateError`.
98
+ This depends on the TLS library libcurl is built against: with GnuTLS these surface as a plain `Patron::Error`.
99
+ Client certificates are tested with the OpenSSL and LibreSSL backends - libcurl's Secure Transport backend
100
+ can't load a PEM certificate from a file at all.
52
101
 
53
102
  ## Threading
54
103
 
@@ -58,16 +107,18 @@ for doing concurrent requests. However, the actual code that interacts with libC
58
107
  so using multiple `Session` objects in different threads actually enables a high degree of parallelism.
59
108
  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
109
 
61
- patron_pool = ConnectionPool.new(size: 5, timeout: 5) { Patron::Session.new }
62
- patron_pool.with do |session|
63
- session.get(...)
64
- end
110
+ ```ruby
111
+ patron_pool = ConnectionPool.new(size: 5, timeout: 5) { Patron::Session.new }
112
+ patron_pool.with do |session|
113
+ session.get(...)
114
+ end
115
+ ```
65
116
 
66
117
  Sharing Session objects between requests will also allow you to benefit from persistent connections (connection reuse), see below.
67
118
 
68
119
  ## Persistent connections
69
120
 
70
- Patron follows the libCURL guidelines on [connection reuse.](https://ec.haxx.se/libcurl-connectionreuse.html) If you create the Session
121
+ Patron follows the libCURL guidelines on [connection reuse.](https://everything.curl.dev/libcurl/connectionreuse.html) If you create the Session
71
122
  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
123
  the same hostname/port/protocol the connection should get reused.
73
124
 
@@ -81,8 +132,10 @@ that are currently active in the process.
81
132
 
82
133
  ## Requirements
83
134
 
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
135
+ Patron 1.0 and up requires MRI Ruby 2.3 or newer. The 0.x versions support
136
+ Ruby 1.9.3 and these versions get tagged and developed on the `v0.x` branch.
137
+
138
+ A recent version of libCURL is required. We recommend at least 7.19.4 because
86
139
  it [supports limiting the protocols](https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html),
87
140
  and that is very important for security - especially if you follow redirects.
88
141
 
@@ -90,9 +143,6 @@ On OSX the provided libcurl is sufficient if you are not using fork+SSL combinat
90
143
  You will have to install the libcurl development packages on Debian or Ubuntu. Other Linux systems are probably
91
144
  similar. For Windows we do not have an established build instruction at the moment, unfortunately.
92
145
 
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
146
  ## Forking webservers on macOS and SSL
97
147
 
98
148
  Currently, [an issue is at play](https://github.com/curl/curl/issues/788) with OSX builds of `curl` which use
@@ -19,9 +19,12 @@ if CONFIG['CC'] =~ /gcc/
19
19
  $CFLAGS << ' -pedantic -Wall'
20
20
  end
21
21
 
22
- $defs.push("-DUSE_TBR")
23
- $defs.push("-DHAVE_THREAD_H") if have_header('ruby/thread.h')
24
- $defs.push("-DHAVE_TBR") if have_func('rb_thread_blocking_region', 'ruby.h')
25
- $defs.push("-DHAVE_TCWOGVL") if have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
22
+ if CONFIG['CC'] =~ /clang/
23
+ $CFLAGS << ' -pedantic -Wall -Wno-void-pointer-to-enum-cast'
24
+ end
25
+
26
+ # Lets CI build with debug info for valgrind without editing this file, like so:
27
+ # PATRON_EXTRA_CFLAGS="-g -O1" rake compile
28
+ $CFLAGS << ' ' << ENV['PATRON_EXTRA_CFLAGS'] if ENV['PATRON_EXTRA_CFLAGS']
26
29
 
27
30
  create_makefile 'patron/session_ext'