Skip to content

Commit e46dae6

Browse files
authored
Query Params as Lists in SpEL, Groovy (#2789)
* Refactor query parameter handling: remove DuplicateKeyOrInvalidFormStrategy, update logic to support lists, and adjust affectd components and tests * Refactor `URI` query parsing: simplify `DuplicateKeyOrInvalidFormStrategy` import, remove unused `ParamBuilder`, and clean up `TemplateInterceptorTest`. * Refactor tests and parsing logic: update query parameter handling, remove unused tests and imports, add null checks, and improve YAML and JSON parsing. * Remove unused `getBean` method from `GenericYamlParserTest.MockBeanRegistry`.
1 parent 6ef08a2 commit e46dae6

24 files changed

Lines changed: 358 additions & 245 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ api:
347347
# Requests with a query parameter city and value Paris
348348
api:
349349
port: 2000
350-
test: params.city == 'Paris'
350+
test: params.city?.[0] == 'Paris'
351351
flow:
352352
- response:
353353
- static:
@@ -676,7 +676,7 @@ api:
676676
contentType: application/json
677677
pretty: true
678678
src: |
679-
{ "answer": ${params.answer} }
679+
{ "answer": ${params.answer?[0]} }
680680
- return:
681681
status: 200
682682
```

core/src/main/java/com/predic8/membrane/core/http/xml/URI.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,15 @@
1313
limitations under the License. */
1414
package com.predic8.membrane.core.http.xml;
1515

16-
import static com.predic8.membrane.core.util.URLParamUtil.parseQueryString;
16+
import com.predic8.membrane.core.config.*;
17+
import com.predic8.membrane.core.util.*;
1718

18-
import java.io.UnsupportedEncodingException;
19-
import java.util.Map;
19+
import javax.xml.stream.*;
20+
import java.io.*;
21+
import java.util.*;
2022

21-
import javax.xml.stream.XMLStreamException;
22-
import javax.xml.stream.XMLStreamReader;
23-
import javax.xml.stream.XMLStreamWriter;
24-
25-
import com.predic8.membrane.core.config.AbstractXmlElement;
26-
import com.predic8.membrane.core.util.URLParamUtil;
23+
import static com.predic8.membrane.core.util.URLParamUtil.*;
24+
import static com.predic8.membrane.core.util.URLParamUtil.DuplicateKeyOrInvalidFormStrategy.MERGE_USING_COMMA;
2725

2826
public class URI extends AbstractXmlElement {
2927

@@ -85,11 +83,11 @@ public void setValue(String value) throws Exception {
8583
parseQueryFromURI(jUri);
8684
}
8785

88-
private void parseQueryFromURI(java.net.URI jUri) throws UnsupportedEncodingException {
86+
private void parseQueryFromURI(java.net.URI jUri) {
8987
if (jUri.getQuery() == null) return;
9088

9189
Query q = new Query();
92-
for (Map.Entry<String, String> e : parseQueryString(jUri.getQuery(), URLParamUtil.DuplicateKeyOrInvalidFormStrategy.MERGE_USING_COMMA).entrySet()) {
90+
for (Map.Entry<String, String> e : parseQueryString(jUri.getQuery(), MERGE_USING_COMMA).entrySet()) {
9391
q.getParams().add(new Param(e.getKey(),e.getValue()));
9492
}
9593
setQuery(q);

core/src/main/java/com/predic8/membrane/core/interceptor/authentication/session/AbstractUserDataProvider.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
/* Copyright 2026 predic8 GmbH, www.predic8.com
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License. */
14+
115
package com.predic8.membrane.core.interceptor.authentication.session;
216

317
import com.predic8.membrane.annot.*;

core/src/main/java/com/predic8/membrane/core/interceptor/authentication/session/User.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
/* Copyright 2026 predic8 GmbH, www.predic8.com
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License. */
14+
115
package com.predic8.membrane.core.interceptor.authentication.session;
216

317
import java.util.*;

core/src/main/java/com/predic8/membrane/core/lang/ScriptingUtils.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import com.predic8.membrane.core.http.*;
2222
import com.predic8.membrane.core.interceptor.Interceptor.*;
2323
import com.predic8.membrane.core.lang.groovy.*;
24-
import com.predic8.membrane.core.lang.spel.spelable.*;
2524
import com.predic8.membrane.core.openapi.serviceproxy.*;
2625
import com.predic8.membrane.core.openapi.util.*;
2726
import com.predic8.membrane.core.router.*;
@@ -32,7 +31,6 @@
3231
import static com.predic8.membrane.core.interceptor.Interceptor.Flow.*;
3332
import static com.predic8.membrane.core.openapi.util.UriTemplateMatcher.*;
3433
import static com.predic8.membrane.core.util.FileUtil.*;
35-
import static com.predic8.membrane.core.util.URLParamUtil.DuplicateKeyOrInvalidFormStrategy.*;
3634
import static com.predic8.membrane.core.util.URLParamUtil.*;
3735
import static java.util.Collections.*;
3836

@@ -68,7 +66,7 @@ public static Map<String, Object> createParameterBindings(Router router, Exchang
6866

6967
if (flow == REQUEST) {
7068
try {
71-
var qParams = getParams(router.getConfiguration().getUriFactory(), exc, MERGE_USING_COMMA);
69+
var qParams = getParams(router.getConfiguration().getUriFactory(), exc);
7270
params.put("params", qParams);
7371
params.put("param", qParams);
7472
} catch (Exception e) {

core/src/main/java/com/predic8/membrane/core/lang/spel/SpELExchangeEvaluationContext.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@
3131
import java.io.*;
3232
import java.util.*;
3333

34-
import static com.predic8.membrane.annot.Constants.VERSION;
35-
import static com.predic8.membrane.core.util.URLParamUtil.DuplicateKeyOrInvalidFormStrategy.*;
34+
import static com.predic8.membrane.annot.Constants.*;
3635

3736
public class SpELExchangeEvaluationContext extends StandardEvaluationContext {
3837

@@ -120,7 +119,7 @@ private void extractFromRequest(Exchange exchange) {
120119
path = request.getUri();
121120
method = request.getMethod();
122121
try {
123-
params = new SpELMap<>(URLParamUtil.getParams(new URIFactory(), exchange, ERROR));
122+
params = new SpELMap<>(URLParamUtil.getParams(new URIFactory(), exchange));
124123
} catch (Exception e) {
125124
// Details are logged in URLParamUtil.getParams
126125
log.info("Error parsing query parameters for request '{} {}'", method, exchange.getOriginalRequestUri());

core/src/main/java/com/predic8/membrane/core/lang/spel/SpELExchangeExpression.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929
import org.springframework.expression.spel.*;
3030
import org.springframework.expression.spel.standard.*;
3131

32+
import java.util.*;
33+
3234
import static java.lang.Boolean.*;
3335
import static org.springframework.expression.spel.SpelCompilerMode.*;
34-
import static org.springframework.expression.spel.SpelMessage.METHOD_NOT_FOUND;
36+
import static org.springframework.expression.spel.SpelMessage.*;
3537

3638
public class SpELExchangeExpression extends AbstractExchangeExpression {
3739

@@ -77,6 +79,10 @@ public <T> T evaluate(Exchange exchange, Flow flow, Class<T> type) {
7779
return type.cast(toBoolean(o));
7880
}
7981
if (String.class.isAssignableFrom(type)) {
82+
// If a String is wanted and the type is List, return the first element of the list
83+
if (o instanceof List<?> l && l.size() > 0) {
84+
return type.cast(l.getFirst());
85+
}
8086
return type.cast(toString(o));
8187
}
8288
if (Object.class.isAssignableFrom(type)) {

0 commit comments

Comments
 (0)