diff --git a/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClient.java b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClient.java index 2b57b2e2f..49e691979 100644 --- a/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClient.java +++ b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClient.java @@ -4,10 +4,8 @@ package com.sap.cloud.sdk.services.openapi.apiclient; -import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; -import java.net.URLEncoder; import java.text.DateFormat; import java.text.ParseException; import java.util.ArrayList; @@ -40,6 +38,7 @@ import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.web.util.UriUtils; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; @@ -699,14 +698,7 @@ public T invokeAPI( //encode the query parameters in case they contain unsafe characters for( final List values : queryParams.values() ) { if( values != null ) { - for( int i = 0; i < values.size(); i++ ) { - try { - values.set(i, URLEncoder.encode(values.get(i), "utf8")); - } - catch( final UnsupportedEncodingException e ) { - throw new OpenApiRequestException(e); - } - } + values.replaceAll(queryParam -> UriUtils.encodeQueryParam(queryParam, "utf8")); } } builder.queryParams(queryParams); diff --git a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientViaConstructorTest.java b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientViaConstructorTest.java index 2103f2004..a7ab44c06 100644 --- a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientViaConstructorTest.java +++ b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientViaConstructorTest.java @@ -5,9 +5,10 @@ package com.sap.cloud.sdk.services.openapi.apiclient; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.content; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.*; + +import java.util.ArrayList; +import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -20,6 +21,8 @@ import org.springframework.test.web.client.ExpectedCount; import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.test.web.client.response.MockRestResponseCreators; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; @@ -89,6 +92,35 @@ void testApiClientWithoutExplicitRestTemplateDoesNotConsiderGetters() server.verify(); } + @Test + void testApiClientWithQueryParams() + { + final String filterQueryValue = "emails.value eq \"my.email@test.com\""; + final String expectedFilterQuery = "emails.value%20eq%20%22my.email@test.com%22"; + final String filterQueryParam = "filter"; + MultiValueMap execQueryParams = new LinkedMultiValueMap<>(); + List values = new ArrayList<>(); + values.add(filterQueryValue); + execQueryParams.put("filter", values); + + final ApiClient apiClient = new ApiClient().setBasePath(BASE_PATH); + final RestTemplate restTemplate = apiClient.getRestTemplate(); + final MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build(); + + server + .expect( + ExpectedCount.once(), + requestTo(BASE_PATH + RELATIVE_PATH + "?" + filterQueryParam + "=" + expectedFilterQuery)) + .andExpect(method(HttpMethod.GET)) + .andExpect(queryParam(filterQueryParam, expectedFilterQuery)) + .andRespond(MockRestResponseCreators.withSuccess(SUCCESS_BODY, MediaType.TEXT_PLAIN)); + + final MyTestOpenApiService myTestOpenApiService = new MyTestOpenApiService(apiClient); + myTestOpenApiService.invokeApiEndpoint(HttpMethod.GET, null, execQueryParams); + + server.verify(); + } + private static class MyDto { @JsonProperty( "Return" ) @@ -112,16 +144,19 @@ private static class MyTestOpenApiService extends AbstractOpenApiService super(apiClient); } - void invokeApiEndpoint() + void invokeApiEndpoint( @Nullable Object body ) { - invokeApiEndpoint(null); + invokeApiEndpoint(HttpMethod.POST, body, null); } - void invokeApiEndpoint( @Nullable Object body ) + void invokeApiEndpoint( + HttpMethod method, + @Nullable Object body, + @Nullable MultiValueMap queryParams ) { assertThat(apiClient.getBasePath()).isEqualTo(BASE_PATH); - final ParameterizedTypeReference returnType = new ParameterizedTypeReference() + final ParameterizedTypeReference returnType = new ParameterizedTypeReference<>() { }; @@ -129,8 +164,8 @@ void invokeApiEndpoint( @Nullable Object body ) apiClient .invokeAPI( UriComponentsBuilder.fromPath(RELATIVE_PATH).toUriString(), - HttpMethod.POST, - null, + method, + queryParams, body, new HttpHeaders(), null, diff --git a/release_notes.md b/release_notes.md index 92ce144f2..7946fb8bf 100644 --- a/release_notes.md +++ b/release_notes.md @@ -26,4 +26,4 @@ ### 🐛 Fixed Issues -- +- OpenAPI QueryParameters are now encoded