react_on_rails_pro 16.6.0.rc.0 → 16.6.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: f373b7e8f1b22b6a346f76eee9e85bf438104439a5d6250ccd8be773cbbdf86d
4
- data.tar.gz: a846f06b5f699c0bf61404237593be4d72e105cec55a152a77ecc80de549efd0
3
+ metadata.gz: 91309f642414eae0ab09407243def617e7f32b2b9db0d0b62b108984d31b41e0
4
+ data.tar.gz: 1dec0600d12b121c3bbe62390a0c36124efed1fe40a5a53b0485d6b74e764a25
5
5
  SHA512:
6
- metadata.gz: b97234a2ae969d0625912780700bffebe01268b7c183b70b56d1707dd6f0ce012f2b7b8d3ab71315d5667bacbb71188c67bad93715a3171cf063b7a0dbc2d340
7
- data.tar.gz: 9433436cd0acf2c2c8a523972946010aa3dc5905d7efc980ce7586bb70bf77b5535deab295f9a5b2fe917c26eca13ce4367dd109184c9df2154c0fab6258c28a
6
+ metadata.gz: 32a8382d7d10c90e475ebcd76607e6716b1e73766c228bb43362a33ca8223efd9cd5470a1c012cc82ec1c957356047351c35e988daed3f27e1a552cde7108a32
7
+ data.tar.gz: 7096efd3fb7dfe712b14f116977b9827594ae7b6505e90842f5d2213c564efc67a890fa7051c53c4373a10e303e35adee23dc27caf95f0cd68e91c70de1d57de
data/Gemfile.lock CHANGED
@@ -9,7 +9,7 @@ GIT
9
9
  PATH
10
10
  remote: ..
11
11
  specs:
12
- react_on_rails (16.6.0.rc.0)
12
+ react_on_rails (16.6.0)
13
13
  addressable
14
14
  connection_pool
15
15
  execjs (~> 2.5)
@@ -20,7 +20,7 @@ PATH
20
20
  PATH
21
21
  remote: .
22
22
  specs:
23
- react_on_rails_pro (16.6.0.rc.0)
23
+ react_on_rails_pro (16.6.0)
24
24
  addressable
25
25
  async (>= 2.29)
26
26
  connection_pool
@@ -29,7 +29,7 @@ PATH
29
29
  httpx (~> 1.5)
30
30
  jwt (~> 2.7)
31
31
  rainbow
32
- react_on_rails (= 16.6.0.rc.0)
32
+ react_on_rails (= 16.6.0)
33
33
 
34
34
  GEM
35
35
  remote: https://rubygems.org/
@@ -128,7 +128,10 @@ module ReactOnRailsProHelper
128
128
  # stream_react_component doesn't have the prerender option
129
129
  # Because setting prerender to false is equivalent to calling react_component with prerender: false
130
130
  options[:prerender] = true
131
- options = options.merge(immediate_hydration: true) unless options.key?(:immediate_hydration)
131
+ if options.key?(:immediate_hydration)
132
+ ReactOnRails::Helper.warn_removed_immediate_hydration_option("stream_react_component")
133
+ options.delete(:immediate_hydration)
134
+ end
132
135
 
133
136
  # Extract streaming-specific callback
134
137
  on_complete = options.delete(:on_complete)
@@ -15,6 +15,7 @@ module ReactOnRailsPro
15
15
  renderer_http_pool_size: Configuration::DEFAULT_RENDERER_HTTP_POOL_SIZE,
16
16
  renderer_http_pool_timeout: Configuration::DEFAULT_RENDERER_HTTP_POOL_TIMEOUT,
17
17
  renderer_http_pool_warn_timeout: Configuration::DEFAULT_RENDERER_HTTP_POOL_WARN_TIMEOUT,
18
+ renderer_http_keep_alive_timeout: Configuration::DEFAULT_RENDERER_HTTP_KEEP_ALIVE_TIMEOUT,
18
19
  renderer_password: nil,
19
20
  tracing: Configuration::DEFAULT_TRACING,
20
21
  dependency_globs: Configuration::DEFAULT_DEPENDENCY_GLOBS,
@@ -44,6 +45,7 @@ module ReactOnRailsPro
44
45
  DEFAULT_RENDERER_HTTP_POOL_SIZE = 10
45
46
  DEFAULT_RENDERER_HTTP_POOL_TIMEOUT = 5
46
47
  DEFAULT_RENDERER_HTTP_POOL_WARN_TIMEOUT = 0.25
48
+ DEFAULT_RENDERER_HTTP_KEEP_ALIVE_TIMEOUT = 30
47
49
  DEFAULT_SSR_TIMEOUT = 5
48
50
  DEFAULT_PRERENDER_CACHING = false
49
51
  DEFAULT_TRACING = false
@@ -72,7 +74,7 @@ module ReactOnRailsPro
72
74
  :rsc_payload_generation_url_path, :rsc_bundle_js_file, :react_client_manifest_file,
73
75
  :react_server_client_manifest_file
74
76
 
75
- attr_reader :concurrent_component_streaming_buffer_size
77
+ attr_reader :concurrent_component_streaming_buffer_size, :renderer_http_keep_alive_timeout
76
78
 
77
79
  # Sets the buffer size for concurrent component streaming.
78
80
  #
@@ -91,10 +93,28 @@ module ReactOnRailsPro
91
93
  @concurrent_component_streaming_buffer_size = value
92
94
  end
93
95
 
96
+ # Sets the keep-alive timeout (in seconds) for persistent HTTP connections to the node renderer.
97
+ #
98
+ # For best results, set this value to slightly less than the node renderer's own
99
+ # keep-alive / idle-connection timeout. If the client-side timeout is longer than
100
+ # the server's, connections may be reused after the server has already closed them,
101
+ # resulting in stale-connection errors. If set to nil, the HTTPX default is used.
102
+ #
103
+ # @param value [Numeric, nil] A positive number or nil (to use the HTTPX default)
104
+ # @raise [ReactOnRailsPro::Error] if value is not a positive number or nil
105
+ def renderer_http_keep_alive_timeout=(value)
106
+ unless value.nil? || (value.is_a?(Numeric) && value.positive? && value.finite?)
107
+ raise ReactOnRailsPro::Error,
108
+ "config.renderer_http_keep_alive_timeout must be a finite positive number or nil"
109
+ end
110
+ @renderer_http_keep_alive_timeout = value
111
+ end
112
+
94
113
  def initialize(renderer_url: nil, renderer_password: nil, server_renderer: nil, # rubocop:disable Metrics/AbcSize
95
114
  renderer_use_fallback_exec_js: nil, prerender_caching: nil,
96
115
  renderer_http_pool_size: nil, renderer_http_pool_timeout: nil,
97
- renderer_http_pool_warn_timeout: nil, tracing: nil,
116
+ renderer_http_pool_warn_timeout: nil, renderer_http_keep_alive_timeout: nil,
117
+ tracing: nil,
98
118
  dependency_globs: nil, excluded_dependency_globs: nil, rendering_returns_promises: nil,
99
119
  remote_bundle_cache_adapter: nil, ssr_pre_hook_js: nil, assets_to_copy: nil,
100
120
  renderer_request_retry_limit: nil, throw_js_errors: nil, ssr_timeout: nil,
@@ -111,6 +131,7 @@ module ReactOnRailsPro
111
131
  self.renderer_http_pool_size = renderer_http_pool_size
112
132
  self.renderer_http_pool_timeout = renderer_http_pool_timeout
113
133
  self.renderer_http_pool_warn_timeout = renderer_http_pool_warn_timeout
134
+ self.renderer_http_keep_alive_timeout = renderer_http_keep_alive_timeout
114
135
  self.tracing = tracing
115
136
  self.rendering_returns_promises = server_renderer == "NodeRenderer" ? rendering_returns_promises : false
116
137
  self.dependency_globs = dependency_globs
@@ -230,12 +251,16 @@ module ReactOnRailsPro
230
251
 
231
252
  def setup_renderer_password
232
253
  # Explicit passwords, including values loaded from ENV in the initializer, skip URL extraction.
233
- # Blank values fall through so URL extraction and production validation still catch misconfiguration.
254
+ # Blank values (nil or "") fall through so URL extraction and ENV fallback still apply.
234
255
  return if renderer_password.present?
235
256
 
236
257
  uri = URI(renderer_url)
237
258
  self.renderer_password = uri.password
238
259
 
260
+ # Mirror Node-side defaults: if Rails config and URL are both missing a password,
261
+ # use RENDERER_PASSWORD from env.
262
+ self.renderer_password = ENV.fetch("RENDERER_PASSWORD", nil) if renderer_password.blank?
263
+
239
264
  validate_renderer_password_for_production
240
265
  end
241
266
 
@@ -260,17 +285,23 @@ module ReactOnRailsPro
260
285
  is required. In all other environments, you must explicitly configure a password to secure
261
286
  communication between Rails and the Node Renderer.
262
287
 
263
- To fix this, set the RENDERER_PASSWORD environment variable and configure it in your initializer:
288
+ To fix this, set the RENDERER_PASSWORD environment variable:
289
+
290
+ export RENDERER_PASSWORD="your-secure-password"
291
+
292
+ Rails reads it automatically. If you prefer to make it explicit in your initializer:
264
293
 
265
294
  # config/initializers/react_on_rails_pro.rb
266
295
  ReactOnRailsPro.configure do |config|
267
296
  config.renderer_password = ENV.fetch("RENDERER_PASSWORD")
268
297
  end
269
298
 
270
- Then set the same password for the Node Renderer via the RENDERER_PASSWORD environment variable.
271
- Note: setting ENV["RENDERER_PASSWORD"] alone is not enough on the Ruby side unless
272
- config.renderer_password is explicitly assigned from ENV.
273
- An empty-string assignment still counts as missing and will raise in production-like environments.
299
+ Set the same password for the Node Renderer via the RENDERER_PASSWORD environment variable.
300
+ Rails resolves the password in this order:
301
+ 1) config.renderer_password (blank values fall through to the next step)
302
+ 2) Password embedded in config.renderer_url (for example, https://:password@host:3800)
303
+ 3) ENV["RENDERER_PASSWORD"]
304
+
274
305
  If Rails and the Node Renderer disagree about startup behavior, verify both RAILS_ENV and NODE_ENV.
275
306
 
276
307
  Environment matrix:
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReactOnRailsPro
4
+ # Status code 400 indicates the renderer rejected the request payload or encountered an unhandled render error.
5
+ STATUS_BAD_REQUEST = 400
4
6
  # Status code 410 means to resend the request with the updated bundle.
5
7
  STATUS_SEND_BUNDLE = 410
6
8
  # Status code 412 means protocol versions are incompatible between the server and the renderer.
@@ -297,11 +297,11 @@ module ReactOnRailsPro
297
297
  # :write_timeout
298
298
  # :request_timeout
299
299
  # :operation_timeout
300
- # :keep_alive_timeout
301
300
  timeout: {
302
301
  connect_timeout: ReactOnRailsPro.configuration.renderer_http_pool_timeout,
303
- read_timeout: ReactOnRailsPro.configuration.ssr_timeout
304
- }
302
+ read_timeout: ReactOnRailsPro.configuration.ssr_timeout,
303
+ keep_alive_timeout: ReactOnRailsPro.configuration.renderer_http_keep_alive_timeout
304
+ }.compact
305
305
  )
306
306
  rescue StandardError => e
307
307
  message = <<~MSG
@@ -309,6 +309,7 @@ module ReactOnRailsPro
309
309
  renderer_http_pool_size = #{ReactOnRailsPro.configuration.renderer_http_pool_size}
310
310
  renderer_http_pool_timeout = #{ReactOnRailsPro.configuration.renderer_http_pool_timeout}
311
311
  renderer_http_pool_warn_timeout = #{ReactOnRailsPro.configuration.renderer_http_pool_warn_timeout}
312
+ renderer_http_keep_alive_timeout = #{ReactOnRailsPro.configuration.renderer_http_keep_alive_timeout}
312
313
  renderer_url = #{url}
313
314
  Be sure to use a url that contains the protocol of http or https.
314
315
  Original error is
@@ -74,9 +74,10 @@ module ReactOnRailsPro
74
74
  ReactOnRailsPro::Error.raise_duplicate_bundle_upload_error if send_bundle
75
75
 
76
76
  eval_js(js_code, render_options, send_bundle: true)
77
- when 400
77
+ when ReactOnRailsPro::STATUS_BAD_REQUEST
78
78
  raise ReactOnRailsPro::Error,
79
- "Renderer unhandled error at the VM level: #{response.status}:\n#{response.body}"
79
+ "Renderer rejected malformed request or hit an unhandled VM error: " \
80
+ "#{response.status}:\n#{response.body}"
80
81
  else
81
82
  raise ReactOnRailsPro::Error,
82
83
  "Unexpected response code from renderer: #{response.status}:\n#{response.body}"
@@ -140,6 +140,10 @@ module ReactOnRailsPro
140
140
  ReactOnRailsPro::Error.raise_duplicate_bundle_upload_error if send_bundle
141
141
 
142
142
  true
143
+ when ReactOnRailsPro::STATUS_BAD_REQUEST
144
+ raise ReactOnRailsPro::Error,
145
+ "Renderer rejected malformed request or hit an unhandled VM error: " \
146
+ "#{response.status}:\n#{error_body}"
143
147
  when ReactOnRailsPro::STATUS_INCOMPATIBLE
144
148
  raise ReactOnRailsPro::Error, error_body
145
149
  else
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReactOnRailsPro
4
- VERSION = "16.6.0.rc.0"
4
+ VERSION = "16.6.0"
5
5
  PROTOCOL_VERSION = "2.0.0"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: react_on_rails_pro
3
3
  version: !ruby/object:Gem::Version
4
- version: 16.6.0.rc.0
4
+ version: 16.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Gordon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-04-02 00:00:00.000000000 Z
11
+ date: 2026-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - '='
130
130
  - !ruby/object:Gem::Version
131
- version: 16.6.0.rc.0
131
+ version: 16.6.0
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - '='
137
137
  - !ruby/object:Gem::Version
138
- version: 16.6.0.rc.0
138
+ version: 16.6.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: bundler
141
141
  requirement: !ruby/object:Gem::Requirement