mirror of
https://github.com/jlengrand/openapi-generator.git
synced 2026-05-17 08:31:23 +00:00
Support Swagger collectionFormat encodings in Feign (#5266)
* Support Swagger collectionFormat encodings in Feign Feign only natively supports the "multi" collectionFormat for encoding lists of parameter values. This change adds manual encoding of the other formats, such as "csv" (the default for collections), "tsv", space-separated, and pipes. * Fix typo in anchor tag.
This commit is contained in:
committed by
wing328
parent
909f392745
commit
5c3fe23e9f
@@ -0,0 +1,86 @@
|
||||
package io.swagger.client;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utilities to support Swagger encoding formats in Feign.
|
||||
*/
|
||||
public final class EncodingUtils {
|
||||
|
||||
/**
|
||||
* Private constructor. Do not construct this class.
|
||||
*/
|
||||
private EncodingUtils() {}
|
||||
|
||||
/**
|
||||
* <p>Encodes a collection of query parameters according to the Swagger
|
||||
* collection format.</p>
|
||||
*
|
||||
* <p>Of the various collection formats defined by Swagger ("csv", "tsv",
|
||||
* etc), Feign only natively supports "multi". This utility generates the
|
||||
* other format types so it will be properly processed by Feign.</p>
|
||||
*
|
||||
* <p>Note, as part of reformatting, it URL encodes the parameters as
|
||||
* well.</p>
|
||||
* @param parameters The collection object to be formatted. This object will
|
||||
* not be changed.
|
||||
* @param collectionFormat The Swagger collection format (eg, "csv", "tsv",
|
||||
* "pipes"). See the
|
||||
* <a href="http://swagger.io/specification/#parameter-object-44">
|
||||
* Swagger Spec</a> for more details.
|
||||
* @return An object that will be correctly formatted by Feign.
|
||||
*/
|
||||
public static Object encodeCollection(Collection<?> parameters,
|
||||
String collectionFormat) {
|
||||
if (parameters == null) {
|
||||
return parameters;
|
||||
}
|
||||
List<String> stringValues = new ArrayList<>(parameters.size());
|
||||
for (Object parameter : parameters) {
|
||||
// ignore null values (same behavior as Feign)
|
||||
if (parameter != null) {
|
||||
stringValues.add(encode(parameter));
|
||||
}
|
||||
}
|
||||
// Feign natively handles single-element lists and the "multi" format.
|
||||
if (stringValues.size() < 2 || "multi".equals(collectionFormat)) {
|
||||
return stringValues;
|
||||
}
|
||||
// Otherwise return a formatted String
|
||||
String[] stringArray = stringValues.toArray(new String[0]);
|
||||
switch (collectionFormat) {
|
||||
case "csv":
|
||||
default:
|
||||
return StringUtil.join(stringArray, ",");
|
||||
case "ssv":
|
||||
return StringUtil.join(stringArray, " ");
|
||||
case "tsv":
|
||||
return StringUtil.join(stringArray, "\t");
|
||||
case "pipes":
|
||||
return StringUtil.join(stringArray, "|");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URL encode a single query parameter.
|
||||
* @param parameter The query parameter to encode. This object will not be
|
||||
* changed.
|
||||
* @return The URL encoded string representation of the parameter. If the
|
||||
* parameter is null, returns null.
|
||||
*/
|
||||
public static String encode(Object parameter) {
|
||||
if (parameter == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return URLEncoder.encode(parameter.toString(), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// Should never happen, UTF-8 is always supported
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.swagger.client.api;
|
||||
|
||||
import io.swagger.client.ApiClient;
|
||||
import io.swagger.client.EncodingUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import io.swagger.client.model.Client;
|
||||
@@ -106,7 +107,7 @@ public interface FakeApi extends ApiClient.Api {
|
||||
|
||||
"enum_header_string: {enumHeaderString}"
|
||||
})
|
||||
void testEnumParameters(@Param("enumFormStringArray") List<String> enumFormStringArray, @Param("enumFormString") String enumFormString, @Param("enumHeaderStringArray") List<String> enumHeaderStringArray, @Param("enumHeaderString") String enumHeaderString, @Param("enumQueryDouble") Double enumQueryDouble, @QueryMap Map<String, Object> queryParams);
|
||||
void testEnumParameters(@Param("enumFormStringArray") List<String> enumFormStringArray, @Param("enumFormString") String enumFormString, @Param("enumHeaderStringArray") List<String> enumHeaderStringArray, @Param("enumHeaderString") String enumHeaderString, @Param("enumQueryDouble") Double enumQueryDouble, @QueryMap(encoded=true) Map<String, Object> queryParams);
|
||||
|
||||
/**
|
||||
* A convenience class for generating query parameters for the
|
||||
@@ -114,15 +115,15 @@ public interface FakeApi extends ApiClient.Api {
|
||||
*/
|
||||
public static class TestEnumParametersQueryParams extends HashMap<String, Object> {
|
||||
public TestEnumParametersQueryParams enumQueryStringArray(final List<String> value) {
|
||||
put("enum_query_string_array", value);
|
||||
put("enum_query_string_array", EncodingUtils.encodeCollection(value, "csv"));
|
||||
return this;
|
||||
}
|
||||
public TestEnumParametersQueryParams enumQueryString(final String value) {
|
||||
put("enum_query_string", value);
|
||||
put("enum_query_string", EncodingUtils.encode(value));
|
||||
return this;
|
||||
}
|
||||
public TestEnumParametersQueryParams enumQueryInteger(final Integer value) {
|
||||
put("enum_query_integer", value);
|
||||
put("enum_query_integer", EncodingUtils.encode(value));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.swagger.client.api;
|
||||
|
||||
import io.swagger.client.ApiClient;
|
||||
import io.swagger.client.EncodingUtils;
|
||||
|
||||
import java.io.File;
|
||||
import io.swagger.client.model.ModelApiResponse;
|
||||
@@ -75,7 +76,7 @@ public interface PetApi extends ApiClient.Api {
|
||||
"Content-Type: application/json",
|
||||
"Accept: application/json",
|
||||
})
|
||||
List<Pet> findPetsByStatus(@QueryMap Map<String, Object> queryParams);
|
||||
List<Pet> findPetsByStatus(@QueryMap(encoded=true) Map<String, Object> queryParams);
|
||||
|
||||
/**
|
||||
* A convenience class for generating query parameters for the
|
||||
@@ -83,7 +84,7 @@ public interface PetApi extends ApiClient.Api {
|
||||
*/
|
||||
public static class FindPetsByStatusQueryParams extends HashMap<String, Object> {
|
||||
public FindPetsByStatusQueryParams status(final List<String> value) {
|
||||
put("status", value);
|
||||
put("status", EncodingUtils.encodeCollection(value, "csv"));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -121,7 +122,7 @@ public interface PetApi extends ApiClient.Api {
|
||||
"Content-Type: application/json",
|
||||
"Accept: application/json",
|
||||
})
|
||||
List<Pet> findPetsByTags(@QueryMap Map<String, Object> queryParams);
|
||||
List<Pet> findPetsByTags(@QueryMap(encoded=true) Map<String, Object> queryParams);
|
||||
|
||||
/**
|
||||
* A convenience class for generating query parameters for the
|
||||
@@ -129,7 +130,7 @@ public interface PetApi extends ApiClient.Api {
|
||||
*/
|
||||
public static class FindPetsByTagsQueryParams extends HashMap<String, Object> {
|
||||
public FindPetsByTagsQueryParams tags(final List<String> value) {
|
||||
put("tags", value);
|
||||
put("tags", EncodingUtils.encodeCollection(value, "csv"));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.swagger.client.api;
|
||||
|
||||
import io.swagger.client.ApiClient;
|
||||
import io.swagger.client.EncodingUtils;
|
||||
|
||||
import io.swagger.client.model.Order;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.swagger.client.api;
|
||||
|
||||
import io.swagger.client.ApiClient;
|
||||
import io.swagger.client.EncodingUtils;
|
||||
|
||||
import io.swagger.client.model.User;
|
||||
|
||||
@@ -110,7 +111,7 @@ public interface UserApi extends ApiClient.Api {
|
||||
"Content-Type: application/json",
|
||||
"Accept: application/json",
|
||||
})
|
||||
String loginUser(@QueryMap Map<String, Object> queryParams);
|
||||
String loginUser(@QueryMap(encoded=true) Map<String, Object> queryParams);
|
||||
|
||||
/**
|
||||
* A convenience class for generating query parameters for the
|
||||
@@ -118,11 +119,11 @@ public interface UserApi extends ApiClient.Api {
|
||||
*/
|
||||
public static class LoginUserQueryParams extends HashMap<String, Object> {
|
||||
public LoginUserQueryParams username(final String value) {
|
||||
put("username", value);
|
||||
put("username", EncodingUtils.encode(value));
|
||||
return this;
|
||||
}
|
||||
public LoginUserQueryParams password(final String value) {
|
||||
put("password", value);
|
||||
put("password", EncodingUtils.encode(value));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,25 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import org.junit.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class PetApiTest {
|
||||
ApiClient apiClient;
|
||||
PetApi api;
|
||||
MockWebServer localServer;
|
||||
ApiClient localClient;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
apiClient = new ApiClient();
|
||||
api = apiClient.buildClient(PetApi.class);
|
||||
localServer = new MockWebServer();
|
||||
localClient = new ApiClient();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -211,6 +219,20 @@ public class PetApiTest {
|
||||
assertTrue(pet1.hashCode() == pet1.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCSVDelimitedArray() throws Exception {
|
||||
localServer.enqueue(new MockResponse().setBody("[{\"id\":5,\"name\":\"rocky\"}]"));
|
||||
localServer.start();
|
||||
PetApi api = localClient.setBasePath(localServer.url("/").toString()).buildClient(PetApi.class);
|
||||
PetApi.FindPetsByTagsQueryParams queryParams = new PetApi.FindPetsByTagsQueryParams()
|
||||
.tags(Arrays.asList("friendly","energetic"));
|
||||
List<Pet> pets = api.findPetsByTags(queryParams);
|
||||
assertNotNull(pets);
|
||||
RecordedRequest request = localServer.takeRequest();
|
||||
assertThat(request.getPath()).contains("tags=friendly,energetic");
|
||||
localServer.shutdown();
|
||||
}
|
||||
|
||||
private Pet createRandomPet() {
|
||||
Pet pet = new Pet();
|
||||
pet.setId(TestUtils.nextId());
|
||||
|
||||
Reference in New Issue
Block a user