From 8d05028c2e4273f7d08f81d20922102283f5d0e2 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Mon, 8 Apr 2024 17:29:03 +0100 Subject: [PATCH] RequestParam resolver supports empty array suffix Closes gh-32577 --- .../RequestParamMethodArgumentResolver.java | 5 ++++- ...RequestParamMethodArgumentResolverTests.java | 17 +++++++++++++++-- .../RequestParamMethodArgumentResolver.java | 7 +++++-- ...RequestParamMethodArgumentResolverTests.java | 12 +++++++++++- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolver.java b/spring-web/src/main/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolver.java index 2a0673239f9d..921f7f656fad 100644 --- a/spring-web/src/main/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolver.java +++ b/spring-web/src/main/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -179,6 +179,9 @@ protected Object resolveName(String name, MethodParameter parameter, NativeWebRe } if (arg == null) { String[] paramValues = request.getParameterValues(name); + if (paramValues == null) { + paramValues = request.getParameterValues(name + "[]"); + } if (paramValues != null) { arg = (paramValues.length == 1 ? paramValues[0] : paramValues); } diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java index 82e750965257..2205d6b1f0e6 100644 --- a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java +++ b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java @@ -66,11 +66,11 @@ class RequestParamMethodArgumentResolverTests { private RequestParamMethodArgumentResolver resolver = new RequestParamMethodArgumentResolver(null, true); - private MockHttpServletRequest request = new MockHttpServletRequest(); + private final MockHttpServletRequest request = new MockHttpServletRequest(); private NativeWebRequest webRequest = new ServletWebRequest(request, new MockHttpServletResponse()); - private ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build(); + private final ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build(); @Test @@ -167,6 +167,19 @@ void resolveStringArray() throws Exception { assertThat((String[]) result).as("Invalid result").isEqualTo(expected); } + @Test // gh-32577 + void resolveStringArrayWithEmptyArraySuffix() throws Exception { + String[] expected = new String[] {"foo", "bar"}; + request.addParameter("name[]", expected[0]); + request.addParameter("name[]", expected[1]); + + MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(String[].class); + Object result = resolver.resolveArgument(param, null, webRequest, null); + boolean condition = result instanceof String[]; + assertThat(condition).isTrue(); + assertThat((String[]) result).isEqualTo(expected); + } + @Test void resolveMultipartFile() throws Exception { MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest(); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolver.java index 55f4d62b37ce..17c6a868d0cc 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -100,8 +100,11 @@ protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) { @Override @Nullable protected Object resolveNamedValue(String name, MethodParameter parameter, ServerWebExchange exchange) { - List paramValues = exchange.getRequest().getQueryParams().get(name); Object result = null; + List paramValues = exchange.getRequest().getQueryParams().get(name); + if (paramValues == null) { + paramValues = exchange.getRequest().getQueryParams().get(name + "[]"); + } if (paramValues != null) { result = (paramValues.size() == 1 ? paramValues.get(0) : paramValues); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java index ccb90f34d629..c42bb55f1516 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestParamMethodArgumentResolverTests.java @@ -53,7 +53,7 @@ class RequestParamMethodArgumentResolverTests { private BindingContext bindContext; - private ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build(); + private final ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build(); @BeforeEach @@ -130,6 +130,16 @@ void resolveStringArray() { assertThat((String[]) result).isEqualTo(new String[] {"foo", "bar"}); } + @Test // gh-32577 + void resolveStringArrayWithEmptyArraySuffix() { + MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(String[].class); + MockServerHttpRequest request = MockServerHttpRequest.get("/path?name[]=foo&name[]=bar").build(); + Object result = resolve(param, MockServerWebExchange.from(request)); + boolean condition = result instanceof String[]; + assertThat(condition).isTrue(); + assertThat((String[]) result).isEqualTo(new String[] {"foo", "bar"}); + } + @Test void resolveDefaultValue() { MethodParameter param = this.testMethod.annot(requestParam().notRequired("bar")).arg(String.class);