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 +4 -4
- data/Gemfile.lock +3 -3
- data/app/helpers/react_on_rails_pro_helper.rb +4 -1
- data/lib/react_on_rails_pro/configuration.rb +39 -8
- data/lib/react_on_rails_pro/constants.rb +2 -0
- data/lib/react_on_rails_pro/request.rb +4 -3
- data/lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb +3 -2
- data/lib/react_on_rails_pro/stream_request.rb +4 -0
- data/lib/react_on_rails_pro/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 91309f642414eae0ab09407243def617e7f32b2b9db0d0b62b108984d31b41e0
|
|
4
|
+
data.tar.gz: 1dec0600d12b121c3bbe62390a0c36124efed1fe40a5a53b0485d6b74e764a25
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
|
77
|
+
when ReactOnRailsPro::STATUS_BAD_REQUEST
|
|
78
78
|
raise ReactOnRailsPro::Error,
|
|
79
|
-
"Renderer
|
|
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
|
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
|
|
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-
|
|
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
|
|
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
|
|
138
|
+
version: 16.6.0
|
|
139
139
|
- !ruby/object:Gem::Dependency
|
|
140
140
|
name: bundler
|
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|