|
|
@@ -1,6 +1,19 @@
|
|
|
import { diag } from '@opentelemetry/api';
|
|
|
|
|
|
-const logger = diag.createComponentLogger({ namespace: 'growi:anonymization:query-params' });
|
|
|
+const logger = diag.createComponentLogger({ namespace: 'growi:anonymization:anonymize-query-params' });
|
|
|
+
|
|
|
+/**
|
|
|
+ * Try to parse JSON array, return null if invalid
|
|
|
+ */
|
|
|
+function tryParseJsonArray(value: string): unknown[] | null {
|
|
|
+ try {
|
|
|
+ const parsed = JSON.parse(value);
|
|
|
+ return Array.isArray(parsed) ? parsed : null;
|
|
|
+ }
|
|
|
+ catch {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
/**
|
|
|
* Anonymize specific query parameters in HTTP target URL
|
|
|
@@ -12,28 +25,35 @@ export function anonymizeQueryParams(target: string, paramNames: string[]): stri
|
|
|
try {
|
|
|
const url = new URL(target, 'http://localhost');
|
|
|
const searchParams = new URLSearchParams(url.search);
|
|
|
- let hasAnonymization = false;
|
|
|
+ let hasChange = false;
|
|
|
|
|
|
- // Anonymize each specified parameter if it exists
|
|
|
for (const paramName of paramNames) {
|
|
|
+ // Handle regular parameter (including JSON arrays)
|
|
|
if (searchParams.has(paramName)) {
|
|
|
- const originalValue = searchParams.get(paramName);
|
|
|
- if (originalValue) {
|
|
|
- // Replace the parameter content with [ANONYMIZED] but keep the parameter structure
|
|
|
- searchParams.set(paramName, '[ANONYMIZED]');
|
|
|
- hasAnonymization = true;
|
|
|
- logger.debug(`Anonymized query parameter '${paramName}': original length=${originalValue.length}`);
|
|
|
+ const value = searchParams.get(paramName);
|
|
|
+ if (value) {
|
|
|
+ let replacement = '[ANONYMIZED]';
|
|
|
+ if (value.startsWith('[') && value.endsWith(']')) {
|
|
|
+ const jsonArray = tryParseJsonArray(value);
|
|
|
+ if (jsonArray && jsonArray.length > 0) {
|
|
|
+ replacement = '["[ANONYMIZED]"]';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ searchParams.set(paramName, replacement);
|
|
|
+ hasChange = true;
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- if (!hasAnonymization) {
|
|
|
- return target; // No changes needed
|
|
|
+ // Handle array-style parameters (paramName[])
|
|
|
+ const arrayParam = `${paramName}[]`;
|
|
|
+ if (searchParams.has(arrayParam)) {
|
|
|
+ searchParams.delete(arrayParam);
|
|
|
+ searchParams.set(arrayParam, '[ANONYMIZED]');
|
|
|
+ hasChange = true;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // Reconstruct the target URL with anonymized parameters
|
|
|
- url.search = searchParams.toString();
|
|
|
- return url.pathname + url.search;
|
|
|
+ return hasChange ? `${url.pathname}?${searchParams.toString()}` : target;
|
|
|
}
|
|
|
catch (error) {
|
|
|
logger.warn(`Failed to anonymize query parameters [${paramNames.join(', ')}]: ${error}`);
|