httpx 0.21.0 → 1.2.1

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.
Files changed (229) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +0 -48
  3. data/README.md +54 -45
  4. data/doc/release_notes/0_10_0.md +2 -2
  5. data/doc/release_notes/0_11_0.md +3 -5
  6. data/doc/release_notes/0_12_0.md +5 -5
  7. data/doc/release_notes/0_13_0.md +4 -4
  8. data/doc/release_notes/0_14_0.md +2 -2
  9. data/doc/release_notes/0_16_0.md +3 -3
  10. data/doc/release_notes/0_17_0.md +1 -1
  11. data/doc/release_notes/0_18_0.md +4 -4
  12. data/doc/release_notes/0_18_2.md +1 -1
  13. data/doc/release_notes/0_19_0.md +1 -1
  14. data/doc/release_notes/0_20_0.md +1 -1
  15. data/doc/release_notes/0_21_0.md +7 -5
  16. data/doc/release_notes/0_21_1.md +12 -0
  17. data/doc/release_notes/0_22_0.md +13 -0
  18. data/doc/release_notes/0_22_1.md +11 -0
  19. data/doc/release_notes/0_22_2.md +5 -0
  20. data/doc/release_notes/0_22_3.md +55 -0
  21. data/doc/release_notes/0_22_4.md +6 -0
  22. data/doc/release_notes/0_22_5.md +6 -0
  23. data/doc/release_notes/0_23_0.md +42 -0
  24. data/doc/release_notes/0_23_1.md +5 -0
  25. data/doc/release_notes/0_23_2.md +5 -0
  26. data/doc/release_notes/0_23_3.md +6 -0
  27. data/doc/release_notes/0_23_4.md +5 -0
  28. data/doc/release_notes/0_24_0.md +48 -0
  29. data/doc/release_notes/0_24_1.md +12 -0
  30. data/doc/release_notes/0_24_2.md +12 -0
  31. data/doc/release_notes/0_24_3.md +12 -0
  32. data/doc/release_notes/0_24_4.md +18 -0
  33. data/doc/release_notes/0_24_5.md +6 -0
  34. data/doc/release_notes/0_24_6.md +5 -0
  35. data/doc/release_notes/0_24_7.md +10 -0
  36. data/doc/release_notes/1_0_0.md +60 -0
  37. data/doc/release_notes/1_0_1.md +5 -0
  38. data/doc/release_notes/1_0_2.md +7 -0
  39. data/doc/release_notes/1_1_0.md +32 -0
  40. data/doc/release_notes/1_1_1.md +17 -0
  41. data/doc/release_notes/1_1_2.md +12 -0
  42. data/doc/release_notes/1_1_3.md +18 -0
  43. data/doc/release_notes/1_1_4.md +6 -0
  44. data/doc/release_notes/1_1_5.md +12 -0
  45. data/doc/release_notes/1_2_0.md +49 -0
  46. data/doc/release_notes/1_2_1.md +6 -0
  47. data/lib/httpx/adapters/datadog.rb +100 -106
  48. data/lib/httpx/adapters/faraday.rb +143 -107
  49. data/lib/httpx/adapters/sentry.rb +26 -7
  50. data/lib/httpx/adapters/webmock.rb +33 -17
  51. data/lib/httpx/altsvc.rb +61 -24
  52. data/lib/httpx/base64.rb +27 -0
  53. data/lib/httpx/buffer.rb +12 -0
  54. data/lib/httpx/callbacks.rb +5 -3
  55. data/lib/httpx/chainable.rb +54 -39
  56. data/lib/httpx/connection/http1.rb +62 -37
  57. data/lib/httpx/connection/http2.rb +16 -27
  58. data/lib/httpx/connection.rb +213 -120
  59. data/lib/httpx/domain_name.rb +10 -13
  60. data/lib/httpx/errors.rb +34 -2
  61. data/lib/httpx/extensions.rb +4 -134
  62. data/lib/httpx/io/ssl.rb +77 -71
  63. data/lib/httpx/io/tcp.rb +46 -70
  64. data/lib/httpx/io/udp.rb +18 -52
  65. data/lib/httpx/io/unix.rb +6 -13
  66. data/lib/httpx/io.rb +3 -9
  67. data/lib/httpx/loggable.rb +4 -19
  68. data/lib/httpx/options.rb +168 -110
  69. data/lib/httpx/plugins/{authentication → auth}/basic.rb +1 -5
  70. data/lib/httpx/plugins/{authentication → auth}/digest.rb +13 -14
  71. data/lib/httpx/plugins/{authentication → auth}/ntlm.rb +1 -3
  72. data/lib/httpx/plugins/{authentication → auth}/socks5.rb +0 -2
  73. data/lib/httpx/plugins/auth.rb +25 -0
  74. data/lib/httpx/plugins/aws_sdk_authentication.rb +1 -3
  75. data/lib/httpx/plugins/aws_sigv4.rb +5 -6
  76. data/lib/httpx/plugins/basic_auth.rb +29 -0
  77. data/lib/httpx/plugins/brotli.rb +50 -0
  78. data/lib/httpx/plugins/callbacks.rb +91 -0
  79. data/lib/httpx/plugins/circuit_breaker/circuit.rb +40 -16
  80. data/lib/httpx/plugins/circuit_breaker/circuit_store.rb +14 -5
  81. data/lib/httpx/plugins/circuit_breaker.rb +30 -7
  82. data/lib/httpx/plugins/cookies/set_cookie_parser.rb +0 -2
  83. data/lib/httpx/plugins/cookies.rb +20 -10
  84. data/lib/httpx/plugins/{digest_authentication.rb → digest_auth.rb} +11 -12
  85. data/lib/httpx/plugins/expect.rb +15 -13
  86. data/lib/httpx/plugins/follow_redirects.rb +71 -29
  87. data/lib/httpx/plugins/grpc/call.rb +2 -3
  88. data/lib/httpx/plugins/grpc/grpc_encoding.rb +88 -0
  89. data/lib/httpx/plugins/grpc/message.rb +7 -37
  90. data/lib/httpx/plugins/grpc.rb +35 -29
  91. data/lib/httpx/plugins/h2c.rb +25 -18
  92. data/lib/httpx/plugins/internal_telemetry.rb +16 -0
  93. data/lib/httpx/plugins/{ntlm_authentication.rb → ntlm_auth.rb} +7 -5
  94. data/lib/httpx/plugins/oauth.rb +170 -0
  95. data/lib/httpx/plugins/persistent.rb +1 -1
  96. data/lib/httpx/plugins/proxy/http.rb +15 -10
  97. data/lib/httpx/plugins/proxy/socks4.rb +8 -6
  98. data/lib/httpx/plugins/proxy/socks5.rb +10 -8
  99. data/lib/httpx/plugins/proxy.rb +69 -67
  100. data/lib/httpx/plugins/push_promise.rb +1 -1
  101. data/lib/httpx/plugins/rate_limiter.rb +3 -1
  102. data/lib/httpx/plugins/response_cache/file_store.rb +40 -0
  103. data/lib/httpx/plugins/response_cache/store.rb +34 -17
  104. data/lib/httpx/plugins/response_cache.rb +6 -6
  105. data/lib/httpx/plugins/retries.rb +61 -12
  106. data/lib/httpx/plugins/ssrf_filter.rb +142 -0
  107. data/lib/httpx/plugins/stream.rb +27 -32
  108. data/lib/httpx/plugins/upgrade/h2.rb +4 -4
  109. data/lib/httpx/plugins/upgrade.rb +8 -10
  110. data/lib/httpx/plugins/webdav.rb +10 -8
  111. data/lib/httpx/pool.rb +85 -23
  112. data/lib/httpx/punycode.rb +9 -291
  113. data/lib/httpx/request/body.rb +158 -0
  114. data/lib/httpx/request.rb +86 -121
  115. data/lib/httpx/resolver/https.rb +54 -17
  116. data/lib/httpx/resolver/multi.rb +8 -12
  117. data/lib/httpx/resolver/native.rb +163 -70
  118. data/lib/httpx/resolver/resolver.rb +28 -13
  119. data/lib/httpx/resolver/system.rb +15 -10
  120. data/lib/httpx/resolver.rb +38 -16
  121. data/lib/httpx/response/body.rb +242 -0
  122. data/lib/httpx/response/buffer.rb +96 -0
  123. data/lib/httpx/response.rb +113 -211
  124. data/lib/httpx/selector.rb +2 -4
  125. data/lib/httpx/session.rb +91 -64
  126. data/lib/httpx/session_extensions.rb +4 -1
  127. data/lib/httpx/timers.rb +28 -8
  128. data/lib/httpx/transcoder/body.rb +0 -2
  129. data/lib/httpx/transcoder/chunker.rb +0 -1
  130. data/lib/httpx/transcoder/deflate.rb +37 -0
  131. data/lib/httpx/transcoder/form.rb +52 -33
  132. data/lib/httpx/transcoder/gzip.rb +74 -0
  133. data/lib/httpx/transcoder/json.rb +2 -5
  134. data/lib/httpx/transcoder/multipart/decoder.rb +139 -0
  135. data/lib/httpx/{plugins → transcoder}/multipart/encoder.rb +3 -3
  136. data/lib/httpx/{plugins → transcoder}/multipart/mime_type_detector.rb +1 -1
  137. data/lib/httpx/{plugins → transcoder}/multipart/part.rb +3 -2
  138. data/lib/httpx/transcoder/multipart.rb +17 -0
  139. data/lib/httpx/transcoder/utils/body_reader.rb +46 -0
  140. data/lib/httpx/transcoder/utils/deflater.rb +72 -0
  141. data/lib/httpx/transcoder/utils/inflater.rb +19 -0
  142. data/lib/httpx/transcoder/xml.rb +0 -5
  143. data/lib/httpx/transcoder.rb +4 -6
  144. data/lib/httpx/utils.rb +36 -16
  145. data/lib/httpx/version.rb +1 -1
  146. data/lib/httpx.rb +12 -14
  147. data/sig/altsvc.rbs +33 -0
  148. data/sig/buffer.rbs +1 -0
  149. data/sig/callbacks.rbs +3 -3
  150. data/sig/chainable.rbs +10 -9
  151. data/sig/connection/http1.rbs +5 -4
  152. data/sig/connection/http2.rbs +1 -1
  153. data/sig/connection.rbs +46 -24
  154. data/sig/errors.rbs +9 -3
  155. data/sig/httpx.rbs +5 -4
  156. data/sig/io/ssl.rbs +26 -0
  157. data/sig/io/tcp.rbs +60 -0
  158. data/sig/io/udp.rbs +20 -0
  159. data/sig/io/unix.rbs +10 -0
  160. data/sig/options.rbs +28 -12
  161. data/sig/plugins/{authentication → auth}/basic.rbs +0 -2
  162. data/sig/plugins/{authentication → auth}/digest.rbs +2 -1
  163. data/sig/plugins/auth.rbs +13 -0
  164. data/sig/plugins/{basic_authentication.rbs → basic_auth.rbs} +2 -2
  165. data/sig/plugins/brotli.rbs +22 -0
  166. data/sig/plugins/callbacks.rbs +38 -0
  167. data/sig/plugins/circuit_breaker.rbs +13 -3
  168. data/sig/plugins/compression.rbs +6 -4
  169. data/sig/plugins/cookies/jar.rbs +2 -2
  170. data/sig/plugins/cookies.rbs +2 -0
  171. data/sig/plugins/{digest_authentication.rbs → digest_auth.rbs} +2 -2
  172. data/sig/plugins/follow_redirects.rbs +11 -2
  173. data/sig/plugins/grpc/call.rbs +19 -0
  174. data/sig/plugins/grpc/grpc_encoding.rbs +37 -0
  175. data/sig/plugins/grpc/message.rbs +17 -0
  176. data/sig/plugins/grpc.rbs +2 -32
  177. data/sig/plugins/h2c.rbs +1 -1
  178. data/sig/plugins/{ntlm_authentication.rbs → ntlm_auth.rbs} +2 -2
  179. data/sig/plugins/oauth.rbs +54 -0
  180. data/sig/plugins/proxy/socks4.rbs +4 -4
  181. data/sig/plugins/proxy/socks5.rbs +2 -2
  182. data/sig/plugins/proxy/ssh.rbs +1 -1
  183. data/sig/plugins/proxy.rbs +10 -4
  184. data/sig/plugins/response_cache.rbs +12 -3
  185. data/sig/plugins/retries.rbs +28 -8
  186. data/sig/plugins/stream.rbs +24 -17
  187. data/sig/plugins/upgrade.rbs +5 -3
  188. data/sig/pool.rbs +5 -4
  189. data/sig/request/body.rbs +40 -0
  190. data/sig/request.rbs +12 -28
  191. data/sig/resolver/https.rbs +7 -2
  192. data/sig/resolver/native.rbs +10 -4
  193. data/sig/resolver/resolver.rbs +6 -4
  194. data/sig/resolver/system.rbs +2 -0
  195. data/sig/resolver.rbs +9 -5
  196. data/sig/response/body.rbs +53 -0
  197. data/sig/response/buffer.rbs +24 -0
  198. data/sig/response.rbs +17 -38
  199. data/sig/session.rbs +24 -18
  200. data/sig/timers.rbs +17 -7
  201. data/sig/transcoder/body.rbs +4 -3
  202. data/sig/transcoder/deflate.rbs +11 -0
  203. data/sig/transcoder/form.rbs +5 -3
  204. data/sig/transcoder/gzip.rbs +24 -0
  205. data/sig/transcoder/json.rbs +4 -2
  206. data/sig/{plugins → transcoder}/multipart.rbs +3 -12
  207. data/sig/transcoder/utils/body_reader.rbs +15 -0
  208. data/sig/transcoder/utils/deflater.rbs +29 -0
  209. data/sig/transcoder/utils/inflater.rbs +12 -0
  210. data/sig/transcoder/xml.rbs +1 -1
  211. data/sig/transcoder.rbs +22 -7
  212. data/sig/utils.rbs +2 -0
  213. metadata +127 -40
  214. data/lib/httpx/plugins/authentication.rb +0 -20
  215. data/lib/httpx/plugins/basic_authentication.rb +0 -30
  216. data/lib/httpx/plugins/compression/brotli.rb +0 -54
  217. data/lib/httpx/plugins/compression/deflate.rb +0 -49
  218. data/lib/httpx/plugins/compression/gzip.rb +0 -88
  219. data/lib/httpx/plugins/compression.rb +0 -164
  220. data/lib/httpx/plugins/multipart/decoder.rb +0 -187
  221. data/lib/httpx/plugins/multipart.rb +0 -84
  222. data/lib/httpx/registry.rb +0 -85
  223. data/sig/plugins/authentication.rbs +0 -11
  224. data/sig/plugins/compression/brotli.rbs +0 -21
  225. data/sig/plugins/compression/deflate.rbs +0 -17
  226. data/sig/plugins/compression/gzip.rbs +0 -29
  227. data/sig/registry.rbs +0 -13
  228. /data/sig/plugins/{authentication → auth}/ntlm.rbs +0 -0
  229. /data/sig/plugins/{authentication → auth}/socks5.rbs +0 -0
@@ -0,0 +1,242 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPX
4
+ # Implementation of the HTTP Response body as a buffer which implements the IO writer protocol
5
+ # (for buffering the response payload), the IO reader protocol (for consuming the response payload),
6
+ # and can be iterated over (via #each, which yields the payload in chunks).
7
+ class Response::Body
8
+ # the payload encoding (i.e. "utf-8", "ASCII-8BIT")
9
+ attr_reader :encoding
10
+
11
+ # Array of encodings contained in the response "content-encoding" header.
12
+ attr_reader :encodings
13
+
14
+ # initialized with the corresponding HTTPX::Response +response+ and HTTPX::Options +options+.
15
+ def initialize(response, options)
16
+ @response = response
17
+ @headers = response.headers
18
+ @options = options
19
+ @window_size = options.window_size
20
+ @encoding = response.content_type.charset || Encoding::BINARY
21
+ @encodings = []
22
+ @length = 0
23
+ @buffer = nil
24
+ @reader = nil
25
+ @state = :idle
26
+ initialize_inflaters
27
+ end
28
+
29
+ def initialize_dup(other)
30
+ super
31
+
32
+ @buffer = other.instance_variable_get(:@buffer).dup
33
+ end
34
+
35
+ def closed?
36
+ @state == :closed
37
+ end
38
+
39
+ # write the response payload +chunk+ into the buffer. Inflates the chunk when required
40
+ # and supported.
41
+ def write(chunk)
42
+ return if @state == :closed
43
+
44
+ return 0 if chunk.empty?
45
+
46
+ chunk = decode_chunk(chunk)
47
+
48
+ size = chunk.bytesize
49
+ @length += size
50
+ transition(:open)
51
+ @buffer.write(chunk)
52
+
53
+ @response.emit(:chunk_received, chunk)
54
+ size
55
+ end
56
+
57
+ # reads a chunk from the payload (implementation of the IO reader protocol).
58
+ def read(*args)
59
+ return unless @buffer
60
+
61
+ unless @reader
62
+ rewind
63
+ @reader = @buffer
64
+ end
65
+
66
+ @reader.read(*args)
67
+ end
68
+
69
+ # size of the decoded response payload. May differ from "content-length" header if
70
+ # response was encoded over-the-wire.
71
+ def bytesize
72
+ @length
73
+ end
74
+
75
+ # yields the payload in chunks.
76
+ def each
77
+ return enum_for(__method__) unless block_given?
78
+
79
+ begin
80
+ if @buffer
81
+ rewind
82
+ while (chunk = @buffer.read(@window_size))
83
+ yield(chunk.force_encoding(@encoding))
84
+ end
85
+ end
86
+ ensure
87
+ close
88
+ end
89
+ end
90
+
91
+ # returns the declared filename in the "contennt-disposition" header, when present.
92
+ def filename
93
+ return unless @headers.key?("content-disposition")
94
+
95
+ Utils.get_filename(@headers["content-disposition"])
96
+ end
97
+
98
+ # returns the full response payload as a string.
99
+ def to_s
100
+ return "".b unless @buffer
101
+
102
+ @buffer.to_s
103
+ end
104
+
105
+ alias_method :to_str, :to_s
106
+
107
+ # whether the payload is empty.
108
+ def empty?
109
+ @length.zero?
110
+ end
111
+
112
+ # copies the payload to +dest+.
113
+ #
114
+ # body.copy_to("path/to/file")
115
+ # body.copy_to(Pathname.new("path/to/file"))
116
+ # body.copy_to(File.new("path/to/file"))
117
+ def copy_to(dest)
118
+ return unless @buffer
119
+
120
+ rewind
121
+
122
+ if dest.respond_to?(:path) && @buffer.respond_to?(:path)
123
+ FileUtils.mv(@buffer.path, dest.path)
124
+ else
125
+ ::IO.copy_stream(@buffer, dest)
126
+ end
127
+ end
128
+
129
+ # closes/cleans the buffer, resets everything
130
+ def close
131
+ if @buffer
132
+ @buffer.close
133
+ @buffer = nil
134
+ end
135
+ @length = 0
136
+ transition(:closed)
137
+ end
138
+
139
+ def ==(other)
140
+ object_id == other.object_id || begin
141
+ if other.respond_to?(:read)
142
+ _with_same_buffer_pos { FileUtils.compare_stream(@buffer, other) }
143
+ else
144
+ to_s == other.to_s
145
+ end
146
+ end
147
+ end
148
+
149
+ # :nocov:
150
+ def inspect
151
+ "#<HTTPX::Response::Body:#{object_id} " \
152
+ "@state=#{@state} " \
153
+ "@length=#{@length}>"
154
+ end
155
+ # :nocov:
156
+
157
+ # rewinds the response payload buffer.
158
+ def rewind
159
+ return unless @buffer
160
+
161
+ # in case there's some reading going on
162
+ @reader = nil
163
+
164
+ @buffer.rewind
165
+ end
166
+
167
+ private
168
+
169
+ # prepares inflaters for the advertised encodings in "content-encoding" header.
170
+ def initialize_inflaters
171
+ @inflaters = nil
172
+
173
+ return unless @headers.key?("content-encoding")
174
+
175
+ return unless @options.decompress_response_body
176
+
177
+ @inflaters = @headers.get("content-encoding").filter_map do |encoding|
178
+ next if encoding == "identity"
179
+
180
+ inflater = self.class.initialize_inflater_by_encoding(encoding, @response)
181
+
182
+ # do not uncompress if there is no decoder available. In fact, we can't reliably
183
+ # continue decompressing beyond that, so ignore.
184
+ break unless inflater
185
+
186
+ @encodings << encoding
187
+ inflater
188
+ end
189
+ end
190
+
191
+ # passes the +chunk+ through all inflaters to decode it.
192
+ def decode_chunk(chunk)
193
+ @inflaters.reverse_each do |inflater|
194
+ chunk = inflater.call(chunk)
195
+ end if @inflaters
196
+
197
+ chunk
198
+ end
199
+
200
+ # tries transitioning the body STM to the +nextstate+.
201
+ def transition(nextstate)
202
+ case nextstate
203
+ when :open
204
+ return unless @state == :idle
205
+
206
+ @buffer = Response::Buffer.new(
207
+ threshold_size: @options.body_threshold_size,
208
+ bytesize: @length,
209
+ encoding: @encoding
210
+ )
211
+ when :closed
212
+ return if @state == :closed
213
+ end
214
+
215
+ @state = nextstate
216
+ end
217
+
218
+ def _with_same_buffer_pos # :nodoc:
219
+ return yield unless @buffer && @buffer.respond_to?(:pos)
220
+
221
+ # @type ivar @buffer: StringIO | Tempfile
222
+ current_pos = @buffer.pos
223
+ @buffer.rewind
224
+ begin
225
+ yield
226
+ ensure
227
+ @buffer.pos = current_pos
228
+ end
229
+ end
230
+
231
+ class << self
232
+ def initialize_inflater_by_encoding(encoding, response, **kwargs) # :nodoc:
233
+ case encoding
234
+ when "gzip"
235
+ Transcoder::GZIP.decode(response, **kwargs)
236
+ when "deflate"
237
+ Transcoder::Deflate.decode(response, **kwargs)
238
+ end
239
+ end
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "delegate"
4
+ require "stringio"
5
+ require "tempfile"
6
+
7
+ module HTTPX
8
+ # wraps and delegates to an internal buffer, which can be a StringIO or a Tempfile.
9
+ class Response::Buffer < SimpleDelegator
10
+ # initializes buffer with the +threshold_size+ over which the payload gets buffer to a tempfile,
11
+ # the initial +bytesize+, and the +encoding+.
12
+ def initialize(threshold_size:, bytesize: 0, encoding: Encoding::BINARY)
13
+ @threshold_size = threshold_size
14
+ @bytesize = bytesize
15
+ @encoding = encoding
16
+ @buffer = StringIO.new("".b)
17
+ super(@buffer)
18
+ end
19
+
20
+ def initialize_dup(other)
21
+ super
22
+
23
+ @buffer = other.instance_variable_get(:@buffer).dup
24
+ end
25
+
26
+ # size in bytes of the buffered content.
27
+ def size
28
+ @bytesize
29
+ end
30
+
31
+ # writes the +chunk+ into the buffer.
32
+ def write(chunk)
33
+ @bytesize += chunk.bytesize
34
+ try_upgrade_buffer
35
+ @buffer.write(chunk)
36
+ end
37
+
38
+ # returns the buffered content as a string.
39
+ def to_s
40
+ case @buffer
41
+ when StringIO
42
+ begin
43
+ @buffer.string.force_encoding(@encoding)
44
+ rescue ArgumentError
45
+ @buffer.string
46
+ end
47
+ when Tempfile
48
+ rewind
49
+ content = _with_same_buffer_pos { @buffer.read }
50
+ begin
51
+ content.force_encoding(@encoding)
52
+ rescue ArgumentError # ex: unknown encoding name - utf
53
+ content
54
+ end
55
+ end
56
+ end
57
+
58
+ # closes the buffer.
59
+ def close
60
+ @buffer.close
61
+ @buffer.unlink if @buffer.respond_to?(:unlink)
62
+ end
63
+
64
+ private
65
+
66
+ # initializes the buffer into a StringIO, or turns it into a Tempfile when the threshold
67
+ # has been reached.
68
+ def try_upgrade_buffer
69
+ return unless @bytesize > @threshold_size
70
+
71
+ return if @buffer.is_a?(Tempfile)
72
+
73
+ aux = @buffer
74
+
75
+ @buffer = Tempfile.new("httpx", encoding: Encoding::BINARY, mode: File::RDWR)
76
+
77
+ if aux
78
+ aux.rewind
79
+ ::IO.copy_stream(aux, @buffer)
80
+ aux.close
81
+ end
82
+
83
+ __setobj__(@buffer)
84
+ end
85
+
86
+ def _with_same_buffer_pos # :nodoc:
87
+ current_pos = @buffer.pos
88
+ @buffer.rewind
89
+ begin
90
+ yield
91
+ ensure
92
+ @buffer.pos = current_pos
93
+ end
94
+ end
95
+ end
96
+ end