httpx 0.15.4 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/doc/release_notes/0_16_0.md +93 -0
  3. data/doc/release_notes/0_16_1.md +5 -0
  4. data/doc/release_notes/0_17_0.md +49 -0
  5. data/doc/release_notes/0_18_0.md +69 -0
  6. data/lib/httpx/adapters/datadog.rb +1 -1
  7. data/lib/httpx/adapters/faraday.rb +8 -14
  8. data/lib/httpx/adapters/webmock.rb +9 -3
  9. data/lib/httpx/altsvc.rb +2 -2
  10. data/lib/httpx/buffer.rb +1 -1
  11. data/lib/httpx/callbacks.rb +1 -1
  12. data/lib/httpx/chainable.rb +18 -11
  13. data/lib/httpx/connection/http1.rb +21 -13
  14. data/lib/httpx/connection/http2.rb +20 -25
  15. data/lib/httpx/connection.rb +73 -77
  16. data/lib/httpx/domain_name.rb +1 -1
  17. data/lib/httpx/errors.rb +11 -11
  18. data/lib/httpx/extensions.rb +50 -4
  19. data/lib/httpx/headers.rb +1 -1
  20. data/lib/httpx/io/ssl.rb +3 -3
  21. data/lib/httpx/io/tls.rb +8 -8
  22. data/lib/httpx/loggable.rb +5 -5
  23. data/lib/httpx/options.rb +108 -81
  24. data/lib/httpx/parser/http1.rb +11 -7
  25. data/lib/httpx/plugins/aws_sdk_authentication.rb +42 -18
  26. data/lib/httpx/plugins/aws_sigv4.rb +19 -20
  27. data/lib/httpx/plugins/compression.rb +17 -14
  28. data/lib/httpx/plugins/cookies/cookie.rb +4 -2
  29. data/lib/httpx/plugins/cookies/jar.rb +21 -2
  30. data/lib/httpx/plugins/cookies.rb +20 -7
  31. data/lib/httpx/plugins/digest_authentication.rb +19 -15
  32. data/lib/httpx/plugins/expect.rb +26 -18
  33. data/lib/httpx/plugins/follow_redirects.rb +9 -9
  34. data/lib/httpx/plugins/grpc/call.rb +4 -1
  35. data/lib/httpx/plugins/grpc/message.rb +2 -2
  36. data/lib/httpx/plugins/grpc.rb +72 -46
  37. data/lib/httpx/plugins/h2c.rb +7 -3
  38. data/lib/httpx/plugins/internal_telemetry.rb +8 -8
  39. data/lib/httpx/plugins/multipart/decoder.rb +187 -0
  40. data/lib/httpx/plugins/multipart/mime_type_detector.rb +3 -3
  41. data/lib/httpx/plugins/multipart/part.rb +2 -2
  42. data/lib/httpx/plugins/multipart.rb +16 -2
  43. data/lib/httpx/plugins/ntlm_authentication.rb +12 -10
  44. data/lib/httpx/plugins/proxy/socks4.rb +2 -1
  45. data/lib/httpx/plugins/proxy/socks5.rb +2 -1
  46. data/lib/httpx/plugins/proxy/ssh.rb +20 -13
  47. data/lib/httpx/plugins/proxy.rb +10 -10
  48. data/lib/httpx/plugins/response_cache/store.rb +55 -0
  49. data/lib/httpx/plugins/response_cache.rb +88 -0
  50. data/lib/httpx/plugins/retries.rb +46 -23
  51. data/lib/httpx/plugins/stream.rb +3 -4
  52. data/lib/httpx/plugins/upgrade.rb +7 -6
  53. data/lib/httpx/pool.rb +39 -13
  54. data/lib/httpx/registry.rb +2 -2
  55. data/lib/httpx/request.rb +16 -25
  56. data/lib/httpx/resolver/https.rb +4 -8
  57. data/lib/httpx/resolver/native.rb +19 -5
  58. data/lib/httpx/resolver/resolver_mixin.rb +2 -1
  59. data/lib/httpx/resolver/system.rb +2 -0
  60. data/lib/httpx/resolver.rb +2 -2
  61. data/lib/httpx/response.rb +91 -48
  62. data/lib/httpx/selector.rb +11 -24
  63. data/lib/httpx/session.rb +41 -23
  64. data/lib/httpx/session2.rb +23 -0
  65. data/lib/httpx/timers.rb +84 -0
  66. data/lib/httpx/transcoder/body.rb +3 -2
  67. data/lib/httpx/transcoder/chunker.rb +2 -1
  68. data/lib/httpx/transcoder/form.rb +20 -0
  69. data/lib/httpx/transcoder/json.rb +12 -0
  70. data/lib/httpx/transcoder.rb +62 -1
  71. data/lib/httpx/utils.rb +10 -2
  72. data/lib/httpx/version.rb +1 -1
  73. data/lib/httpx.rb +7 -3
  74. data/sig/buffer.rbs +3 -1
  75. data/sig/chainable.rbs +31 -29
  76. data/sig/connection/http1.rbs +11 -5
  77. data/sig/connection/http2.rbs +16 -5
  78. data/sig/connection.rbs +31 -13
  79. data/sig/errors.rbs +35 -1
  80. data/sig/headers.rbs +20 -19
  81. data/sig/httpx.rbs +4 -1
  82. data/sig/loggable.rbs +3 -1
  83. data/sig/options.rbs +45 -34
  84. data/sig/parser/http1.rbs +3 -3
  85. data/sig/plugins/authentication.rbs +1 -1
  86. data/sig/plugins/aws_sdk_authentication.rbs +25 -3
  87. data/sig/plugins/aws_sigv4.rbs +13 -5
  88. data/sig/plugins/basic_authentication.rbs +1 -1
  89. data/sig/plugins/compression.rbs +4 -6
  90. data/sig/plugins/cookies/cookie.rbs +5 -7
  91. data/sig/plugins/cookies/jar.rbs +9 -10
  92. data/sig/plugins/cookies.rbs +4 -5
  93. data/sig/plugins/digest_authentication.rbs +2 -3
  94. data/sig/plugins/expect.rbs +2 -4
  95. data/sig/plugins/follow_redirects.rbs +3 -5
  96. data/sig/plugins/grpc.rbs +4 -7
  97. data/sig/plugins/h2c.rbs +0 -2
  98. data/sig/plugins/multipart.rbs +64 -10
  99. data/sig/plugins/ntlm_authentication.rbs +2 -3
  100. data/sig/plugins/persistent.rbs +3 -8
  101. data/sig/plugins/proxy/ssh.rbs +4 -4
  102. data/sig/plugins/proxy.rbs +13 -13
  103. data/sig/plugins/push_promise.rbs +0 -2
  104. data/sig/plugins/response_cache.rbs +35 -0
  105. data/sig/plugins/retries.rbs +7 -8
  106. data/sig/plugins/stream.rbs +1 -1
  107. data/sig/plugins/upgrade.rbs +2 -3
  108. data/sig/pool.rbs +7 -2
  109. data/sig/registry.rbs +1 -1
  110. data/sig/request.rbs +11 -8
  111. data/sig/resolver/native.rbs +10 -5
  112. data/sig/resolver/resolver_mixin.rbs +4 -5
  113. data/sig/resolver/system.rbs +4 -0
  114. data/sig/resolver.rbs +7 -0
  115. data/sig/response.rbs +26 -13
  116. data/sig/selector.rbs +11 -9
  117. data/sig/session.rbs +22 -23
  118. data/sig/timers.rbs +32 -0
  119. data/sig/transcoder/body.rbs +6 -1
  120. data/sig/transcoder/chunker.rbs +8 -2
  121. data/sig/transcoder/form.rbs +3 -1
  122. data/sig/transcoder/json.rbs +2 -0
  123. data/sig/transcoder.rbs +13 -5
  124. data/sig/utils.rbs +6 -0
  125. metadata +18 -18
  126. data/lib/httpx/request2.rb +0 -14
@@ -69,10 +69,10 @@ module HTTPX
69
69
  end
70
70
 
71
71
  @inflight = 0
72
- @keep_alive_timeout = options.timeout[:keep_alive_timeout]
73
- @keep_alive_timer = nil
72
+ @keep_alive_timeout = @options.timeout[:keep_alive_timeout]
73
+ @total_timeout = @options.timeout[:total_timeout]
74
74
 
75
- self.addresses = options.addresses if options.addresses
75
+ self.addresses = @options.addresses if @options.addresses
76
76
  end
77
77
 
78
78
  # this is a semi-private method, to be used by the resolver
@@ -200,11 +200,9 @@ module HTTPX
200
200
  end
201
201
 
202
202
  def close
203
- @parser.close if @parser
204
- return unless @keep_alive_timer
203
+ transition(:active) if @state == :inactive
205
204
 
206
- @keep_alive_timer.cancel
207
- remove_instance_variable(:@keep_alive_timer)
205
+ @parser.close if @parser
208
206
  end
209
207
 
210
208
  def reset
@@ -216,26 +214,40 @@ module HTTPX
216
214
  def send(request)
217
215
  if @parser && !@write_buffer.full?
218
216
  request.headers["alt-used"] = @origin.authority if match_altsvcs?(request.uri)
219
- if @keep_alive_timer
217
+
218
+ if @response_received_at && @keep_alive_timeout &&
219
+ Utils.elapsed_time(@response_received_at) > @keep_alive_timeout
220
220
  # when pushing a request into an existing connection, we have to check whether there
221
221
  # is the possibility that the connection might have extended the keep alive timeout.
222
222
  # for such cases, we want to ping for availability before deciding to shovel requests.
223
- if @keep_alive_timer.fires_in.negative?
224
- @pending << request
225
- parser.ping
226
- return
227
- end
228
-
229
- @keep_alive_timer.pause
223
+ @pending << request
224
+ parser.ping
225
+ transition(:active) if @state == :inactive
226
+ return
230
227
  end
231
- @inflight += 1
232
- parser.send(request)
228
+
229
+ send_request_to_parser(request)
233
230
  else
234
231
  @pending << request
235
232
  end
236
233
  end
237
234
 
238
235
  def timeout
236
+ if @total_timeout
237
+ return @total_timeout unless @connected_at
238
+
239
+ elapsed_time = @total_timeout - Utils.elapsed_time(@connected_at)
240
+
241
+ if elapsed_time.negative?
242
+ ex = TotalTimeoutError.new(@total_timeout, "Timed out after #{@total_timeout} seconds")
243
+ ex.set_backtrace(caller)
244
+ on_error(@total_timeout)
245
+ return
246
+ end
247
+
248
+ return elapsed_time
249
+ end
250
+
239
251
  return @timeout if defined?(@timeout)
240
252
 
241
253
  return @options.timeout[:connect_timeout] if @state == :idle
@@ -243,6 +255,14 @@ module HTTPX
243
255
  @options.timeout[:operation_timeout]
244
256
  end
245
257
 
258
+ def deactivate
259
+ transition(:inactive)
260
+ end
261
+
262
+ def open?
263
+ @state == :open || @state == :inactive
264
+ end
265
+
246
266
  private
247
267
 
248
268
  def connect
@@ -313,7 +333,7 @@ module HTTPX
313
333
 
314
334
  # exit #consume altogether if all outstanding requests have been dealt with
315
335
  return if @pending.size.zero? && @inflight.zero?
316
- end unless (interests.nil? || interests == :w || @state == :closing) && !epiped
336
+ end unless ((ints = interests).nil? || ints == :w || @state == :closing) && !epiped
317
337
 
318
338
  #
319
339
  # tight write loop.
@@ -360,19 +380,18 @@ module HTTPX
360
380
  break if interests == :r || @state == :closing || @state == :closed
361
381
 
362
382
  write_drained = false
363
- end unless interests == :r
383
+ end unless (ints = interests) == :r
364
384
 
365
385
  send_pending if @state == :open
366
386
 
367
387
  # return if socket is drained
368
- next unless (interests != :r || read_drained) &&
369
- (interests != :w || write_drained)
388
+ next unless (ints != :r || read_drained) && (ints != :w || write_drained)
370
389
 
371
390
  # gotta go back to the event loop. It happens when:
372
391
  #
373
392
  # * the socket is drained of bytes or it's not the interest of the conn to read;
374
393
  # * theres nothing more to write, or it's not in the interest of the conn to write;
375
- log(level: 3) { "(#{interests}): WAITING FOR EVENTS..." }
394
+ log(level: 3) { "(#{ints}): WAITING FOR EVENTS..." }
376
395
  return
377
396
  end
378
397
  end
@@ -380,9 +399,7 @@ module HTTPX
380
399
 
381
400
  def send_pending
382
401
  while !@write_buffer.full? && (request = @pending.shift)
383
- @inflight += 1
384
- @keep_alive_timer.pause if @keep_alive_timer
385
- parser.send(request)
402
+ send_request_to_parser(request)
386
403
  end
387
404
  end
388
405
 
@@ -390,6 +407,15 @@ module HTTPX
390
407
  @parser ||= build_parser
391
408
  end
392
409
 
410
+ def send_request_to_parser(request)
411
+ @inflight += 1
412
+ parser.send(request)
413
+
414
+ return unless @state == :inactive
415
+
416
+ transition(:active)
417
+ end
418
+
393
419
  def build_parser(protocol = @io.protocol)
394
420
  parser = registry(protocol).new(@write_buffer, @options)
395
421
  set_parser_callbacks(parser)
@@ -401,7 +427,8 @@ module HTTPX
401
427
  AltSvc.emit(request, response) do |alt_origin, origin, alt_params|
402
428
  emit(:altsvc, alt_origin, origin, alt_params)
403
429
  end
404
- handle_response
430
+ @response_received_at = Utils.now
431
+ @inflight -= 1
405
432
  request.emit(:response, response)
406
433
  end
407
434
  parser.on(:altsvc) do |alt_origin, origin, alt_params|
@@ -421,7 +448,7 @@ module HTTPX
421
448
  end
422
449
  parser.on(:close) do |force|
423
450
  transition(:closing)
424
- if force
451
+ if force || @state == :idle
425
452
  transition(:closed)
426
453
  emit(:close)
427
454
  end
@@ -467,15 +494,17 @@ module HTTPX
467
494
  when :open
468
495
  return if @state == :closed
469
496
 
470
- total_timeout
471
-
472
497
  @io.connect
473
498
  return unless @io.connected?
474
499
 
500
+ @connected_at = Utils.now
501
+
475
502
  send_pending
476
503
 
477
504
  @timeout = @current_timeout = parser.timeout
478
505
  emit(:open)
506
+ when :inactive
507
+ return unless @state == :open
479
508
  when :closing
480
509
  return unless @state == :open
481
510
 
@@ -483,15 +512,15 @@ module HTTPX
483
512
  return unless @state == :closing
484
513
  return unless @write_buffer.empty?
485
514
 
486
- if @total_timeout
487
- @total_timeout.cancel
488
- remove_instance_variable(:@total_timeout)
489
- end
490
-
491
515
  purge_after_closed
492
516
  when :already_open
493
517
  nextstate = :open
494
518
  send_pending
519
+ when :active
520
+ return unless @state == :inactive
521
+
522
+ nextstate = :open
523
+ emit(:activate)
495
524
  end
496
525
  @state = nextstate
497
526
  rescue Errno::ECONNREFUSED,
@@ -507,44 +536,24 @@ module HTTPX
507
536
  def purge_after_closed
508
537
  @io.close if @io
509
538
  @read_buffer.clear
510
- if @keep_alive_timer
511
- @keep_alive_timer.cancel
512
- remove_instance_variable(:@keep_alive_timer)
513
- end
514
-
515
539
  remove_instance_variable(:@timeout) if defined?(@timeout)
516
540
  end
517
541
 
518
- def handle_response
519
- @inflight -= 1
520
- return unless @inflight.zero?
521
-
522
- if @keep_alive_timer
523
- @keep_alive_timer.resume
524
- @keep_alive_timer.reset
525
- else
526
- @keep_alive_timer = @timers.after(@keep_alive_timeout) do
527
- unless @inflight.zero?
528
- log { "(#{@origin}): keep alive timeout expired" }
529
- parser.ping
530
- end
531
- end
532
- end
533
- end
534
-
535
542
  def on_error(error)
536
543
  if error.instance_of?(TimeoutError)
537
- if @timeout
538
- @timeout -= error.timeout
539
- return unless @timeout <= 0
540
- end
541
544
 
542
- if @total_timeout && @total_timeout.fires_in.negative?
543
- ex = TotalTimeoutError.new(@total_timeout.interval, "Timed out after #{@total_timeout.interval} seconds")
545
+ if @total_timeout && @connected_at &&
546
+ Utils.elapsed_time(@connected_at) > @total_timeout
547
+ ex = TotalTimeoutError.new(@total_timeout, "Timed out after #{@total_timeout} seconds")
544
548
  ex.set_backtrace(error.backtrace)
545
549
  error = ex
546
- elsif connecting?
547
- error = error.to_connection_error
550
+ else
551
+ if @timeout
552
+ @timeout -= error.timeout
553
+ return unless @timeout <= 0
554
+ end
555
+
556
+ error = error.to_connection_error if connecting?
548
557
  end
549
558
  end
550
559
  handle_error(error)
@@ -559,18 +568,5 @@ module HTTPX
559
568
  request.emit(:response, response)
560
569
  end
561
570
  end
562
-
563
- def total_timeout
564
- total = @options.timeout[:total_timeout]
565
-
566
- return unless total
567
-
568
- @total_timeout ||= @timers.after(total) do
569
- ex = TotalTimeoutError.new(total, "Timed out after #{total} seconds")
570
- ex.set_backtrace(caller)
571
- on_error(ex)
572
- @parser.close if @parser
573
- end
574
- end
575
571
  end
576
572
  end
@@ -123,7 +123,7 @@ module HTTPX
123
123
 
124
124
  # RFC 6265 #4.1.1
125
125
  # Domain-value must be a subdomain.
126
- @domain && self <= domain && domain <= @domain ? true : false
126
+ @domain && self <= domain && domain <= @domain
127
127
  end
128
128
 
129
129
  # def ==(other)
data/lib/httpx/errors.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
- Error = Class.new(StandardError)
4
+ class Error < StandardError; end
5
5
 
6
- UnsupportedSchemeError = Class.new(Error)
6
+ class UnsupportedSchemeError < Error; end
7
7
 
8
- TimeoutError = Class.new(Error) do
8
+ class TimeoutError < Error
9
9
  attr_reader :timeout
10
10
 
11
11
  def initialize(timeout, message)
@@ -20,17 +20,17 @@ module HTTPX
20
20
  end
21
21
  end
22
22
 
23
- TotalTimeoutError = Class.new(TimeoutError)
23
+ class TotalTimeoutError < TimeoutError; end
24
24
 
25
- ConnectTimeoutError = Class.new(TimeoutError)
25
+ class ConnectTimeoutError < TimeoutError; end
26
26
 
27
- SettingsTimeoutError = Class.new(TimeoutError)
27
+ class SettingsTimeoutError < TimeoutError; end
28
28
 
29
- ResolveTimeoutError = Class.new(TimeoutError)
29
+ class ResolveTimeoutError < TimeoutError; end
30
30
 
31
- ResolveError = Class.new(Error)
31
+ class ResolveError < Error; end
32
32
 
33
- NativeResolveError = Class.new(ResolveError) do
33
+ class NativeResolveError < ResolveError
34
34
  attr_reader :connection, :host
35
35
 
36
36
  def initialize(connection, host, message = "Can't resolve #{host}")
@@ -40,7 +40,7 @@ module HTTPX
40
40
  end
41
41
  end
42
42
 
43
- HTTPError = Class.new(Error) do
43
+ class HTTPError < Error
44
44
  attr_reader :response
45
45
 
46
46
  def initialize(response)
@@ -53,5 +53,5 @@ module HTTPX
53
53
  end
54
54
  end
55
55
 
56
- MisdirectedRequestError = Class.new(HTTPError)
56
+ class MisdirectedRequestError < HTTPError; end
57
57
  end
@@ -54,6 +54,51 @@ module HTTPX
54
54
  Numeric.__send__(:include, NegMethods)
55
55
  end
56
56
 
57
+ module HashExtensions
58
+ refine Hash do
59
+ def compact
60
+ h = {}
61
+ each do |key, value|
62
+ h[key] = value unless value == nil
63
+ end
64
+ h
65
+ end unless Hash.method_defined?(:compact)
66
+ end
67
+ end
68
+
69
+ module ArrayExtensions
70
+ refine Array do
71
+
72
+ def filter_map
73
+ return to_enum(:filter_map) unless block_given?
74
+
75
+ each_with_object([]) do |item, res|
76
+ processed = yield(item)
77
+ res << processed if processed
78
+ end
79
+ end unless Array.method_defined?(:filter_map)
80
+
81
+ def sum(accumulator = 0, &block)
82
+ values = block_given? ? map(&block) : self
83
+ values.inject(accumulator, :+)
84
+ end unless Array.method_defined?(:sum)
85
+ end
86
+ end
87
+
88
+ module IOExtensions
89
+ refine IO do
90
+ # provides a fallback for rubies where IO#wait isn't implemented,
91
+ # but IO#wait_readable and IO#wait_writable are.
92
+ def wait(timeout = nil, _mode = :read_write)
93
+ r, w = IO.select([self], [self], nil, timeout)
94
+
95
+ return unless r || w
96
+
97
+ self
98
+ end unless IO.method_defined?(:wait) && IO.instance_method(:wait).arity == 2
99
+ end
100
+ end
101
+
57
102
  module RegexpExtensions
58
103
  # If you wonder why this is there: the oauth feature uses a refinement to enhance the
59
104
  # Regexp class locally with #match? , but this is never tested, because ActiveSupport
@@ -77,13 +122,14 @@ module HTTPX
77
122
  end
78
123
 
79
124
  def authority
80
- port_string = port == default_port ? nil : ":#{port}"
81
- "#{host}#{port_string}"
82
- end
125
+ return host if port == default_port
126
+
127
+ "#{host}:#{port}"
128
+ end unless URI::HTTP.method_defined?(:authority)
83
129
 
84
130
  def origin
85
131
  "#{scheme}://#{authority}"
86
- end
132
+ end unless URI::HTTP.method_defined?(:origin)
87
133
 
88
134
  def altsvc_match?(uri)
89
135
  uri = URI.parse(uri)
data/lib/httpx/headers.rb CHANGED
@@ -57,7 +57,7 @@ module HTTPX
57
57
  def merge(other)
58
58
  headers = dup
59
59
  other.each do |field, value|
60
- headers[field] = value
60
+ headers[downcased(field)] = value
61
61
  end
62
62
  headers
63
63
  end
data/lib/httpx/io/ssl.rb CHANGED
@@ -7,9 +7,9 @@ module HTTPX
7
7
 
8
8
  class SSL < TCP
9
9
  TLS_OPTIONS = if OpenSSL::SSL::SSLContext.instance_methods.include?(:alpn_protocols)
10
- { alpn_protocols: %w[h2 http/1.1] }
10
+ { alpn_protocols: %w[h2 http/1.1].freeze }.freeze
11
11
  else
12
- {}
12
+ {}.freeze
13
13
  end
14
14
 
15
15
  def initialize(_, _, options)
@@ -134,7 +134,7 @@ module HTTPX
134
134
  server_cert = @io.peer_cert
135
135
 
136
136
  "#{super}\n\n" \
137
- "SSL connection using #{@io.ssl_version} / #{Array(@io.cipher).first}\n" \
137
+ "SSL connection using #{@io.ssl_version} / #{Array(@io.cipher).first}\n" \
138
138
  "ALPN, server accepted to use #{protocol}\n" \
139
139
  "Server certificate:\n" \
140
140
  " subject: #{server_cert.subject}\n" \
data/lib/httpx/io/tls.rb CHANGED
@@ -4,7 +4,7 @@ require "openssl"
4
4
 
5
5
  module HTTPX
6
6
  class TLS < TCP
7
- Error = Class.new(StandardError)
7
+ class Error < StandardError; end
8
8
 
9
9
  def initialize(_, _, options)
10
10
  super
@@ -194,15 +194,15 @@ module HTTPX
194
194
  server_cert = @peer_cert
195
195
 
196
196
  "#{super}\n\n" \
197
- "SSL connection using #{@ctx.ssl_version} / #{Array(@ctx.cipher).first}\n" \
198
- "ALPN, server accepted to use #{protocol}\n" +
197
+ "SSL connection using #{@ctx.ssl_version} / #{Array(@ctx.cipher).first}\n" \
198
+ "ALPN, server accepted to use #{protocol}\n" +
199
199
  (if server_cert
200
200
  "Server certificate:\n" \
201
- " subject: #{server_cert.subject}\n" \
202
- " start date: #{server_cert.not_before}\n" \
203
- " expire date: #{server_cert.not_after}\n" \
204
- " issuer: #{server_cert.issuer}\n" \
205
- " SSL certificate verify ok."
201
+ " subject: #{server_cert.subject}\n" \
202
+ " start date: #{server_cert.not_before}\n" \
203
+ " expire date: #{server_cert.not_after}\n" \
204
+ " issuer: #{server_cert.issuer}\n" \
205
+ " SSL certificate verify ok."
206
206
  else
207
207
  "SSL certificate verify failed."
208
208
  end
@@ -24,15 +24,13 @@ module HTTPX
24
24
  debug_stream << message
25
25
  end
26
26
 
27
- if !Exception.instance_methods.include?(:full_message)
27
+ if Exception.instance_methods.include?(:full_message)
28
28
 
29
29
  def log_exception(ex, level: @options.debug_level, color: nil)
30
30
  return unless @options.debug
31
31
  return unless @options.debug_level >= level
32
32
 
33
- message = +"#{ex.message} (#{ex.class})"
34
- message << "\n" << ex.backtrace.join("\n") unless ex.backtrace.nil?
35
- log(level: level, color: color) { message }
33
+ log(level: level, color: color) { ex.full_message }
36
34
  end
37
35
 
38
36
  else
@@ -41,7 +39,9 @@ module HTTPX
41
39
  return unless @options.debug
42
40
  return unless @options.debug_level >= level
43
41
 
44
- log(level: level, color: color) { ex.full_message }
42
+ message = +"#{ex.message} (#{ex.class})"
43
+ message << "\n" << ex.backtrace.join("\n") unless ex.backtrace.nil?
44
+ log(level: level, color: color) { message }
45
45
  end
46
46
 
47
47
  end