react-on-rails-pro-node-renderer 16.7.0-rc.3 → 17.0.0-rc.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.
- package/README.md +1 -1
- package/lib/integrations/api.d.ts +4 -2
- package/lib/integrations/api.js +10 -1
- package/lib/integrations/opentelemetry.js +14 -24
- package/lib/shared/configBuilder.js +33 -24
- package/lib/shared/opentelemetryState.d.ts +7 -0
- package/lib/shared/opentelemetryState.js +7 -0
- package/lib/shared/sensitiveKeys.d.ts +3 -0
- package/lib/shared/sensitiveKeys.js +24 -0
- package/lib/shared/tracing.d.ts +8 -2
- package/lib/shared/tracing.js +8 -2
- package/lib/worker/checkProtocolVersionHandler.js +2 -1
- package/lib/worker.js +2 -17
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ reactOnRailsProNodeRenderer({
|
|
|
53
53
|
ReactOnRailsPro.configure do |config|
|
|
54
54
|
config.server_renderer = "NodeRenderer"
|
|
55
55
|
config.renderer_url = ENV.fetch("REACT_RENDERER_URL", "http://localhost:3800")
|
|
56
|
-
config.renderer_password = ENV
|
|
56
|
+
config.renderer_password = ENV["RENDERER_PASSWORD"]
|
|
57
57
|
end
|
|
58
58
|
```
|
|
59
59
|
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
*/
|
|
25
25
|
export { default as log } from '../shared/log.js';
|
|
26
26
|
export { addErrorNotifier, addMessageNotifier, addNotifier, error, message, Notifier, ErrorNotifier, MessageNotifier, } from '../shared/errorReporter.js';
|
|
27
|
-
export { setupTracing, setupSubSpan, subSpan, TracingContext, TracingIntegrationOptions, UnitOfWorkOptions, SubSpanOptions, SubSpanFn, SubSpanController, } from '../shared/tracing.js';
|
|
28
|
-
export {
|
|
27
|
+
export { resetTracing, resetSubSpan, setupTracing, setupSubSpan, subSpan, TracingContext, TracingIntegrationOptions, UnitOfWorkOptions, SubSpanOptions, SubSpanFn, SubSpanController, } from '../shared/tracing.js';
|
|
28
|
+
export { getOpenTelemetryTracerProvider, setOpenTelemetryTracerProvider, } from '../shared/opentelemetryState.js';
|
|
29
|
+
export { configureFastify, registerFastifyConfigFunction, FastifyConfigFunction, } from '../worker/fastifyConfig.js';
|
|
30
|
+
export { registerWorkerShutdownHook, WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS, WorkerShutdownHook, } from '../worker/shutdownHooks.js';
|
|
29
31
|
//# sourceMappingURL=api.d.ts.map
|
package/lib/integrations/api.js
CHANGED
|
@@ -27,7 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
28
|
};
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.configureFastify = exports.subSpan = exports.setupSubSpan = exports.setupTracing = exports.message = exports.error = exports.addNotifier = exports.addMessageNotifier = exports.addErrorNotifier = exports.log = void 0;
|
|
30
|
+
exports.WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS = exports.registerWorkerShutdownHook = exports.registerFastifyConfigFunction = exports.configureFastify = exports.setOpenTelemetryTracerProvider = exports.getOpenTelemetryTracerProvider = exports.subSpan = exports.setupSubSpan = exports.setupTracing = exports.resetSubSpan = exports.resetTracing = exports.message = exports.error = exports.addNotifier = exports.addMessageNotifier = exports.addErrorNotifier = exports.log = void 0;
|
|
31
31
|
var log_js_1 = require("../shared/log.js");
|
|
32
32
|
Object.defineProperty(exports, "log", { enumerable: true, get: function () { return __importDefault(log_js_1).default; } });
|
|
33
33
|
var errorReporter_js_1 = require("../shared/errorReporter.js");
|
|
@@ -37,9 +37,18 @@ Object.defineProperty(exports, "addNotifier", { enumerable: true, get: function
|
|
|
37
37
|
Object.defineProperty(exports, "error", { enumerable: true, get: function () { return errorReporter_js_1.error; } });
|
|
38
38
|
Object.defineProperty(exports, "message", { enumerable: true, get: function () { return errorReporter_js_1.message; } });
|
|
39
39
|
var tracing_js_1 = require("../shared/tracing.js");
|
|
40
|
+
Object.defineProperty(exports, "resetTracing", { enumerable: true, get: function () { return tracing_js_1.resetTracing; } });
|
|
41
|
+
Object.defineProperty(exports, "resetSubSpan", { enumerable: true, get: function () { return tracing_js_1.resetSubSpan; } });
|
|
40
42
|
Object.defineProperty(exports, "setupTracing", { enumerable: true, get: function () { return tracing_js_1.setupTracing; } });
|
|
41
43
|
Object.defineProperty(exports, "setupSubSpan", { enumerable: true, get: function () { return tracing_js_1.setupSubSpan; } });
|
|
42
44
|
Object.defineProperty(exports, "subSpan", { enumerable: true, get: function () { return tracing_js_1.subSpan; } });
|
|
45
|
+
var opentelemetryState_js_1 = require("../shared/opentelemetryState.js");
|
|
46
|
+
Object.defineProperty(exports, "getOpenTelemetryTracerProvider", { enumerable: true, get: function () { return opentelemetryState_js_1.getOpenTelemetryTracerProvider; } });
|
|
47
|
+
Object.defineProperty(exports, "setOpenTelemetryTracerProvider", { enumerable: true, get: function () { return opentelemetryState_js_1.setOpenTelemetryTracerProvider; } });
|
|
43
48
|
var fastifyConfig_js_1 = require("../worker/fastifyConfig.js");
|
|
44
49
|
Object.defineProperty(exports, "configureFastify", { enumerable: true, get: function () { return fastifyConfig_js_1.configureFastify; } });
|
|
50
|
+
Object.defineProperty(exports, "registerFastifyConfigFunction", { enumerable: true, get: function () { return fastifyConfig_js_1.registerFastifyConfigFunction; } });
|
|
51
|
+
var shutdownHooks_js_1 = require("../worker/shutdownHooks.js");
|
|
52
|
+
Object.defineProperty(exports, "registerWorkerShutdownHook", { enumerable: true, get: function () { return shutdownHooks_js_1.registerWorkerShutdownHook; } });
|
|
53
|
+
Object.defineProperty(exports, "WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS", { enumerable: true, get: function () { return shutdownHooks_js_1.WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS; } });
|
|
45
54
|
//# sourceMappingURL=api.js.map
|
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.init = init;
|
|
4
|
-
/* eslint-disable no-restricted-imports --
|
|
5
|
-
* This integration needs internal worker/shared modules that the public
|
|
6
|
-
* api.ts does not yet re-export (tracing adapter slots, OTel global state,
|
|
7
|
-
* fastify config + worker shutdown hook registration). Tracked in #3419
|
|
8
|
-
* — once api.ts surfaces these, remove this disable. */
|
|
9
|
-
const tracing_js_1 = require("../shared/tracing.js");
|
|
10
|
-
const opentelemetryState_js_1 = require("../shared/opentelemetryState.js");
|
|
11
|
-
const fastifyConfig_js_1 = require("../worker/fastifyConfig.js");
|
|
12
|
-
const shutdownHooks_js_1 = require("../worker/shutdownHooks.js");
|
|
13
|
-
/* eslint-enable no-restricted-imports */
|
|
14
4
|
const api_js_1 = require("./api.js");
|
|
15
5
|
const DEFAULT_SERVICE_NAME = 'react-on-rails-pro-node-renderer';
|
|
16
6
|
const DEFAULT_SHUTDOWN_TIMEOUT_MS = 5000;
|
|
17
7
|
// Leave 1s of headroom under the worker's hard cap so the shutdown hook can
|
|
18
8
|
// resolve cleanly even when provider.shutdown() runs right at its limit.
|
|
19
|
-
const MAX_SHUTDOWN_TIMEOUT_MS =
|
|
9
|
+
const MAX_SHUTDOWN_TIMEOUT_MS = api_js_1.WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS - 1000;
|
|
20
10
|
function isProduction() {
|
|
21
11
|
return process.env.NODE_ENV === 'production' || process.env.RAILS_ENV === 'production';
|
|
22
12
|
}
|
|
@@ -32,7 +22,7 @@ function resolveShutdownTimeoutMs(opts) {
|
|
|
32
22
|
return DEFAULT_SHUTDOWN_TIMEOUT_MS;
|
|
33
23
|
}
|
|
34
24
|
if (requested > MAX_SHUTDOWN_TIMEOUT_MS) {
|
|
35
|
-
api_js_1.log.warn('[OpenTelemetry] shutdownTimeoutMs=%dms exceeds worker shutdown hook cap (%dms); capping to %dms so the hook can resolve before the worker is forcibly destroyed.', requested,
|
|
25
|
+
api_js_1.log.warn('[OpenTelemetry] shutdownTimeoutMs=%dms exceeds worker shutdown hook cap (%dms); capping to %dms so the hook can resolve before the worker is forcibly destroyed.', requested, api_js_1.WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS, MAX_SHUTDOWN_TIMEOUT_MS);
|
|
36
26
|
return MAX_SHUTDOWN_TIMEOUT_MS;
|
|
37
27
|
}
|
|
38
28
|
return requested;
|
|
@@ -78,10 +68,10 @@ function disableOpenTelemetryGlobals(otelApi) {
|
|
|
78
68
|
}
|
|
79
69
|
function resetInstalledTracingAdapters(installedAdapters) {
|
|
80
70
|
if (installedAdapters.subSpan) {
|
|
81
|
-
(0,
|
|
71
|
+
(0, api_js_1.resetSubSpan)();
|
|
82
72
|
}
|
|
83
73
|
if (installedAdapters.tracing) {
|
|
84
|
-
(0,
|
|
74
|
+
(0, api_js_1.resetTracing)();
|
|
85
75
|
}
|
|
86
76
|
return { tracing: false, subSpan: false };
|
|
87
77
|
}
|
|
@@ -115,7 +105,7 @@ async function shutdownProviderWithTimeout(provider, shutdownTimeoutMs) {
|
|
|
115
105
|
}
|
|
116
106
|
}
|
|
117
107
|
function init(opts = {}) {
|
|
118
|
-
if ((0,
|
|
108
|
+
if ((0, api_js_1.getOpenTelemetryTracerProvider)()) {
|
|
119
109
|
(0, api_js_1.message)('[OpenTelemetry] init() called more than once; ignoring duplicate call.');
|
|
120
110
|
return;
|
|
121
111
|
}
|
|
@@ -179,7 +169,7 @@ function init(opts = {}) {
|
|
|
179
169
|
// reference) correctly disables the globals if register() throws.
|
|
180
170
|
ownsOpenTelemetryGlobals = true;
|
|
181
171
|
registeredProvider = provider;
|
|
182
|
-
(0,
|
|
172
|
+
(0, api_js_1.setOpenTelemetryTracerProvider)(provider);
|
|
183
173
|
// Re-call provider.register() to set context manager + propagator globals.
|
|
184
174
|
// The second setGlobalTracerProvider() call inside register() is a no-op
|
|
185
175
|
// (registerGlobal returns false because the proxy is already owned by us),
|
|
@@ -205,7 +195,7 @@ function init(opts = {}) {
|
|
|
205
195
|
}
|
|
206
196
|
if (opts.tracing) {
|
|
207
197
|
const tracer = loadedOtelApi.trace.getTracer(serviceName);
|
|
208
|
-
installedAdapters.tracing = (0,
|
|
198
|
+
installedAdapters.tracing = (0, api_js_1.setupTracing)({
|
|
209
199
|
startSsrRequestOptions: () => ({
|
|
210
200
|
// Keep the root span free of request payload data. Future safe
|
|
211
201
|
// attributes should be derived from structured metadata supplied by
|
|
@@ -252,7 +242,7 @@ function init(opts = {}) {
|
|
|
252
242
|
span.end();
|
|
253
243
|
}
|
|
254
244
|
});
|
|
255
|
-
installedAdapters.subSpan = (0,
|
|
245
|
+
installedAdapters.subSpan = (0, api_js_1.setupSubSpan)(subSpanImpl);
|
|
256
246
|
}
|
|
257
247
|
else {
|
|
258
248
|
(0, api_js_1.message)('[OpenTelemetry] tracing integration was not installed because another tracing integration is ' +
|
|
@@ -264,8 +254,8 @@ function init(opts = {}) {
|
|
|
264
254
|
shutdownOpenTelemetryPromise ?? (shutdownOpenTelemetryPromise = (async () => {
|
|
265
255
|
try {
|
|
266
256
|
await shutdownProviderWithTimeout(provider, shutdownTimeoutMs);
|
|
267
|
-
if ((0,
|
|
268
|
-
(0,
|
|
257
|
+
if ((0, api_js_1.getOpenTelemetryTracerProvider)() === provider) {
|
|
258
|
+
(0, api_js_1.setOpenTelemetryTracerProvider)(null);
|
|
269
259
|
disableOpenTelemetryGlobals(loadedOtelApi);
|
|
270
260
|
ownsOpenTelemetryGlobals = false;
|
|
271
261
|
installedAdapters = resetInstalledTracingAdapters(installedAdapters);
|
|
@@ -281,8 +271,8 @@ function init(opts = {}) {
|
|
|
281
271
|
// Register these last so failed init paths do not leave partial shutdown hooks
|
|
282
272
|
// behind. The worker hook runs during cluster restarts, while Fastify onClose
|
|
283
273
|
// still handles explicit app.close() calls from tests or custom integrations.
|
|
284
|
-
unregisterWorkerShutdownHook = (0,
|
|
285
|
-
unregisterFastifyConfig = (0,
|
|
274
|
+
unregisterWorkerShutdownHook = (0, api_js_1.registerWorkerShutdownHook)(shutdownOpenTelemetry);
|
|
275
|
+
unregisterFastifyConfig = (0, api_js_1.registerFastifyConfigFunction)((app) => {
|
|
286
276
|
app.addHook('onClose', shutdownOpenTelemetry);
|
|
287
277
|
});
|
|
288
278
|
api_js_1.log.info('[OpenTelemetry] Tracer provider initialized');
|
|
@@ -293,8 +283,8 @@ function init(opts = {}) {
|
|
|
293
283
|
if (ownsOpenTelemetryGlobals &&
|
|
294
284
|
registeredProvider &&
|
|
295
285
|
otelApi &&
|
|
296
|
-
(0,
|
|
297
|
-
(0,
|
|
286
|
+
(0, api_js_1.getOpenTelemetryTracerProvider)() === registeredProvider) {
|
|
287
|
+
(0, api_js_1.setOpenTelemetryTracerProvider)(null);
|
|
298
288
|
disableOpenTelemetryGlobals(otelApi);
|
|
299
289
|
ownsOpenTelemetryGlobals = false;
|
|
300
290
|
}
|
|
@@ -181,32 +181,41 @@ function logSanitizedConfig() {
|
|
|
181
181
|
'Final renderer settings': sanitizedSettings(config, '<NOT PROVIDED>'),
|
|
182
182
|
});
|
|
183
183
|
}
|
|
184
|
+
const KNOWN_WEAK_PASSWORDS = new Set(['devPassword', 'myPassword1', 'password', 'changeme', 'admin', 'secret', 'test', 'renderer'].map((p) => p.toLowerCase()));
|
|
185
|
+
const MIN_PASSWORD_LENGTH = 16;
|
|
184
186
|
function validatePasswordForProduction(aConfig) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
187
|
+
const isProductionLike = !runtimeEnvsAllowDevelopmentDefaults();
|
|
188
|
+
if (!aConfig.password || aConfig.password.trim() === '') {
|
|
189
|
+
if (isProductionLike) {
|
|
190
|
+
return ('RENDERER_PASSWORD must be set in production-like environments ' +
|
|
191
|
+
`(NODE_ENV: "${env.NODE_ENV ?? '(not set)'}", RAILS_ENV: "${env.RAILS_ENV ?? '(not set)'}").` +
|
|
192
|
+
'\n\n' +
|
|
193
|
+
'In development and test environments, the renderer password is optional and no authentication\n' +
|
|
194
|
+
'is required. In all other environments, you must explicitly configure a password to secure\n' +
|
|
195
|
+
'communication between Rails and the Node Renderer.\n\n' +
|
|
196
|
+
'To fix this, set the RENDERER_PASSWORD environment variable:\n\n' +
|
|
197
|
+
' export RENDERER_PASSWORD="your-secure-password"\n\n' +
|
|
198
|
+
'Or pass it in the config object:\n\n' +
|
|
199
|
+
' reactOnRailsProNodeRenderer({ password: process.env.RENDERER_PASSWORD });\n\n' +
|
|
200
|
+
'Environment matrix:\n' +
|
|
201
|
+
' development — password optional (no authentication)\n' +
|
|
202
|
+
' test — password optional (no authentication)\n' +
|
|
203
|
+
' (neither set) — treated as production-like; RENDERER_PASSWORD required\n' +
|
|
204
|
+
' all other environments (staging, production, qa, preview, etc.) — RENDERER_PASSWORD required');
|
|
205
|
+
}
|
|
194
206
|
return null;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
'
|
|
198
|
-
|
|
199
|
-
'
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
' test — password optional (no authentication)\n' +
|
|
208
|
-
' (neither set) — treated as production-like; RENDERER_PASSWORD required\n' +
|
|
209
|
-
' all other environments (staging, production, qa, preview, etc.) — RENDERER_PASSWORD required');
|
|
207
|
+
}
|
|
208
|
+
if (KNOWN_WEAK_PASSWORDS.has(aConfig.password.toLowerCase())) {
|
|
209
|
+
// Don't log the literal value — even a known-default value is the user's
|
|
210
|
+
// *current* live credential until they rotate it.
|
|
211
|
+
log_js_1.default.warn('RENDERER_PASSWORD matches a known-default value. ' +
|
|
212
|
+
`Set RENDERER_PASSWORD to a random value of at least ${MIN_PASSWORD_LENGTH} characters.`);
|
|
213
|
+
}
|
|
214
|
+
else if (aConfig.password.length < MIN_PASSWORD_LENGTH) {
|
|
215
|
+
log_js_1.default.warn(`RENDERER_PASSWORD is shorter than ${MIN_PASSWORD_LENGTH} characters (current length: ${aConfig.password.length}). ` +
|
|
216
|
+
'Consider using a stronger password.');
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
210
219
|
}
|
|
211
220
|
/**
|
|
212
221
|
* Lazily create the config.
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import type { NodeTracerProvider as NodeTracerProviderType } from '@opentelemetry/sdk-trace-node';
|
|
2
2
|
export declare function getOpenTelemetryTracerProvider(): NodeTracerProviderType | null;
|
|
3
|
+
/**
|
|
4
|
+
* Updates the process-global OpenTelemetry provider reference.
|
|
5
|
+
*
|
|
6
|
+
* Caller contract: only integrations that own the OpenTelemetry init/shutdown
|
|
7
|
+
* lifecycle should call this, and the value must mirror that lifecycle's
|
|
8
|
+
* current provider ownership.
|
|
9
|
+
*/
|
|
3
10
|
export declare function setOpenTelemetryTracerProvider(provider: NodeTracerProviderType | null): void;
|
|
4
11
|
//# sourceMappingURL=opentelemetryState.d.ts.map
|
|
@@ -6,6 +6,13 @@ let tracerProvider = null;
|
|
|
6
6
|
function getOpenTelemetryTracerProvider() {
|
|
7
7
|
return tracerProvider;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Updates the process-global OpenTelemetry provider reference.
|
|
11
|
+
*
|
|
12
|
+
* Caller contract: only integrations that own the OpenTelemetry init/shutdown
|
|
13
|
+
* lifecycle should call this, and the value must mirror that lifecycle's
|
|
14
|
+
* current provider ownership.
|
|
15
|
+
*/
|
|
9
16
|
function setOpenTelemetryTracerProvider(provider) {
|
|
10
17
|
tracerProvider = provider;
|
|
11
18
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SENSITIVE_REQUEST_BODY_KEYS = void 0;
|
|
4
|
+
exports.sanitizeBodyKeys = sanitizeBodyKeys;
|
|
5
|
+
exports.SENSITIVE_REQUEST_BODY_KEYS = new Set([
|
|
6
|
+
'password',
|
|
7
|
+
'token',
|
|
8
|
+
'secret',
|
|
9
|
+
'api_key',
|
|
10
|
+
'api-key',
|
|
11
|
+
'apikey',
|
|
12
|
+
'authorization',
|
|
13
|
+
'auth_token',
|
|
14
|
+
'auth-token',
|
|
15
|
+
'authtoken',
|
|
16
|
+
'access_token',
|
|
17
|
+
'accesstoken',
|
|
18
|
+
'bearer',
|
|
19
|
+
'credentials',
|
|
20
|
+
]);
|
|
21
|
+
function sanitizeBodyKeys(body) {
|
|
22
|
+
return Object.keys(body).filter((key) => !exports.SENSITIVE_REQUEST_BODY_KEYS.has(key.toLowerCase()));
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=sensitiveKeys.js.map
|
package/lib/shared/tracing.d.ts
CHANGED
|
@@ -52,7 +52,10 @@ export declare function setupTracing(options: TracingIntegrationOptions): boolea
|
|
|
52
52
|
export declare function trace<T>(fn: UnitOfWork<T>, unitOfWorkOptions: UnitOfWorkOptions): Promise<T>;
|
|
53
53
|
/**
|
|
54
54
|
* Resets the installed tracing executor + startSsrRequestOptions back to
|
|
55
|
-
* defaults.
|
|
55
|
+
* defaults. Integrations use this during lifecycle teardown or failed initialization cleanup.
|
|
56
|
+
*
|
|
57
|
+
* Caller contract: only integrations that own the active tracing lifecycle
|
|
58
|
+
* should call this, and only while tearing that lifecycle down.
|
|
56
59
|
*/
|
|
57
60
|
export declare function resetTracing(): void;
|
|
58
61
|
/**
|
|
@@ -119,7 +122,10 @@ export declare function setupSubSpan(impl: SubSpanFn): boolean;
|
|
|
119
122
|
export declare function subSpan<T>(opts: SubSpanOptions, fn: (controller: SubSpanController) => Promise<T>): Promise<T>;
|
|
120
123
|
/**
|
|
121
124
|
* Resets the installed sub-span implementation back to the default pass-through.
|
|
122
|
-
*
|
|
125
|
+
* Integrations use this during lifecycle teardown or failed initialization cleanup.
|
|
126
|
+
*
|
|
127
|
+
* Caller contract: only integrations that own the active sub-span lifecycle
|
|
128
|
+
* should call this, and only while tearing that lifecycle down.
|
|
123
129
|
*/
|
|
124
130
|
export declare function resetSubSpan(): void;
|
|
125
131
|
/**
|
package/lib/shared/tracing.js
CHANGED
|
@@ -50,7 +50,10 @@ function trace(fn, unitOfWorkOptions) {
|
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
52
|
* Resets the installed tracing executor + startSsrRequestOptions back to
|
|
53
|
-
* defaults.
|
|
53
|
+
* defaults. Integrations use this during lifecycle teardown or failed initialization cleanup.
|
|
54
|
+
*
|
|
55
|
+
* Caller contract: only integrations that own the active tracing lifecycle
|
|
56
|
+
* should call this, and only while tearing that lifecycle down.
|
|
54
57
|
*/
|
|
55
58
|
function resetTracing() {
|
|
56
59
|
executor = (fn) => fn();
|
|
@@ -129,7 +132,10 @@ function subSpan(opts, fn) {
|
|
|
129
132
|
}
|
|
130
133
|
/**
|
|
131
134
|
* Resets the installed sub-span implementation back to the default pass-through.
|
|
132
|
-
*
|
|
135
|
+
* Integrations use this during lifecycle teardown or failed initialization cleanup.
|
|
136
|
+
*
|
|
137
|
+
* Caller contract: only integrations that own the active sub-span lifecycle
|
|
138
|
+
* should call this, and only while tearing that lifecycle down.
|
|
133
139
|
*/
|
|
134
140
|
function resetSubSpan() {
|
|
135
141
|
subSpanImpl = defaultSubSpan;
|
|
@@ -10,6 +10,7 @@ exports.checkProtocolVersion = checkProtocolVersion;
|
|
|
10
10
|
*/
|
|
11
11
|
const packageJson_js_1 = __importDefault(require("../shared/packageJson.js"));
|
|
12
12
|
const log_js_1 = __importDefault(require("../shared/log.js"));
|
|
13
|
+
const sensitiveKeys_js_1 = require("../shared/sensitiveKeys.js");
|
|
13
14
|
const NODE_ENV = process.env.NODE_ENV || 'production';
|
|
14
15
|
// Cache to store version comparison results to avoid repeated normalization and logging
|
|
15
16
|
// Key: gemVersion string, Value: boolean (true if matches, false if mismatch)
|
|
@@ -43,7 +44,7 @@ function checkProtocolVersion(body) {
|
|
|
43
44
|
status: 412,
|
|
44
45
|
data: `Unsupported renderer protocol version ${reqProtocolVersion
|
|
45
46
|
? `request protocol ${reqProtocolVersion}`
|
|
46
|
-
: `MISSING
|
|
47
|
+
: `MISSING (received fields: ${(0, sensitiveKeys_js_1.sanitizeBodyKeys)(body).join(', ') || '(none)'})`} does not match installed renderer protocol ${packageJson_js_1.default.protocolVersion} for version ${packageJson_js_1.default.version}.
|
|
47
48
|
Update either the renderer or the Rails server`,
|
|
48
49
|
};
|
|
49
50
|
}
|
package/lib/worker.js
CHANGED
|
@@ -57,6 +57,7 @@ const requestPrechecks_js_1 = require("./worker/requestPrechecks.js");
|
|
|
57
57
|
const authHandler_js_1 = require("./worker/authHandler.js");
|
|
58
58
|
const handleRenderRequest_js_1 = require("./worker/handleRenderRequest.js");
|
|
59
59
|
const handleGracefulShutdown_js_1 = __importDefault(require("./worker/handleGracefulShutdown.js"));
|
|
60
|
+
const sensitiveKeys_js_1 = require("./shared/sensitiveKeys.js");
|
|
60
61
|
const startupErrorHandler_js_1 = require("./worker/startupErrorHandler.js");
|
|
61
62
|
const handleIncrementalRenderRequest_js_1 = require("./worker/handleIncrementalRenderRequest.js");
|
|
62
63
|
const handleIncrementalRenderStream_js_1 = require("./worker/handleIncrementalRenderStream.js");
|
|
@@ -136,22 +137,6 @@ const errorCode = (error) => {
|
|
|
136
137
|
return typeof code === 'string' ? code : undefined;
|
|
137
138
|
};
|
|
138
139
|
const isValidRenderingRequest = (value) => typeof value === 'string' && value.length > 0;
|
|
139
|
-
const SENSITIVE_REQUEST_BODY_KEYS = new Set([
|
|
140
|
-
'password',
|
|
141
|
-
'token',
|
|
142
|
-
'secret',
|
|
143
|
-
'api_key',
|
|
144
|
-
'api-key',
|
|
145
|
-
'apikey',
|
|
146
|
-
'authorization',
|
|
147
|
-
'auth_token',
|
|
148
|
-
'auth-token',
|
|
149
|
-
'authtoken',
|
|
150
|
-
'access_token',
|
|
151
|
-
'accesstoken',
|
|
152
|
-
'bearer',
|
|
153
|
-
'credentials',
|
|
154
|
-
]);
|
|
155
140
|
const invalidRenderingRequestMessage = (body) => {
|
|
156
141
|
const { renderingRequest } = body;
|
|
157
142
|
let renderingRequestType = typeof renderingRequest;
|
|
@@ -164,7 +149,7 @@ const invalidRenderingRequestMessage = (body) => {
|
|
|
164
149
|
else if (renderingRequest === '') {
|
|
165
150
|
renderingRequestType = 'empty string';
|
|
166
151
|
}
|
|
167
|
-
const bodyKeys = Object.keys(body).filter((key) => key !== 'renderingRequest' && !SENSITIVE_REQUEST_BODY_KEYS.has(key.toLowerCase()));
|
|
152
|
+
const bodyKeys = Object.keys(body).filter((key) => key !== 'renderingRequest' && !sensitiveKeys_js_1.SENSITIVE_REQUEST_BODY_KEYS.has(key.toLowerCase()));
|
|
168
153
|
return [
|
|
169
154
|
'Invalid "renderingRequest" field in render request.',
|
|
170
155
|
'Expected a non-empty string of JavaScript to execute in the SSR VM.',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-on-rails-pro-node-renderer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "17.0.0-rc.1",
|
|
4
4
|
"protocolVersion": "2.0.0",
|
|
5
5
|
"description": "React on Rails Pro Node Renderer for server-side rendering",
|
|
6
6
|
"main": "lib/ReactOnRailsProNodeRenderer.js",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"sentry-testkit": "^5.0.6",
|
|
75
75
|
"touch": "^3.1.0",
|
|
76
76
|
"typescript": "^5.4.3",
|
|
77
|
-
"react-on-rails": "
|
|
77
|
+
"react-on-rails": "17.0.0-rc.1"
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
80
80
|
"@honeybadger-io/js": ">=4.0.0",
|