diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java index 1285391cef5..b9152047f38 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java @@ -2,6 +2,7 @@ import io.swagger.codegen.*; import io.swagger.codegen.languages.features.BeanValidationFeatures; +import io.swagger.codegen.languages.features.GzipFeatures; import io.swagger.codegen.languages.features.PerformBeanValidationFeatures; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; @@ -13,7 +14,9 @@ import java.util.regex.Pattern; public class JavaClientCodegen extends AbstractJavaCodegen - implements BeanValidationFeatures, PerformBeanValidationFeatures { + implements BeanValidationFeatures, PerformBeanValidationFeatures, + GzipFeatures +{ static final String MEDIA_TYPE = "mediaType"; @SuppressWarnings("hiding") @@ -36,6 +39,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen protected boolean parcelableModel = false; protected boolean useBeanValidation = false; protected boolean performBeanValidation = false; + protected boolean useGzipFeature = false; public JavaClientCodegen() { super(); @@ -53,11 +57,12 @@ public JavaClientCodegen() { cliOptions.add(CliOption.newBoolean(SUPPORT_JAVA6, "Whether to support Java6 with the Jersey1 library.")); cliOptions.add(CliOption.newBoolean(USE_BEANVALIDATION, "Use BeanValidation API annotations")); cliOptions.add(CliOption.newBoolean(PERFORM_BEANVALIDATION, "Perform BeanValidation")); + cliOptions.add(CliOption.newBoolean(USE_GZIP_FEATURE, "Send gzip-encoded requests")); - supportedLibraries.put("jersey1", "HTTP client: Jersey client 1.19.1. JSON processing: Jackson 2.7.0. Enable Java6 support using '-DsupportJava6=true'."); + supportedLibraries.put("jersey1", "HTTP client: Jersey client 1.19.1. JSON processing: Jackson 2.7.0. Enable Java6 support using '-DsupportJava6=true'. Enable gzip request encoding using '-DuseGzipFeature=true'."); supportedLibraries.put("feign", "HTTP client: Netflix Feign 8.16.0. JSON processing: Jackson 2.7.0"); supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.22.2. JSON processing: Jackson 2.7.0"); - supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.7.5. JSON processing: Gson 2.6.2. Enable Parcelable modles on Android using '-DparcelableModel=true'"); + supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.7.5. JSON processing: Gson 2.6.2. Enable Parcelable modles on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'."); supportedLibraries.put(RETROFIT_1, "HTTP client: OkHttp 2.7.5. JSON processing: Gson 2.3.1 (Retrofit 1.9.0). IMPORTANT NOTE: retrofit1.x is no longer actively maintained so please upgrade to 'retrofit2' instead."); supportedLibraries.put(RETROFIT_2, "HTTP client: OkHttp 3.2.0. JSON processing: Gson 2.6.1 (Retrofit 2.0.2). Enable the RxJava adapter using '-DuseRxJava[2]=true'. (RxJava 1.x or 2.x)"); @@ -119,6 +124,10 @@ public void processOpts() { this.setPerformBeanValidation(convertPropertyToBooleanAndWriteBack(PERFORM_BEANVALIDATION)); } + if (additionalProperties.containsKey(USE_GZIP_FEATURE)) { + this.setUseGzipFeature(convertPropertyToBooleanAndWriteBack(USE_GZIP_FEATURE)); + } + final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/"); final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/"); @@ -174,6 +183,7 @@ public void processOpts() { supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java")); supportingFiles.add(new SupportingFile("ProgressRequestBody.mustache", invokerFolder, "ProgressRequestBody.java")); supportingFiles.add(new SupportingFile("ProgressResponseBody.mustache", invokerFolder, "ProgressResponseBody.java")); + supportingFiles.add(new SupportingFile("GzipRequestInterceptor.mustache", invokerFolder, "GzipRequestInterceptor.java")); additionalProperties.put("gson", "true"); } else if (usesAnyRetrofitLibrary()) { supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java")); @@ -377,6 +387,10 @@ public void setPerformBeanValidation(boolean performBeanValidation) { this.performBeanValidation = performBeanValidation; } + public void setUseGzipFeature(boolean useGzipFeature) { + this.useGzipFeature = useGzipFeature; + } + 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/swagger-codegen/src/main/resources/Java/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache index 14a215eac4a..dac15cd9f83 100644 --- a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache @@ -15,6 +15,7 @@ import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.GenericType; import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter; import com.sun.jersey.api.client.filter.LoggingFilter; import com.sun.jersey.api.client.WebResource.Builder; @@ -110,6 +111,7 @@ public class ApiClient { DefaultClientConfig conf = new DefaultClientConfig(); conf.getSingletons().add(jsonProvider); Client client = Client.create(conf); + client.addFilter(new GZIPContentEncodingFilter({{#useGzipFeature}}true{{/useGzipFeature}}{{^useGzipFeature}}false{{/useGzipFeature}})); if (debugging) { client.addFilter(new LoggingFilter()); } diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache index 9c75d671607..a3f73d0b27b 100644 --- a/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache @@ -128,6 +128,11 @@ public class ApiClient { public ApiClient() { httpClient = new OkHttpClient(); + {{#useGzipFeature}} + // Enable gzip request compression + httpClient.interceptors().add(new GzipRequestInterceptor()); + {{/useGzipFeature}} + verifyingSsl = true; json = new JSON(this); diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/GzipRequestInterceptor.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/GzipRequestInterceptor.mustache new file mode 100644 index 00000000000..23224cf5d5b --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/GzipRequestInterceptor.mustache @@ -0,0 +1,70 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.squareup.okhttp.*; +import okio.Buffer; +import okio.BufferedSink; +import okio.GzipSink; +import okio.Okio; + +import java.io.IOException; + +/** + * Encodes request bodies using gzip. + * + * Taken from https://github.com/square/okhttp/issues/350 + */ +class GzipRequestInterceptor implements Interceptor { + @Override public Response intercept(Chain chain) throws IOException { + Request originalRequest = chain.request(); + if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { + return chain.proceed(originalRequest); + } + + Request compressedRequest = originalRequest.newBuilder() + .header("Content-Encoding", "gzip") + .method(originalRequest.method(), forceContentLength(gzip(originalRequest.body()))) + .build(); + return chain.proceed(compressedRequest); + } + + private RequestBody forceContentLength(final RequestBody requestBody) throws IOException { + final Buffer buffer = new Buffer(); + requestBody.writeTo(buffer); + return new RequestBody() { + @Override + public MediaType contentType() { + return requestBody.contentType(); + } + + @Override + public long contentLength() { + return buffer.size(); + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + sink.write(buffer.snapshot()); + } + }; + } + + private RequestBody gzip(final RequestBody body) { + return new RequestBody() { + @Override public MediaType contentType() { + return body.contentType(); + } + + @Override public long contentLength() { + return -1; // We don't know the compressed length in advance! + } + + @Override public void writeTo(BufferedSink sink) throws IOException { + BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); + body.writeTo(gzipSink); + gzipSink.close(); + } + }; + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaClientOptionsProvider.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaClientOptionsProvider.java index cc0f3217403..3a4ddc208f8 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaClientOptionsProvider.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaClientOptionsProvider.java @@ -23,6 +23,7 @@ public Map createOptions() { options.put(JavaClientCodegen.SUPPORT_JAVA6, "false"); options.put(JavaClientCodegen.USE_BEANVALIDATION, "false"); options.put(JavaClientCodegen.PERFORM_BEANVALIDATION, PERFORM_BEANVALIDATION); + options.put(JavaClientCodegen.USE_GZIP_FEATURE, "false"); return options; } diff --git a/samples/client/petstore/java/jersey1/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/jersey1/src/main/java/io/swagger/client/ApiClient.java index de98188515a..90f05be0078 100644 --- a/samples/client/petstore/java/jersey1/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/jersey1/src/main/java/io/swagger/client/ApiClient.java @@ -21,6 +21,7 @@ import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.GenericType; import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter; import com.sun.jersey.api.client.filter.LoggingFilter; import com.sun.jersey.api.client.WebResource.Builder; @@ -111,6 +112,7 @@ public ApiClient rebuildHttpClient() { DefaultClientConfig conf = new DefaultClientConfig(); conf.getSingletons().add(jsonProvider); Client client = Client.create(conf); + client.addFilter(new GZIPContentEncodingFilter(false)); if (debugging) { client.addFilter(new LoggingFilter()); } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java index d014d7d4035..64e0e9a04a9 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java @@ -139,6 +139,7 @@ public class ApiClient { public ApiClient() { httpClient = new OkHttpClient(); + verifyingSsl = true; json = new JSON(this); diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/GzipRequestInterceptor.java b/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/GzipRequestInterceptor.java new file mode 100644 index 00000000000..cc4e4f951c1 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/GzipRequestInterceptor.java @@ -0,0 +1,81 @@ +/* + * Swagger Petstore + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ + * + * OpenAPI spec version: 1.0.0 + * Contact: apiteam@swagger.io + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +package io.swagger.client; + +import com.squareup.okhttp.*; +import okio.Buffer; +import okio.BufferedSink; +import okio.GzipSink; +import okio.Okio; + +import java.io.IOException; + +/** + * Encodes request bodies using gzip. + * + * Taken from https://github.com/square/okhttp/issues/350 + */ +class GzipRequestInterceptor implements Interceptor { + @Override public Response intercept(Chain chain) throws IOException { + Request originalRequest = chain.request(); + if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { + return chain.proceed(originalRequest); + } + + Request compressedRequest = originalRequest.newBuilder() + .header("Content-Encoding", "gzip") + .method(originalRequest.method(), forceContentLength(gzip(originalRequest.body()))) + .build(); + return chain.proceed(compressedRequest); + } + + private RequestBody forceContentLength(final RequestBody requestBody) throws IOException { + final Buffer buffer = new Buffer(); + requestBody.writeTo(buffer); + return new RequestBody() { + @Override + public MediaType contentType() { + return requestBody.contentType(); + } + + @Override + public long contentLength() { + return buffer.size(); + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + sink.write(buffer.snapshot()); + } + }; + } + + private RequestBody gzip(final RequestBody body) { + return new RequestBody() { + @Override public MediaType contentType() { + return body.contentType(); + } + + @Override public long contentLength() { + return -1; // We don't know the compressed length in advance! + } + + @Override public void writeTo(BufferedSink sink) throws IOException { + BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); + body.writeTo(gzipSink); + gzipSink.close(); + } + }; + } +} \ No newline at end of file