Class: ReactOnRailsPro::RendererHttpClient
- Inherits:
-
Object
- Object
- ReactOnRailsPro::RendererHttpClient
show all
- Defined in:
- lib/react_on_rails_pro/renderer_http_client.rb,
sig/react_on_rails_pro/renderer_http_client.rbs
Overview
rubocop:disable Metrics/ClassLength
Defined Under Namespace
Classes: BufferedResponseBody, ConnectTimeoutWrapper, ConnectionError, Error, HTTPError, MultipartBody, MultipartFileBody, PersistentThreadClient, Response, TimeoutError
Constant Summary
collapse
- CONNECTION_ERRORS =
[
SocketError,
IOError,
Errno::ECONNRESET,
Errno::ECONNREFUSED,
Errno::EHOSTUNREACH,
Errno::ENETUNREACH,
Errno::EPIPE,
Errno::ETIMEDOUT,
Protocol::HTTP::RefusedError
].freeze
- SCHEDULER_CLIENTS_KEY =
Per-scheduler storage for persistent HTTP clients. When an outer Fiber.scheduler
exists BEFORE we enter Sync {}, clients are stored on the scheduler object using
this instance variable key. This enables connection reuse across requests within
the same long-lived scheduler context (e.g., Falcon, Puma with async scheduler).
The hash maps origin URLs to Async::HTTP::Client instances.
IMPORTANT: We only use persistent mode when a scheduler already exists before
execute_request enters Sync {}. If Sync {} creates an ephemeral scheduler,
we use the ephemeral client path to ensure proper cleanup when the block exits.
:@__ror_pro_http_clients__
- CLIENT_GENERATION_MUTEX =
Mutex.new
Class Method Summary
collapse
Instance Method Summary
collapse
-
#close ⇒ nil
-
#get(path) ⇒ Response
-
#initialize(origin:, pool_size:, connect_timeout:, read_timeout:, force_http2: true) ⇒ RendererHttpClient
constructor
A new instance of RendererHttpClient.
-
#post(path, form: nil, json: nil, raw: nil, stream: false) ⇒ Object
-
#post_bidi(path, headers:) ⇒ [untyped, Response]
Bidirectional streaming POST.
Constructor Details
#initialize(origin:, pool_size:, connect_timeout:, read_timeout:, force_http2: true) ⇒ RendererHttpClient
Returns a new instance of RendererHttpClient.
605
606
607
608
609
610
611
612
613
614
615
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 605
def initialize(origin:, pool_size:, connect_timeout:, read_timeout:, force_http2: true)
@origin = origin
@pool_size = pool_size
@connect_timeout = connect_timeout
@read_timeout = read_timeout
@force_h2c = force_http2 && URI.parse(origin).scheme == "http"
@thread_clients = {}.compare_by_identity
@thread_clients_mutex = Mutex.new
@closed = false
@closed_mutex = Mutex.new
end
|
Class Method Details
.build_form_body(form) ⇒ [Array[[String, String]], MultipartBody | String]
546
547
548
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 546
def build_form_body(form)
build_multipart_body(form)
end
|
.build_multipart_body(form, boundary: SecureRandom.hex(24)) ⇒ Object
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 529
def build_multipart_body(form, boundary: SecureRandom.hex(24))
raise ArgumentError, "boundary must not contain '--'" if boundary.include?("--")
body = MultipartBody.new
form.each do |name, value|
append_multipart_value(body, boundary, name, value)
end
body << "--#{boundary}--\r\n"
[
[["content-type", "multipart/form-data; boundary=#{boundary}"]],
body
]
end
|
.bump_client_generation ⇒ Integer
523
524
525
526
527
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 523
def bump_client_generation
CLIENT_GENERATION_MUTEX.synchronize do
@client_generation = (@client_generation || 0) + 1
end
end
|
.client_generation ⇒ Integer
517
518
519
520
521
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 517
def client_generation
CLIENT_GENERATION_MUTEX.synchronize do
@client_generation ||= 0
end
end
|
.get(url, connect_timeout:, read_timeout:) ⇒ Response
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 492
def get(url, connect_timeout:, read_timeout:)
origin, path = split_url(url)
client = new(
origin:,
pool_size: 1,
connect_timeout:,
read_timeout:,
force_http2: false
)
response = client.get(path)
response.body
response
ensure
client&.close
end
|
.split_url(url) ⇒ [String, String]
509
510
511
512
513
514
515
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 509
def split_url(url)
uri = URI.parse(url)
port = uri.port unless uri.default_port == uri.port
origin = "#{uri.scheme}://#{uri.host}#{":#{port}" if port}"
[origin, uri.request_uri]
end
|
.transport_config_description ⇒ String
Instance Method Details
#close ⇒ nil
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 660
def close
return unless mark_closed
close_error = nil
scheduler = Fiber.scheduler
begin
evict_client_from_scheduler(scheduler) if scheduler
rescue StandardError => e
close_error ||= e
end
begin
close_thread_clients
rescue StandardError => e
close_error ||= e
end
raise close_error if close_error
end
|
629
630
631
632
633
634
635
636
637
638
639
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 629
def get(path)
ensure_open!
= []
parent_context = ReactOnRailsPro::OpenTelemetry.capture_context
build_response(stream: false) do |yielder, status_assigner, |
execute_request_with_trace(:get, path, [, nil],
stream: false,
response_handlers: [yielder, status_assigner, ],
parent_context:)
end
end
|
#post(path, form: nil, json: nil, raw: nil, stream: false) ⇒ Object
617
618
619
620
621
622
623
624
625
626
627
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 617
def post(path, form: nil, json: nil, raw: nil, stream: false)
ensure_open!
, body = request_body(form:, json:, raw:)
parent_context = ReactOnRailsPro::OpenTelemetry.capture_context
build_response(stream:) do |yielder, status_assigner, |
execute_request_with_trace(:post, path, [, body],
stream:,
response_handlers: [yielder, status_assigner, ],
parent_context:)
end
end
|
#post_bidi(path, headers:) ⇒ [untyped, Response]
Bidirectional streaming POST. Returns [output, response] where:
- output is a Protocol::HTTP::Body::Writable::Output (supports << and close)
- response is a lazy Response whose body is consumed via Response#each
The caller writes NDJSON lines to output while concurrently reading response
chunks. Calling output.close signals request-body EOF to the selected transport.
647
648
649
650
651
652
653
654
655
656
657
658
|
# File 'lib/react_on_rails_pro/renderer_http_client.rb', line 647
def post_bidi(path, headers:)
ensure_open!
writable = WritableBody.new
parent_context = ReactOnRailsPro::OpenTelemetry.capture_context
response = build_response(stream: true) do |yielder, status_assigner, |
execute_request_with_trace(:post, path, [, writable],
stream: true,
response_handlers: [yielder, status_assigner, ],
parent_context:)
end
[writable.output, response]
end
|