Skip to content

Commit

Permalink
Make Content-Encoding configurable
Browse files Browse the repository at this point in the history
A new configuration property was added to make the Content-Encoding
configurable when using the feign request compression. The default
values are the same as the previous hardcoded values.

Closes issue 1048
  • Loading branch information
AndreTeigler committed Sep 8, 2024
1 parent a11a442 commit 4d99120
Show file tree
Hide file tree
Showing 3 changed files with 226 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* The Feign encoding properties.
*
* @author Jakub Narloch
* @author André Teigler
*/
@ConfigurationProperties("spring.cloud.openfeign.compression.request")
public class FeignClientEncodingProperties {
Expand All @@ -39,6 +40,11 @@ public class FeignClientEncodingProperties {
*/
private int minRequestSize = 2048;

/**
* The list of content encodings (applicable encodings depend on the used client).
*/
private String[] contentEncodings = new String[] { HttpEncoding.GZIP_ENCODING, HttpEncoding.DEFLATE_ENCODING };

public String[] getMimeTypes() {
return mimeTypes;
}
Expand All @@ -55,6 +61,14 @@ public void setMinRequestSize(int minRequestSize) {
this.minRequestSize = minRequestSize;
}

public String[] getContentEncodings() {
return contentEncodings;
}

public void setContentEncodings(String[] contentEncodings) {
this.contentEncodings = contentEncodings;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -64,7 +78,8 @@ public boolean equals(Object o) {
return false;
}
FeignClientEncodingProperties that = (FeignClientEncodingProperties) o;
return Arrays.equals(mimeTypes, that.mimeTypes) && Objects.equals(minRequestSize, that.minRequestSize);
return Arrays.equals(mimeTypes, that.mimeTypes) && Objects.equals(minRequestSize, that.minRequestSize)
&& Arrays.equals(contentEncodings, that.contentEncodings);
}

@Override
Expand All @@ -79,6 +94,9 @@ public String toString() {
.append(", ")
.append("minRequestSize=")
.append(minRequestSize)
.append(", ")
.append("contentEncodings=")
.append(Arrays.toString(contentEncodings))
.append("}")
.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,18 @@ protected FeignContentGzipEncodingInterceptor(FeignClientEncodingProperties prop
public void apply(RequestTemplate template) {

if (requiresCompression(template)) {
addHeader(template, HttpEncoding.CONTENT_ENCODING_HEADER, HttpEncoding.GZIP_ENCODING,
HttpEncoding.DEFLATE_ENCODING);
addHeader(template, HttpEncoding.CONTENT_ENCODING_HEADER, getContentEncodings());
}
}

private String[] getContentEncodings() {
if (getProperties().getContentEncodings() != null && getProperties().getContentEncodings().length > 0) {
return getProperties().getContentEncodings();
}

return new String[] { HttpEncoding.GZIP_ENCODING, HttpEncoding.DEFLATE_ENCODING };
}

/**
* Returns whether the request requires GZIP compression.
* @param template the request template
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* Copyright 2013-2022 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.cloud.openfeign.encoding;

import java.util.List;

import feign.RequestTemplate;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Unit tests for {@link FeignContentGzipEncodingInterceptor}
*
* @author André Teigler
*/
class FeignContentGzipEncodingInterceptorTest {

@Test
void apply_SizeBelowThreshold_NoCompressionHeader() {

final var properties = new FeignClientEncodingProperties();

final var template = new RequestTemplate();

template.header(HttpEncoding.CONTENT_LENGTH, "2047");
template.header(HttpEncoding.CONTENT_TYPE, "application/json");

final var interceptor = new FeignContentGzipEncodingInterceptor(properties);

interceptor.apply(template);

assertThat(template.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)).isFalse();
}

@Test
void apply_SizeEqualsThreshold_NoCompressionHeader() {

final var properties = new FeignClientEncodingProperties();

final var template = new RequestTemplate();

template.header(HttpEncoding.CONTENT_LENGTH, "2048");
template.header(HttpEncoding.CONTENT_TYPE, "application/json");

final var interceptor = new FeignContentGzipEncodingInterceptor(properties);

interceptor.apply(template);

assertThat(template.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)).isFalse();
}

@Test
void apply_SizeAboveThreshold_DefaultCompressionHeader() {

final var properties = new FeignClientEncodingProperties();

final var template = new RequestTemplate();

template.header(HttpEncoding.CONTENT_LENGTH, "2049");
template.header(HttpEncoding.CONTENT_TYPE, "application/json");

final var interceptor = new FeignContentGzipEncodingInterceptor(properties);

interceptor.apply(template);

assertThat(template.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)).isTrue();
assertThat(template.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER)).isEqualTo(List.of("gzip", "deflate"));
}

@Test
void apply_MimeTypeMismatch_NoCompressionHeader() {

final var properties = new FeignClientEncodingProperties();
properties.setMimeTypes(new String[] { "application/xml" });

final var template = new RequestTemplate();

template.header(HttpEncoding.CONTENT_LENGTH, "2049");
template.header(HttpEncoding.CONTENT_TYPE, "application/json");

final var interceptor = new FeignContentGzipEncodingInterceptor(properties);

interceptor.apply(template);

assertThat(template.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)).isFalse();
}

@Test
void apply_NoMimeTypeSet_DefaultCompressionHeader() {

final var properties = new FeignClientEncodingProperties();
properties.setMimeTypes(new String[] {});

final var template = new RequestTemplate();

template.header(HttpEncoding.CONTENT_LENGTH, "2049");
template.header(HttpEncoding.CONTENT_TYPE, "application/json");

final var interceptor = new FeignContentGzipEncodingInterceptor(properties);

interceptor.apply(template);

assertThat(template.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)).isTrue();
assertThat(template.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER)).isEqualTo(List.of("gzip", "deflate"));
}

@Test
void apply_NullMimeTypeSet_DefaultCompressionHeader() {

final var properties = new FeignClientEncodingProperties();
properties.setMimeTypes(null);

final var template = new RequestTemplate();

template.header(HttpEncoding.CONTENT_LENGTH, "2049");
template.header(HttpEncoding.CONTENT_TYPE, "application/json");

final var interceptor = new FeignContentGzipEncodingInterceptor(properties);

interceptor.apply(template);

assertThat(template.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)).isTrue();
assertThat(template.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER)).isEqualTo(List.of("gzip", "deflate"));
}

@Test
void apply_NonDefaultContentEncodingSet_CustomCompressionHeader() {

final var properties = new FeignClientEncodingProperties();
properties.setContentEncodings(new String[] { "gzip" });

final var template = new RequestTemplate();

template.header(HttpEncoding.CONTENT_LENGTH, "2049");
template.header(HttpEncoding.CONTENT_TYPE, "application/json");

final var interceptor = new FeignContentGzipEncodingInterceptor(properties);

interceptor.apply(template);

assertThat(template.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)).isTrue();
assertThat(template.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER)).isEqualTo(List.of("gzip"));
}

@Test
void apply_NoContentEncodingsSet_DefaultCompressionHeader() {

final var properties = new FeignClientEncodingProperties();
properties.setContentEncodings(new String[] {});

final var template = new RequestTemplate();

template.header(HttpEncoding.CONTENT_LENGTH, "2049");
template.header(HttpEncoding.CONTENT_TYPE, "application/json");

final var interceptor = new FeignContentGzipEncodingInterceptor(properties);

interceptor.apply(template);

assertThat(template.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)).isTrue();
assertThat(template.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER)).isEqualTo(List.of("gzip", "deflate"));
}

@Test
void apply_NullContentEncodingsSet_DefaultCompressionHeader() {

final var properties = new FeignClientEncodingProperties();
properties.setContentEncodings(null);

final var template = new RequestTemplate();

template.header(HttpEncoding.CONTENT_LENGTH, "2049");
template.header(HttpEncoding.CONTENT_TYPE, "application/json");

final var interceptor = new FeignContentGzipEncodingInterceptor(properties);

interceptor.apply(template);

assertThat(template.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)).isTrue();
assertThat(template.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER)).isEqualTo(List.of("gzip", "deflate"));
}

}

0 comments on commit 4d99120

Please sign in to comment.