diff --git a/docs/generators/java.md b/docs/generators/java.md
index fefac1ff1d17..7785ee892e9f 100644
--- a/docs/generators/java.md
+++ b/docs/generators/java.md
@@ -54,4 +54,5 @@ sidebar_label: java
|useRuntimeException|Use RuntimeException instead of Exception| |false|
|feignVersion|Version of OpenFeign: '10.x', '9.x' (default)| |false|
|useReflectionEqualsHashCode|Use org.apache.commons.lang3.builder for equals and hashCode in the models. WARNING: This will fail under a security manager, unless the appropriate permissions are set up correctly and also there's potential performance impact.| |false|
+|caseInsensitiveResponseHeaders|Make API response's headers case-insensitive in okhttp-gson library| |false|
|library|library template (sub-template) to use|
- **jersey1**
- HTTP client: Jersey client 1.19.x. JSON processing: Jackson 2.8.x. Enable Java6 support using '-DsupportJava6=true'. Enable gzip request encoding using '-DuseGzipFeature=true'. IMPORTANT NOTE: jersey 1.x is no longer actively maintained so please upgrade to 'jersey2' or other HTTP libaries instead.
- **jersey2**
- HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.8.x
- **feign**
- HTTP client: OpenFeign 9.x or 10.x. JSON processing: Jackson 2.8.x. To enable OpenFeign 10.x, set the 'feignVersion' option to '10.x'
- **okhttp-gson**
- [DEFAULT] HTTP client: OkHttp 3.x. JSON processing: Gson 2.8.x. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'.
- **retrofit**
- HTTP client: OkHttp 2.x. JSON processing: Gson 2.x (Retrofit 1.9.0). IMPORTANT NOTE: retrofit1.x is no longer actively maintained so please upgrade to 'retrofit2' instead.
- **retrofit2**
- HTTP client: OkHttp 3.x. JSON processing: Gson 2.x (Retrofit 2.3.0). Enable the RxJava adapter using '-DuseRxJava[2]=true'. (RxJava 1.x or 2.x)
- **resttemplate**
- HTTP client: Spring RestTemplate 4.x. JSON processing: Jackson 2.8.x
- **webclient**
- HTTP client: Spring WebClient 5.x. JSON processing: Jackson 2.9.x
- **resteasy**
- HTTP client: Resteasy client 3.x. JSON processing: Jackson 2.8.x
- **vertx**
- HTTP client: VertX client 3.x. JSON processing: Jackson 2.8.x
- **google-api-client**
- HTTP client: Google API client 1.x. JSON processing: Jackson 2.8.x
- **rest-assured**
- HTTP client: rest-assured : 3.x. JSON processing: Gson 2.x. Only for Java8
|okhttp-gson|
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java
index 35c8a83aaa21..a5a3b3dd40df 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java
@@ -54,6 +54,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
public static final String PARCELABLE_MODEL = "parcelableModel";
public static final String USE_RUNTIME_EXCEPTION = "useRuntimeException";
public static final String USE_REFLECTION_EQUALS_HASHCODE = "useReflectionEqualsHashCode";
+ public static final String CASE_INSENSITIVE_RESPONSE_HEADERS = "caseInsensitiveResponseHeaders";
public static final String PLAY_24 = "play24";
public static final String PLAY_25 = "play25";
@@ -90,6 +91,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
protected boolean useGzipFeature = false;
protected boolean useRuntimeException = false;
protected boolean useReflectionEqualsHashCode = false;
+ protected boolean caseInsensitiveResponseHeaders = false;
protected String authFolder;
public JavaClientCodegen() {
@@ -122,6 +124,8 @@ public JavaClientCodegen() {
cliOptions.add(CliOption.newBoolean(USE_RUNTIME_EXCEPTION, "Use RuntimeException instead of Exception"));
cliOptions.add(CliOption.newBoolean(FEIGN_VERSION, "Version of OpenFeign: '10.x', '9.x' (default)"));
cliOptions.add(CliOption.newBoolean(USE_REFLECTION_EQUALS_HASHCODE, "Use org.apache.commons.lang3.builder for equals and hashCode in the models. WARNING: This will fail under a security manager, unless the appropriate permissions are set up correctly and also there's potential performance impact."));
+ cliOptions.add(CliOption.newBoolean(CASE_INSENSITIVE_RESPONSE_HEADERS, "Make API response's headers case-insensitive in " + OKHTTP_GSON + " library"));
+
supportedLibraries.put(JERSEY1, "HTTP client: Jersey client 1.19.x. JSON processing: Jackson 2.8.x. Enable Java6 support using '-DsupportJava6=true'. Enable gzip request encoding using '-DuseGzipFeature=true'. IMPORTANT NOTE: jersey 1.x is no longer actively maintained so please upgrade to 'jersey2' or other HTTP libaries instead.");
supportedLibraries.put(JERSEY2, "HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.8.x");
@@ -232,6 +236,10 @@ public void processOpts() {
this.setUseReflectionEqualsHashCode(convertPropertyToBooleanAndWriteBack(USE_REFLECTION_EQUALS_HASHCODE));
}
+ if (additionalProperties.containsKey(CASE_INSENSITIVE_RESPONSE_HEADERS)) {
+ this.setUseReflectionEqualsHashCode(convertPropertyToBooleanAndWriteBack(CASE_INSENSITIVE_RESPONSE_HEADERS));
+ }
+
final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/");
final String apiFolder = (sourceFolder + '/' + apiPackage).replace(".", "/");
authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/");
@@ -659,6 +667,10 @@ public void setUseReflectionEqualsHashCode(boolean useReflectionEqualsHashCode)
this.useReflectionEqualsHashCode = useReflectionEqualsHashCode;
}
+ public void setCaseInsensitiveResponseHeaders(final Boolean caseInsensitiveResponseHeaders) {
+ this.caseInsensitiveResponseHeaders = caseInsensitiveResponseHeaders;
+ }
+
final private static Pattern JSON_MIME_PATTERN = Pattern.compile("(?i)application\\/json(;.*)?");
final private static Pattern JSON_VENDOR_MIME_PATTERN = Pattern.compile("(?i)application\\/vnd.(.*)+json(;.*)?");
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiResponse.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiResponse.mustache
index 3909393697cd..1f3f3a31981b 100644
--- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiResponse.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiResponse.mustache
@@ -4,6 +4,10 @@ package {{invokerPackage}};
import java.util.List;
import java.util.Map;
+{{#caseInsensitiveResponseHeaders}}
+import java.util.Map.Entry;
+import java.util.TreeMap;
+{{/caseInsensitiveResponseHeaders}}
/**
* API response returned by API call.
@@ -30,7 +34,13 @@ public class ApiResponse {
*/
public ApiResponse(int statusCode, Map> headers, T data) {
this.statusCode = statusCode;
- this.headers = headers;
+ {{#caseInsensitiveResponseHeaders}}
+ Map> responseHeaders = new TreeMap>(String.CASE_INSENSITIVE_ORDER);
+ for(Entry> entry : headers.entrySet()){
+ responseHeaders.put(entry.getKey().toLowerCase(), entry.getValue());
+ }
+ {{/caseInsensitiveResponseHeaders}}
+ this.headers = {{#caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}};
this.data = data;
}
diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/apiException.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/apiException.mustache
new file mode 100644
index 000000000000..e89524565917
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/apiException.mustache
@@ -0,0 +1,96 @@
+{{>licenseInfo}}
+
+package {{invokerPackage}};
+
+import java.util.Map;
+import java.util.List;
+{{#caseInsensitiveResponseHeaders}}
+import java.util.Map.Entry;
+import java.util.TreeMap;
+{{/caseInsensitiveResponseHeaders}}
+
+{{>generatedAnnotation}}
+public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{
+ private int code = 0;
+ private Map> responseHeaders = null;
+ private String responseBody = null;
+
+ public ApiException() {}
+
+ public ApiException(Throwable throwable) {
+ super(throwable);
+ }
+
+ public ApiException(String message) {
+ super(message);
+ }
+
+ public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) {
+ super(message, throwable);
+ this.code = code;
+ {{#caseInsensitiveResponseHeaders}}
+ Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER);
+ for(Entry> entry : responseHeaders.entrySet()){
+ headers.put(entry.getKey().toLowerCase(), entry.getValue());
+ }
+ {{/caseInsensitiveResponseHeaders}}
+ this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}};
+ this.responseBody = responseBody;
+ }
+
+ public ApiException(String message, int code, Map> responseHeaders, String responseBody) {
+ this(message, (Throwable) null, code, responseHeaders, responseBody);
+ }
+
+ public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) {
+ this(message, throwable, code, responseHeaders, null);
+ }
+
+ public ApiException(int code, Map> responseHeaders, String responseBody) {
+ this((String) null, (Throwable) null, code, responseHeaders, responseBody);
+ }
+
+ public ApiException(int code, String message) {
+ super(message);
+ this.code = code;
+ }
+
+ public ApiException(int code, String message, Map> responseHeaders, String responseBody) {
+ this(code, message);
+ {{#caseInsensitiveResponseHeaders}}
+ Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER);
+ for(Entry> entry : responseHeaders.entrySet()){
+ headers.put(entry.getKey().toLowerCase(), entry.getValue());
+ }
+ {{/caseInsensitiveResponseHeaders}}
+ this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}};
+ this.responseBody = responseBody;
+ }
+
+ /**
+ * Get the HTTP status code.
+ *
+ * @return HTTP status code
+ */
+ public int getCode() {
+ return code;
+ }
+
+ /**
+ * Get the HTTP response headers.
+ *
+ * @return A map of list of string
+ */
+ public Map> getResponseHeaders() {
+ return responseHeaders;
+ }
+
+ /**
+ * Get the HTTP response body.
+ *
+ * @return Response body in the form of string
+ */
+ public String getResponseBody() {
+ return responseBody;
+ }
+}