Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding gzip support for Spring Decoder #230

Merged

Conversation

jskim1991
Copy link
Contributor

fixes #229, #145

Based on my usage of FeignClient, I was only able to get gzip content. So I only added test for gzip decompression. If there is a need to add support for other content-encoding with different types of http clients, please provide me some information and we can work on it together.

Thanks :)

@pivotal-issuemaster
Copy link

@jskim1991 Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

@holy12345
Copy link
Contributor

Hi @jskim1991 thanks for you PR. Test failed please fixed it.

On the other thing just exchange ideas, I see the judgment logic in SpringDecoder. Do you think create new class and put logic in this class. because SpringDecoder is default.(Loaded into the container by Spring by default)

The source code

	@Bean
	@ConditionalOnMissingBean
	public Decoder feignDecoder() {
		return new OptionalDecoder(
				new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
	}

So I think If the property feign.compression.response.enabled is true, spring does not load the default class but loads the class that supports gzip.
So the order looks like this:

  • If the client customizes Decode then Spring loads the custom Decode.
  • If the property feign.compression.response.enabled is true then Spring loads the gizp decode.
  • if no things customizes then spring loads the SpringDecoder.

Any Thoughts?

: null;

if (encoding != null) {
if (encoding.contains(HttpEncoding.GZIP_ENCODING)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make this behaviour optional and not turned on by default in order to maintain backwards compatibility. You can, for example make it dependant on a new property.

if (encoding != null) {
if (encoding.contains(HttpEncoding.GZIP_ENCODING)) {
Response build = response.toBuilder()
.body(this.decompress(response).getBytes()).build();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

decompress(response) can return null - add nullcheck.

.isEqualTo(new Hello("hello world via response"));
}

public static class Hello {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this have to be public?

@pivotal-issuemaster
Copy link

@jskim1991 Thank you for signing the Contributor License Agreement!

@OlgaMaciaszek OlgaMaciaszek added enhancement New feature or request and removed waiting-for-triage labels Oct 16, 2019
@OlgaMaciaszek OlgaMaciaszek added this to In progress in Hoxton.RC1 via automation Oct 16, 2019
@OlgaMaciaszek OlgaMaciaszek added this to the 2.1.4.RELEASE milestone Oct 16, 2019
@OlgaMaciaszek
Copy link
Collaborator

@holy12345 - I agree with you, with the distinction that I still would like to see maybe an additional property used to opt in apart from feign.compression.response.enabled, cause we would be changing behaviour in a minor version and could cause issues for users that handled it on their own. We cannot add breaking changes in a minor.

@OlgaMaciaszek
Copy link
Collaborator

Build seems to be failing due to a circleci-related issue. Contacting them to find out what the problem is.

@OlgaMaciaszek
Copy link
Collaborator

@jskim1991 I have merged this fix for the circleci issue: https://github.com/spring-cloud/spring-cloud-openfeign/pull/231/files Plese merge master to your branch to get this commit and rebuild the PR.

@jskim1991
Copy link
Contributor Author

@OlgaMaciaszek, thank you so much for your feedback. I will work on it to meet your directions and let you know.

@jskim1991
Copy link
Contributor Author

jskim1991 commented Oct 17, 2019

@OlgaMaciaszek, i thought about your comment on backward compatibility. If users customized feign.codec.Decoder, it doesn't use SpringDecoder and also, the logic checks for Http Header to see what content type is returned. If you really want me to add a new property, I will do so but I am not sure why that would fail in normal cases as well as when customized decoder is implemented. Please let me know. Thanks :)

Edit: i guess one possible way is they do decompression part and use SpringDecoder on the decompressed response. I think your request for an additional property makes sense.

@codecov
Copy link

codecov bot commented Oct 19, 2019

Codecov Report

Merging #230 into master will increase coverage by 0.53%.
The diff coverage is 83.33%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master     #230      +/-   ##
============================================
+ Coverage     76.44%   76.98%   +0.53%     
- Complexity      336      345       +9     
============================================
  Files            41       43       +2     
  Lines          1422     1451      +29     
  Branches        207      213       +6     
============================================
+ Hits           1087     1117      +30     
+ Misses          246      241       -5     
- Partials         89       93       +4
Impacted Files Coverage Δ Complexity Δ
...mework/cloud/openfeign/FeignAutoConfiguration.java 88.88% <ø> (ø) 3 <0> (ø) ⬇️
...amework/cloud/openfeign/support/SpringEncoder.java 75.86% <100%> (+0.42%) 11 <0> (ø) ⬇️
...feign/support/DefaultGzipDecoderConfiguration.java 100% <100%> (ø) 2 <2> (?)
...rk/cloud/openfeign/support/DefaultGzipDecoder.java 79.16% <79.16%> (ø) 6 <6> (?)
...bbon/HttpClientFeignLoadBalancedConfiguration.java 91.17% <0%> (-5.89%) 2% <0%> (ø)
...mework/cloud/openfeign/FeignClientFactoryBean.java 72.35% <0%> (+4.7%) 47% <0%> (+1%) ⬆️

@jskim1991
Copy link
Contributor Author

jskim1991 commented Oct 19, 2019

@OlgaMaciaszek I committed some new changes to support backward compatibility as you requested. Please let me know if there is anything I need to change to make it better. Thanks :)

Edit: I was thinking about which would be a better way to inject gzipdecoder. Let me know what you think of it.

  1. new OptionalDecoder(new ResponseEntityDecoder(new DefaultGzipDecoder(new SpringDecoder)))
  2. new DefaultGzipDecoder(new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder)))

I tried both and don't see much difference. Going with option 1 made sense to me initially since OptionalDecoder and ResponseEntityDecoder have some logic and flow to get to a specific point in SpringDecoder. So I think it is aligned with the previous design where it starts from OptionalDecoder and goes in order.

@jskim1991
Copy link
Contributor Author

@OlgaMaciaszek I am still waiting for your feedback

@@ -39,7 +39,7 @@
@EnableConfigurationProperties(FeignClientEncodingProperties.class)
@ConditionalOnClass(Feign.class)
@ConditionalOnBean(Client.class)
@ConditionalOnProperty(value = "feign.compression.response.enabled",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the havingValue property is not necessary

@@ -42,7 +42,7 @@
// The OK HTTP client uses "transparent" compression.
// If the content-encoding header is present it disable transparent compression
@ConditionalOnMissingBean(type = "okhttp3.OkHttpClient")
@ConditionalOnProperty(value = "feign.compression.request.enabled",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the havingValue property is not necessary

}
GZIPInputStream gzipInputStream = new GZIPInputStream(
response.body().asInputStream());
BufferedReader reader = new BufferedReader(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you need to close these readers

}

@Bean
@ConditionalOnProperty(value = "feign.compression.response.useGzipDecoder",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add some documentation about the new property

@ryanjbaxter ryanjbaxter modified the milestones: 2.1.4.RELEASE, 2.2.0.RC1 Oct 28, 2019
@ryanjbaxter ryanjbaxter added this to In progress in Hoxton.RC2 via automation Oct 28, 2019
@ryanjbaxter ryanjbaxter removed this from In progress in Hoxton.RC1 Oct 28, 2019
@jskim1991
Copy link
Contributor Author

@ryanjbaxter I have made some changes that you requested. Please let me know if there is anything else I need to change. Thanks :)

Copy link
Collaborator

@OlgaMaciaszek OlgaMaciaszek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but there are still some things that should be fixed.

*/
@Configuration
@ConditionalOnProperty(value = "feign.compression.response.enabled",
matchIfMissing = false)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matchIfMissing = false is not needed. That's the default. value = is not needed.

import org.springframework.cloud.openfeign.encoding.HttpEncoding;

/**
* When response is compressed as gzip, this decompresses and uses SpringDecoder to
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to {@link SpringDecoder}

@ConditionalOnProperty(value = "feign.compression.response.enabled",
matchIfMissing = false)
// The OK HTTP client uses "transparent" compression.
// If the accept-encoding header is present it disable transparent compression
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix the grammar and punctuation:
If the accept-encoding header is present, it disables transparent compression.

}

@Bean
@ConditionalOnProperty(value = "feign.compression.response.useGzipDecoder",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove value = and matchIfMissing = false. They are unnecessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this, i see most configs use dashes between words in the documentation. Should I change this property name from camel case to dashes?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spring will automatically do that

this.messageConverters = messageConverters;
}

@Bean
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably have a @ConditionalOnMissingBean here, i.e., if the user provides their own Decoder implementation, that should have priority and, at the same time, ensure that this configuration is processed before the FeignClientsConfiguration that provides its own @Bean @ConditionalOnMissingBean Decoder.

@jskim1991
Copy link
Contributor Author

@OlgaMaciaszek Thank you for feedback. Please let me know what else I need to change.

Copy link
Collaborator

@OlgaMaciaszek OlgaMaciaszek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good now.

@OlgaMaciaszek OlgaMaciaszek merged commit bc10583 into spring-cloud:master Nov 4, 2019
Hoxton.RC2 automation moved this from In progress to Done Nov 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
No open projects
Hoxton.RC2
  
Done
Development

Successfully merging this pull request may close these issues.

spring boot server.compression conflict with feign.compression
6 participants