wreq 1.2.7 → 1.2.8

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: d852c54ebc9e5ea5e94dee83399d2d59f8df824cc68bc74065e94eb0885e99a6
4
- data.tar.gz: def648deb12f7339b3de1271dee582cb9e9c03f9cf6cf483bc8031f3815861b5
3
+ metadata.gz: 556005991e7cd3da728dada73a12c7fc016fa08e0701f7bc027e3da8c40003fd
4
+ data.tar.gz: dea7a13e0c20655b7aee8404e51c60c37b293c18bf453eac304e0bd9b9759f78
5
5
  SHA512:
6
- metadata.gz: f25d1ee505f44c8ce4c81b8f12f91a87d7ec6b5c324aa1c2478a6d9a2e18e4604036f46bd9cf711b951007ae53cb6811dd0b7e77973631d179dfd070f2c240ce
7
- data.tar.gz: 890f1c4514804666a60f40735d9a678c26edbf0c2d17d057990e61d3209e39aca819c2ebf26cff8e4a3f1a2f7661b94467f109d24f469c3e93007f6c5bcdbf7a
6
+ metadata.gz: c3f420c02de369f78abed9022089a2e221a8b5da7e71775aadce38cc23482615ba51405f447e855422f68f27b13af8534011816e0065eac42954bba1d1b8ce7a
7
+ data.tar.gz: 84876653e4a2233f2d0502b4eb3118a318178051b0dc52669aa26b94d85f741b23cff1f520d30c5891a32f630736adcd0c97dbd308e8530985234c5c017ea3a8
data/Cargo.lock CHANGED
@@ -1549,7 +1549,7 @@ dependencies = [
1549
1549
 
1550
1550
  [[package]]
1551
1551
  name = "wreq-ruby"
1552
- version = "1.2.7"
1552
+ version = "1.2.8"
1553
1553
  dependencies = [
1554
1554
  "arc-swap",
1555
1555
  "bytes",
data/Cargo.toml CHANGED
@@ -5,7 +5,7 @@ authors = ["SearchApi <support@searchapi.io>"]
5
5
  homepage = "https://github.com/SearchApi/wreq-ruby"
6
6
  repository = "https://github.com/SearchApi/wreq-ruby"
7
7
  edition = "2024"
8
- version = "1.2.7"
8
+ version = "1.2.8"
9
9
  rust-version = "1.95"
10
10
 
11
11
  [lib]
@@ -2,6 +2,10 @@
2
2
 
3
3
  unless defined?(Wreq)
4
4
  module Wreq
5
+ # Keep interruption outside StandardError so a broad transport rescue
6
+ # never swallows a Ruby interrupt.
7
+ class InterruptError < Interrupt; end
8
+
5
9
  # System-level and runtime errors
6
10
 
7
11
  # Memory allocation failed.
@@ -113,7 +113,7 @@ impl BodySender {
113
113
  /// # Errors
114
114
  ///
115
115
  /// Returns `IOError` after either channel side has closed. An interrupted
116
- /// wait raises Ruby's standard `Interrupt` exception.
116
+ /// wait raises `Wreq::InterruptError`.
117
117
  pub fn push(ruby: &Ruby, rb_self: &Self, data: RString) -> Result<(), Error> {
118
118
  // Clone during the shared borrow, then release it before waiting
119
119
  // for capacity. Request attachment needs a mutable borrow.
data/src/error.rs CHANGED
@@ -84,14 +84,18 @@ define_exception!(DECODING_ERROR, "DecodingError", exception_runtime_error);
84
84
  // Configuration and builder errors
85
85
  define_exception!(BUILDER_ERROR, "BuilderError", exception_runtime_error);
86
86
 
87
+ // Keep interruption outside StandardError so a broad transport rescue
88
+ // never swallows a Ruby interrupt.
89
+ define_exception!(INTERRUPT_ERROR, "InterruptError", exception_interrupt);
90
+
87
91
  /// Memory error constant
88
92
  pub fn memory_error(ruby: &Ruby) -> MagnusError {
89
93
  MagnusError::new(ruby.get_inner(&MEMORY), RACE_CONDITION_ERROR_MSG)
90
94
  }
91
95
 
92
- /// Create Ruby's standard thread interruption error.
96
+ /// Create a `Wreq::InterruptError` when Ruby interrupts a request.
93
97
  pub fn interrupt_error(ruby: &Ruby) -> MagnusError {
94
- MagnusError::new(ruby.exception_interrupt(), "request interrupted")
98
+ MagnusError::new(ruby.get_inner(&INTERRUPT_ERROR), "request interrupted")
95
99
  }
96
100
 
97
101
  /// Map a Tokio runtime initialization failure to `Wreq::BuilderError`.
@@ -312,5 +316,12 @@ pub fn include(ruby: &Ruby, gem_module: &RModule) -> Result<(), MagnusError> {
312
316
  "BuilderError",
313
317
  exception_runtime_error
314
318
  );
319
+ initialize_exception!(
320
+ ruby,
321
+ gem_module,
322
+ INTERRUPT_ERROR,
323
+ "InterruptError",
324
+ exception_interrupt
325
+ );
315
326
  Ok(())
316
327
  }
data/src/rt.rs CHANGED
@@ -29,7 +29,7 @@ enum BlockOnError<E> {
29
29
  /// # Errors
30
30
  ///
31
31
  /// Returns `Wreq::BuilderError` if the Tokio runtime cannot be initialized,
32
- /// Ruby's standard `Interrupt` if Ruby interrupts the request, or the error produced
32
+ /// `Wreq::InterruptError` if Ruby interrupts the request, or the error produced
33
33
  /// by `map_err` if the future fails.
34
34
  pub fn try_block_on<F, T, E, M>(ruby: &Ruby, future: F, map_err: M) -> Result<T, magnus::Error>
35
35
  where
@@ -1,6 +1,37 @@
1
1
  require "test_helper"
2
+ require "socket"
3
+ require "timeout"
2
4
 
3
5
  class ErrorHandlingTest < Minitest::Test
6
+ def test_interrupt_error_stays_outside_standard_error
7
+ assert_equal Interrupt, Wreq::InterruptError.superclass
8
+ refute_operator Wreq::InterruptError, :<, StandardError
9
+ end
10
+
11
+ def test_request_interruption_raises_interrupt_error
12
+ request_thread = nil
13
+ with_hanging_server do |url, accepted|
14
+ request_thread = Thread.new do
15
+ Wreq.get(url, timeout: 60)
16
+ rescue Interrupt, StandardError => error
17
+ error
18
+ end
19
+ request_thread.report_on_exception = false
20
+
21
+ Timeout.timeout(5) { accepted.pop }
22
+ request_thread.wakeup
23
+
24
+ assert request_thread.join(5), "Interrupted request thread should stop"
25
+
26
+ error = request_thread.value
27
+ assert_instance_of Wreq::InterruptError, error
28
+ refute_kind_of StandardError, error
29
+ end
30
+ ensure
31
+ request_thread&.kill
32
+ request_thread&.join(1)
33
+ end
34
+
4
35
  def test_network_error_handling
5
36
  # Try to connect to a non-existent domain
6
37
  response = Wreq.get("https://definitely-not-a-real-domain-12345.com")
@@ -89,4 +120,27 @@ class ErrorHandlingTest < Minitest::Test
89
120
  end
90
121
  end
91
122
  end
123
+
124
+ private
125
+
126
+ def with_hanging_server
127
+ server = TCPServer.new("127.0.0.1", 0)
128
+ accepted = Queue.new
129
+ thread = Thread.new do
130
+ socket = server.accept
131
+ accepted << true
132
+ sleep
133
+ rescue IOError, SystemCallError
134
+ nil
135
+ ensure
136
+ socket&.close unless socket&.closed?
137
+ end
138
+ thread.report_on_exception = false
139
+
140
+ yield "http://127.0.0.1:#{server.addr[1]}/", accepted
141
+ ensure
142
+ server&.close unless server&.closed?
143
+ thread&.kill
144
+ thread&.join(1)
145
+ end
92
146
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wreq
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.7
4
+ version: 1.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - SearchApi