ramu11 commented on code in PR #27686:
URL: https://github.com/apache/camel/pull/27686#discussion_r4254561139
##########
components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/Kamelet.java:
##########
@@ -184,6 +207,196 @@ public static void
extractKameletEnvironmentVariables(Map<String, Object> proper
}
}
+ /**
+ * Reads the original advanced options map stored under a single internal
key.
+ */
+ private static Map<String, Object> extractAdvancedOptions(Map<String,
Object> parameters, String key) {
+ Map<String, Object> options = new LinkedHashMap<>();
+ if (parameters == null) {
+ return options;
+ }
+
+ Object value = parameters.get(key);
+ if (value instanceof Map<?, ?> map) {
+ for (Map.Entry<?, ?> entry : map.entrySet()) {
+ if (entry.getKey() != null) {
+ options.put(entry.getKey().toString(), entry.getValue());
+ }
+ }
+ }
+
+ return options;
+ }
+
+ /**
+ * Preserves the user-supplied option name. When both camelCase and
kebab-case forms are present, the kebab-case
+ * form is kept so the same option is not appended twice.
+ */
+ private static Map<String, Object> normalizeParameterNames(Map<String,
Object> parameters) {
+ Map<String, Object> normalized = new LinkedHashMap<>();
+ Map<String, String> seenOriginal = new HashMap<>();
+ Map<String, Boolean> seenIsCanonical = new HashMap<>();
+
+ if (parameters == null) {
+ return normalized;
+ }
+
+ for (Map.Entry<String, Object> entry : parameters.entrySet()) {
+ String originalName = entry.getKey();
+ String name = StringHelper.camelCaseToDash(originalName);
+ boolean isCanonical = originalName.equals(name);
+
+ String existingOriginal = seenOriginal.get(name);
+ if (existingOriginal == null) {
+ seenOriginal.put(name, originalName);
+ seenIsCanonical.put(name, isCanonical);
+ normalized.put(originalName, entry.getValue());
+ } else {
+ boolean existingIsCanonical = seenIsCanonical.get(name);
+ if (isCanonical && !existingIsCanonical) {
+ normalized.remove(existingOriginal);
+ seenOriginal.put(name, originalName);
+ seenIsCanonical.put(name, isCanonical);
+ normalized.put(originalName, entry.getValue());
+ }
+ }
+ }
+
+ return normalized;
+ }
+
+ /**
+ * Appends query parameters without parsing or re-encoding the endpoint
URI. This preserves property placeholders
+ * and RAW expressions that may appear in the URI.
+ */
+ private static String appendParametersToURI(String uri, Map<String,
Object> parameters) {
+ if (parameters == null || parameters.isEmpty()) {
+ return uri;
+ }
+
+ String result = uri;
+ for (Map.Entry<String, Object> entry : parameters.entrySet()) {
+ String name = entry.getKey();
+ String value = String.valueOf(entry.getValue());
+
+ result = removeQueryParameter(result, name);
+ result += result.contains("?") ? "&" : "?";
+ result += name + "=" + wrapRawIfNeeded(value);
+ }
+
+ return result;
+ }
+
+ /**
+ * Re-wraps values that contain URI-sensitive characters. RAW wrappers may
already have been stripped by
+ * {@link URISupport#resolveRawParameterValues(Map)} before options reach
this method.
+ */
+ private static String wrapRawIfNeeded(String value) {
+ if (isRawToken(value)) {
+ return value;
+ }
+ if (value.contains("&") || value.contains("=") || value.contains("?"))
{
Review Comment:
Thanks for the reviews. The RAW handling here is intentional, and I'd like
to clarify the problem it addresses so we can converge on the expected behavior
rather than iterating on individual URI characters.
When advanced `sink.*` options are extracted from the Kamelet parameters,
the `RAW(...)` wrapper may already have been removed by Camel's endpoint
parameter parsing. The resulting value is then appended to the destination
endpoint URI.
If that value contains URI-sensitive characters such as `&`, `=`, `?`, `+`,
or `%`, appending it directly can change its meaning when Camel parses the
destination URI. For example, `sink.password=RAW(p@ss&word)` can become
`password=p@ss&word`, where `&word` is interpreted as another query parameter
and the password is truncated to `p@ss`. Similarly, `+` can be decoded as a
space, and `%` can trigger percent-decoding behavior.
The purpose of `wrapRawIfNeeded()` is therefore to restore RAW semantics for
values that would otherwise be altered during URI parsing, while leaving
existing RAW tokens and ordinary values unchanged.
The regression test `sinkOptionsPreserveRawValuesWithUriSensitiveCharacters`
covers this behavior, and the build now passes.
I'd prefer to keep the fix scoped to preserving the original parameter value
through URI reconstruction. If there is a Camel-core API that provides this
guarantee without manually restoring RAW wrappers, I'm happy to consider it.
Otherwise, could we agree on the expected behavior and test cases for this
helper so the remaining changes can be evaluated consistently?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]