|
18 | 18 | package org.apache.shenyu.plugin.mcp.server.callback; |
19 | 19 |
|
20 | 20 | import com.google.common.collect.Maps; |
| 21 | +import com.google.gson.JsonArray; |
21 | 22 | import com.google.gson.JsonElement; |
22 | 23 | import com.google.gson.JsonObject; |
23 | 24 | import io.modelcontextprotocol.server.McpSyncServerExchange; |
|
55 | 56 | import java.util.Objects; |
56 | 57 | import java.util.concurrent.CompletableFuture; |
57 | 58 | import java.util.concurrent.TimeUnit; |
| 59 | +import java.util.regex.Matcher; |
| 60 | +import java.util.regex.Pattern; |
58 | 61 |
|
59 | 62 | /** |
60 | 63 | * Tool Callback Implementation for Shenyu Gateway MCP Integration. |
@@ -92,6 +95,11 @@ public class ShenyuToolCallback implements ToolCallback { |
92 | 95 | */ |
93 | 96 | private static final String STREAMABLE_HTTP_PATH = "/streamablehttp"; |
94 | 97 |
|
| 98 | + /** |
| 99 | + * Regex pattern for template variable interpolation in tool inputs. |
| 100 | + **/ |
| 101 | + private static final Pattern TEMPLATE_VARIABLE_PATTERN = Pattern.compile("\\{\\{\\.(.*?)\\}\\}"); |
| 102 | + |
95 | 103 | private final ToolDefinition toolDefinition; |
96 | 104 |
|
97 | 105 | /** |
@@ -467,25 +475,62 @@ private ServerHttpRequest buildDecoratedRequest(final ServerWebExchange originEx |
467 | 475 | */ |
468 | 476 | private void addCustomHeaders(final ServerHttpRequest.Builder requestBuilder, |
469 | 477 | final RequestConfig requestConfig) { |
470 | | - if (requestConfig.getRequestTemplate().has("headers")) { |
471 | | - for (final var headerElem : requestConfig.getRequestTemplate().getAsJsonArray("headers")) { |
472 | | - final JsonObject headerObj = headerElem.getAsJsonObject(); |
473 | | - String headerKey = headerObj.get("key").getAsString(); |
474 | | - String headerValue = headerObj.get("value").getAsString(); |
475 | | - if (headerValue.contains("{{.")) { |
476 | | - JsonObject inputJson = requestConfig.getInputJson(); |
477 | | - if (Objects.nonNull(inputJson)) { |
478 | | - for (String key : inputJson.keySet()) { |
479 | | - if (inputJson.get(key).isJsonPrimitive() && inputJson.get(key).getAsJsonPrimitive().isString()) { |
480 | | - String value = inputJson.get(key).getAsString(); |
481 | | - headerValue = headerValue.replace("{{." + key + "}}", value); |
482 | | - } |
483 | | - } |
484 | | - } |
| 478 | + if (!requestConfig.getRequestTemplate().has("headers")) { |
| 479 | + return; |
| 480 | + } |
| 481 | + |
| 482 | + JsonArray headersArray = requestConfig.getRequestTemplate().getAsJsonArray("headers"); |
| 483 | + if (Objects.isNull(headersArray) || headersArray.isEmpty()) { |
| 484 | + return; |
| 485 | + } |
| 486 | + |
| 487 | + JsonObject inputJson = requestConfig.getInputJson(); |
| 488 | + for (JsonElement headerElem : headersArray) { |
| 489 | + if (!headerElem.isJsonObject()) { |
| 490 | + continue; |
| 491 | + } |
| 492 | + |
| 493 | + JsonObject headerObj = headerElem.getAsJsonObject(); |
| 494 | + if (!headerObj.has("key") || !headerObj.has("value") |
| 495 | + || !headerObj.get("key").isJsonPrimitive() || !headerObj.get("value").isJsonPrimitive()) { |
| 496 | + continue; |
| 497 | + } |
| 498 | + |
| 499 | + String headerKey = headerObj.get("key").getAsString(); |
| 500 | + String headerValue = headerObj.get("value").getAsString(); |
| 501 | + |
| 502 | + // Process template variables if present |
| 503 | + if (headerValue.contains("{{.") && Objects.nonNull(inputJson)) { |
| 504 | + headerValue = resolveTemplateVariables(headerValue, inputJson); |
| 505 | + } |
| 506 | + |
| 507 | + requestBuilder.header(headerKey, headerValue); |
| 508 | + } |
| 509 | + } |
| 510 | + |
| 511 | + /** |
| 512 | + * Resolves template variables in the format {{.variableName}} with values from the input JSON. |
| 513 | + * |
| 514 | + * @param templateValue the template string containing variables |
| 515 | + * @param inputJson the JSON object containing values for substitution |
| 516 | + * @return the resolved string with variables replaced |
| 517 | + */ |
| 518 | + private String resolveTemplateVariables(final String templateValue, final JsonObject inputJson) { |
| 519 | + String result = templateValue; |
| 520 | + Matcher matcher = TEMPLATE_VARIABLE_PATTERN.matcher(templateValue); |
| 521 | + |
| 522 | + while (matcher.find()) { |
| 523 | + String variableName = matcher.group(1); |
| 524 | + if (inputJson.has(variableName)) { |
| 525 | + JsonElement element = inputJson.get(variableName); |
| 526 | + if (element.isJsonPrimitive()) { |
| 527 | + String value = element.getAsString(); |
| 528 | + result = result.replace("{{." + variableName + "}}", value); |
485 | 529 | } |
486 | | - requestBuilder.header(headerKey, headerValue); |
487 | 530 | } |
488 | 531 | } |
| 532 | + |
| 533 | + return result; |
489 | 534 | } |
490 | 535 |
|
491 | 536 | /** |
|
0 commit comments