15
15
*/
16
16
package com .alibaba .cloud .ai .graph .node ;
17
17
18
+ import java .net .URI ;
19
+ import java .nio .charset .StandardCharsets ;
20
+ import java .time .Duration ;
21
+ import java .util .ArrayList ;
22
+ import java .util .Base64 ;
23
+ import java .util .Collections ;
24
+ import java .util .HashMap ;
25
+ import java .util .List ;
26
+ import java .util .Map ;
27
+ import java .util .Objects ;
28
+ import java .util .Optional ;
29
+ import java .util .UUID ;
30
+ import java .util .regex .Matcher ;
31
+ import java .util .function .Function ;
32
+ import java .util .regex .Pattern ;
33
+
18
34
import com .alibaba .cloud .ai .graph .OverAllState ;
19
35
import com .alibaba .cloud .ai .graph .action .NodeAction ;
20
36
import com .alibaba .cloud .ai .graph .exception .GraphRunnerException ;
25
41
import com .fasterxml .jackson .databind .ObjectMapper ;
26
42
import org .slf4j .Logger ;
27
43
import org .slf4j .LoggerFactory ;
44
+ import reactor .core .publisher .Mono ;
45
+ import reactor .util .retry .Retry ;
46
+
28
47
import org .springframework .core .io .ByteArrayResource ;
29
48
import org .springframework .http .HttpHeaders ;
30
49
import org .springframework .http .HttpMethod ;
39
58
import org .springframework .web .reactive .function .client .WebClient ;
40
59
import org .springframework .web .reactive .function .client .WebClientResponseException ;
41
60
import org .springframework .web .util .UriComponentsBuilder ;
42
- import reactor .core .publisher .Mono ;
43
- import reactor .util .retry .Retry ;
44
-
45
- import java .net .URI ;
46
- import java .nio .charset .StandardCharsets ;
47
- import java .time .Duration ;
48
- import java .util .ArrayList ;
49
- import java .util .Base64 ;
50
- import java .util .Collections ;
51
- import java .util .HashMap ;
52
- import java .util .List ;
53
- import java .util .Map ;
54
- import java .util .Objects ;
55
- import java .util .Optional ;
56
- import java .util .UUID ;
57
- import java .util .regex .Matcher ;
58
- import java .util .regex .Pattern ;
59
61
60
62
import static java .lang .String .format ;
61
63
@@ -69,7 +71,26 @@ public class HttpNode implements NodeAction {
69
71
70
72
private static final long DEFAULT_MAX_RETRY_INTERVAL = 1000 ;
71
73
72
- private static final ObjectMapper mapper = new ObjectMapper ();
74
+ private static final ObjectMapper DEFAULT_MAPPER = new ObjectMapper ();
75
+
76
+ /**
77
+ * Default string replacement function that cleans JSON template strings.
78
+ */
79
+ private static final Function <Object , Object > DEFAULT_VARIABLE_FILTER = jsonTemplate -> {
80
+ if (jsonTemplate instanceof String && StringUtils .hasText ((String ) jsonTemplate )) {
81
+ return ((String ) jsonTemplate ).replace ("```json" , "" )
82
+ .replace ("```" , "" )
83
+ .replace ("\n " , "" )
84
+ .replace ("\r " , "" )
85
+ .replace ("\t " , "" )
86
+ .replace ("\" " , "\\ \" " );
87
+ }
88
+ return jsonTemplate ;
89
+ };
90
+
91
+ private final ObjectMapper mapper ;
92
+
93
+ private final Function <Object , Object > variableFilter ;
73
94
74
95
private final WebClient webClient ;
75
96
@@ -99,6 +120,8 @@ private HttpNode(Builder builder) {
99
120
this .authConfig = builder .authConfig ;
100
121
this .retryConfig = builder .retryConfig ;
101
122
this .outputKey = builder .outputKey ;
123
+ this .mapper = builder .objectMapper != null ? builder .objectMapper : DEFAULT_MAPPER ;
124
+ this .variableFilter = builder .variableFilter != null ? builder .variableFilter : DEFAULT_VARIABLE_FILTER ;
102
125
}
103
126
104
127
@ Override
@@ -148,8 +171,8 @@ private String replaceVariables(String template, OverAllState state) {
148
171
while (matcher .find ()) {
149
172
String key = matcher .group (1 );
150
173
Object value = state .value (key ).orElse ("" );
151
- String strReplaced = getStrReplaced ( value . toString () );
152
- matcher .appendReplacement (result , Matcher .quoteReplacement (strReplaced ));
174
+ Object replaced = variableFilter . apply ( value );
175
+ matcher .appendReplacement (result , Matcher .quoteReplacement (replaced != null ? replaced . toString () : "" ));
153
176
}
154
177
matcher .appendTail (result );
155
178
return result .toString ();
@@ -258,31 +281,16 @@ public String getFilename() {
258
281
}
259
282
}
260
283
261
- /**
262
- * Get string replaced.
263
- * @param jsonTemplate JSON template
264
- * @return string replaced
265
- */
266
- private static String getStrReplaced (String jsonTemplate ) {
267
- return jsonTemplate == null ? ""
268
- : jsonTemplate .replace ("```json" , "" )
269
- .replace ("```" , "" )
270
- .replace ("\n " , "" )
271
- .replace ("\r " , "" )
272
- .replace ("\t " , "" )
273
- .replace ("\" " , "\\ \" " );
274
- }
275
-
276
284
/**
277
285
* Parse nested JSON string.
278
286
* @param json JSON string
279
287
* @return parsed JSON object
280
288
* @throws JsonProcessingException if parsing fails
281
289
*/
282
- public static Object parseNestedJson (String json ) throws JsonProcessingException {
283
- JsonNode rootNode = mapper .readTree (json );
290
+ public Object parseNestedJson (String json ) throws JsonProcessingException {
291
+ JsonNode rootNode = this . mapper .readTree (json );
284
292
if (rootNode .isObject ()) {
285
- Map <String , Object > map = mapper .convertValue (rootNode , Map .class );
293
+ Map <String , Object > map = this . mapper .convertValue (rootNode , Map .class );
286
294
for (Map .Entry <String , Object > entry : map .entrySet ()) {
287
295
Object value = entry .getValue ();
288
296
if (value instanceof String valueStr ) {
@@ -303,7 +311,7 @@ public static Object parseNestedJson(String json) throws JsonProcessingException
303
311
return map ;
304
312
}
305
313
else {
306
- return mapper .convertValue (rootNode , Object .class );
314
+ return this . mapper .convertValue (rootNode , Object .class );
307
315
}
308
316
}
309
317
@@ -341,8 +349,7 @@ private Map<String, Object> processResponse(ResponseEntity<byte[]> responseEntit
341
349
else {
342
350
String text = new String (body , StandardCharsets .UTF_8 );
343
351
try {
344
- ObjectMapper objectMapper = new ObjectMapper ();
345
- Map <String , Object > map = objectMapper .readValue (text , Map .class );
352
+ Map <String , Object > map = this .mapper .readValue (text , Map .class );
346
353
result .put ("body" , map );
347
354
}
348
355
catch (Exception ex ) {
@@ -416,6 +423,15 @@ public static class Builder {
416
423
417
424
private String outputKey ;
418
425
426
+ private ObjectMapper objectMapper ;
427
+
428
+ private Function <Object , Object > variableFilter ;
429
+
430
+ public Builder objectMapper (ObjectMapper objectMapper ) {
431
+ this .objectMapper = objectMapper ;
432
+ return this ;
433
+ }
434
+
419
435
public Builder webClient (WebClient webClient ) {
420
436
this .webClient = webClient ;
421
437
return this ;
@@ -461,6 +477,19 @@ public Builder outputKey(String outputKey) {
461
477
return this ;
462
478
}
463
479
480
+ /**
481
+ * Set a custom string filter function for processing variable replacement values.
482
+ * This function will be applied to all string values during variable replacement.
483
+ * If not set, a default filter will be used that cleans JSON template strings.
484
+ * @param variableFilter the function to filter string values during variable
485
+ * replacement
486
+ * @return this builder
487
+ */
488
+ public Builder variableFilter (Function <Object , Object > variableFilter ) {
489
+ this .variableFilter = variableFilter ;
490
+ return this ;
491
+ }
492
+
464
493
public HttpNode build () {
465
494
return new HttpNode (this );
466
495
}
0 commit comments