gnodet-bot commented on code in PR #26758:
URL: https://github.com/apache/camel/pull/26758#discussion_r4079682637
##########
dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java:
##########
@@ -668,6 +669,87 @@ void checkSimpleSyntaxInScripts(JsonNode node, NodePath
path, List<Error> errors
}
}
+ /**
+ * to: http://host/stock/${header.sku}: the endpoint of a to: is resolved
once when the route starts, so an
+ * expression in its path is never evaluated - it is sent as the text it
is, url-encoded. That is what toD: is for
+ * (CAMEL-24917).
+ * <p/>
+ * Only the path is checked, never the options after the {@code ?}: an
option such as the file component's
+ * {@code fileName=${date:now:yyyyMMdd}} is evaluated by the producer and
is correct on a plain to:.
+ */
+ void checkDynamicUri(JsonNode node, NodePath path, List<Error> errors) {
+ if (node == null) {
+ return;
+ }
+ if (node.isArray()) {
+ for (int i = 0; i < node.size(); i++) {
+ checkDynamicUri(node.get(i), path.append(i), errors);
+ }
+ return;
+ }
+ if (!node.isObject()) {
+ return;
+ }
+ var fields = node.fieldNames();
+ while (fields.hasNext()) {
+ String name = fields.next();
+ JsonNode value = node.get(name);
+ if ("to".equals(name)) {
+ String uri = null;
+ NodePath at = path.append(name);
+ if (value.isTextual()) {
+ uri = value.asText();
+ } else if (value.isObject() && value.has("uri") &&
value.get("uri").isTextual()) {
+ uri = value.get("uri").asText();
+ at = at.append("uri");
+ }
+ String expression = expressionInPath(uri);
+ if (expression != null) {
+ errors.add(Error.builder()
+ .keyword("type")
+ .instanceLocation(at)
+ .messageKey("type")
+ .format(new MessageFormat("{0}"))
+ .arguments("to: the uri holds an expression (" +
expression + ") but the endpoint of a to:"
+ + " is fixed when the route starts, so
it is sent as text: write toD: to build"
+ + " the uri for each message")
+ .build());
+ }
+ }
+ checkDynamicUri(value, path.append(name), errors);
+ }
+ }
+
+ /**
+ * The first simple expression in the path of the uri (what comes before
the options), or null when there is none.
+ */
+ private static String expressionInPath(String uri) {
+ if (uri == null) {
+ return null;
+ }
+ int scheme = uri.indexOf(':');
+ if (scheme > 0 && EVALUATED_PATH.contains(uri.substring(0, scheme))) {
+ return null;
+ }
+ String head = uri.indexOf('?') > 0 ? uri.substring(0,
uri.indexOf('?')) : uri;
+ int start = head.indexOf("${");
+ if (start < 0) {
+ return null;
+ }
+ if (start >= 2 && head.startsWith(":#", start - 2)) {
+ return null; // :#${...} is a parameter the component binds per
message, not part of the address
+ }
+ int end = head.indexOf('}', start);
+ return end > 0 ? head.substring(start, end + 1) :
head.substring(start);
+ }
+
+ /**
+ * Components that read their path as a script, a statement or a template
name and evaluate it for each message,
+ * where an expression in the path is what the component is for.
+ */
+ private static final Set<String> EVALUATED_PATH = Set.of("language",
"sql", "sql-stored", "elsql", "jdbc",
+ "spring-jdbc", "mybatis", "xquery", "xslt");
Review Comment:
⚠️ **`xslt` and `xquery` do not belong in `EVALUATED_PATH`.**
The Javadoc says these components "read their path as a script, a statement
or a template name and evaluate it for each message" — but that is not what
they do. Both `XsltEndpoint` and `XQueryEndpoint` resolve their `resourceUri`
**once at startup** and load the stylesheet/query from that fixed path. They
never evaluate a `${...}` in the URI path per-message; dynamic template
selection in `xslt` is done via `allowTemplateFromHeader` (a message header,
not a path expression).
Consequence: a user who writes
```yaml
- to:
uri: "xslt:my-${header.type}.xsl"
```
gets no warning. The expression is sent as literal text at startup — the
exact runtime-silent bug this PR guards against — and the validator lets it
pass.
Remove both from the set. Add two test cases in
`YamlValidatorDynamicUriTest` asserting that `xslt:my-${header.type}.xsl` and
`xquery:my-${header.type}.xq` **are** flagged.
```suggestion
private static final Set<String> EVALUATED_PATH = Set.of("language",
"sql", "sql-stored", "elsql", "jdbc",
"spring-jdbc", "mybatis");
```
--
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]