Compare commits

..
28 Commits
Author SHA1 Message Date
buildmaster e8eb5c3d08 Bumping versions 2022-07-27 10:47:29 +00:00
buildmaster f3bf53acd6 Bumping versions to 3.0.9-SNAPSHOT after release 2022-07-27 10:27:42 +00:00
buildmaster a1115f6044 Going back to snapshots 2022-07-27 10:27:42 +00:00
buildmaster d111204007 Update SNAPSHOT to 3.0.8 2022-07-27 10:26:03 +00:00
fml2 b4c9567de5 Update spring-cloud-openfeign.adoc 2022-07-25 16:00:28 +02:00
Nikita Konev 8fdb488697 fix cascading deserialization Spring Data's Page by setting @JsonIgnoreProperties(ignoreUnknown = true), revert ignoring getTotalPages(), getNumberOfElements(), isFirst(), isLast() (#653) 2022-07-25 15:12:22 +02:00
buildmaster 7e01355317 Bumping versions to 3.0.8-SNAPSHOT after release 2022-06-29 22:15:46 +00:00
buildmaster fc459044b5 Going back to snapshots 2022-06-29 22:15:46 +00:00
buildmaster e321e72e3d Update SNAPSHOT to 3.0.7 2022-06-29 22:14:15 +00:00
Olga Maciaszek-Sharma ae63aae6eb Add deprecations for OAuth2. 2022-06-29 17:40:23 +02:00
Olga Maciaszek-Sharma 10fefea29b Remove incompatible test. 2022-06-28 15:46:11 +02:00
Olga MaciaszekSharma 24d9b08d5c Backport bugfix and resolve conflicts. 2022-06-28 15:36:06 +02:00
Olga Maciaszek-Sharma d4832788f6 Resolve conflicts for backport. 2022-06-28 15:02:16 +02:00
Olga Maciaszek-Sharma ff96850ec0 Wrap underlying checked exception with IllegalStateException. Add tests. 2022-06-28 14:53:37 +02:00
Olga Maciaszek-Sharma 9023cc2dc5 Unwarap InvocationTargetException and NoFallbackAvailableException. 2022-06-28 14:53:27 +02:00
Olga Maciaszek-Sharma 6c3b8c257e Fixes gh-680. 2022-06-28 14:44:00 +02:00
buildmaster fe43b6c52b Bumping versions 2022-02-24 10:52:51 +00:00
Olga MaciaszekSharma 3e5aa41490 Update license entries. 2022-01-11 14:47:10 +01:00
Olga Maciaszek-Sharma 3a1d19f74f Upgarde protobuf-java (security fix) and vavr. (#663) 2022-01-11 14:12:31 +01:00
buildmaster 0853ccc1e5 Bumping versions to 3.0.7-SNAPSHOT after release 2021-12-15 17:02:34 +00:00
buildmaster 13f91320b1 Going back to snapshots 2021-12-15 17:02:33 +00:00
buildmaster 7af0efd569 Update SNAPSHOT to 3.0.6 2021-12-15 17:01:03 +00:00
Been24 70a9002002 Update RetryableFeignBlockingLoadBalancerClient.java
fix log  class
2021-11-29 16:45:40 +01:00
Nikita Konev ad892a23f0 Support size = 0 in PageJacksonModule 2021-11-29 16:30:20 +01:00
Hyeonmin Park c0f314a5f0 GitHub workflows: Use Java version in matrix, cache functionality of actions/setup-java@v2 (#614)
* Fix GitHub workflows not using Java version in matrix

* Use cache functionality of actions/setup-java@v2
2021-10-28 18:15:02 +02:00
buildmaster 56dc4e07e4 Bumping versions to 3.0.6-SNAPSHOT after release 2021-10-21 11:48:48 +00:00
buildmaster 9167752bfb Going back to snapshots 2021-10-21 11:48:47 +00:00
buildmaster 127c866616 Update SNAPSHOT to 3.0.5 2021-10-21 11:46:52 +00:00
186 changed files with 836 additions and 883 deletions
+7 -12
View File
@@ -5,9 +5,9 @@ name: Build
on:
push:
branches: [ main ]
branches: [ 3.0.x ]
pull_request:
branches: [ main ]
branches: [ 3.0.x ]
jobs:
build:
@@ -20,17 +20,12 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v2
with:
java-version: 1.8
- name: Cache local Maven repository
uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
distribution: 'zulu'
java-version: ${{ matrix.java }}
cache: 'maven'
- name: Build with Maven
run: ./mvnw clean install -B -U -P sonar
- uses: codecov/codecov-action@v1
+53 -1
View File
@@ -40,7 +40,8 @@ and binding to the Spring Environment and other Spring programming model idioms.
== Building
:jdkversion: 1.8
:jdkversion: 17
=== Basic Compile and Test
@@ -303,6 +304,57 @@ Go to `File` -> `Settings` -> `Other settings` -> `Checkstyle`. There click on t
IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources.
=== Duplicate Finder
Spring Cloud Build brings along the `basepom:duplicate-finder-maven-plugin`, that enables flagging duplicate and conflicting classes and resources on the java classpath.
==== Duplicate Finder configuration
Duplicate finder is *enabled by default* and will run in the `verify` phase of your Maven build, but it will only take effect in your project if you add the `duplicate-finder-maven-plugin` to the `build` section of the projecst's `pom.xml`.
.pom.xml
[source,xml]
----
<build>
<plugins>
<plugin>
<groupId>org.basepom.maven</groupId>
<artifactId>duplicate-finder-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
----
For other properties, we have set defaults as listed in the https://github.com/basepom/duplicate-finder-maven-plugin/wiki[plugin documentation].
You can easily override them but setting the value of the selected property prefixed with `duplicate-finder-maven-plugin`. For example, set `duplicate-finder-maven-plugin.skip` to `true` in order to skip duplicates check in your build.
If you need to add `ignoredClassPatterns` or `ignoredResourcePatterns` to your setup, make sure to add them in the plugin configuration section of your project:
[source,xml]
----
<build>
<plugins>
<plugin>
<groupId>org.basepom.maven</groupId>
<artifactId>duplicate-finder-maven-plugin</artifactId>
<configuration>
<ignoredClassPatterns>
<ignoredClassPattern>org.joda.time.base.BaseDateTime</ignoredClassPattern>
<ignoredClassPattern>.*module-info</ignoredClassPattern>
</ignoredClassPatterns>
<ignoredResourcePatterns>
<ignoredResourcePattern>changelog.txt</ignoredResourcePattern>
</ignoredResourcePatterns>
</configuration>
</plugin>
</plugins>
</build>
----
== License
The project license file is available https://raw.githubusercontent.com/spring-cloud/spring-cloud-openfeign/main/LICENSE.txt[here].
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>3.1.0-M4</version>
<version>3.0.8-SNAPSHOT</version>
</parent>
<artifactId>spring-cloud-openfeign-docs</artifactId>
<packaging>jar</packaging>
+1
View File
@@ -13,6 +13,7 @@
|feign.compression.request.mime-types | `[text/xml, application/xml, application/json]` | The list of supported mime types.
|feign.compression.request.min-request-size | `2048` | The minimum threshold content size.
|feign.compression.response.enabled | `false` | Enables the response from Feign to be compressed.
|feign.compression.response.useGzipDecoder | `false` | Enables the default gzip decoder to be used.
|feign.encoder.charset-from-content-type | `false` | Indicates whether the charset should be derived from the {@code Content-Type} header.
|feign.httpclient.connection-timeout | `2000` |
|feign.httpclient.connection-timer-repeat | `3000` |
-1
View File
@@ -1 +0,0 @@
include::spring-cloud-openfeign.adoc[]
+1
View File
@@ -0,0 +1 @@
spring-cloud-openfeign.adoc
@@ -52,9 +52,6 @@ public interface StoreClient {
@RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
Store update(@PathVariable("storeId") Long storeId, Store store);
@RequestMapping(method = RequestMethod.DELETE, value = "/stores/{storeId:\\d+}")
void delete(@PathVariable Long storeId);
}
----
@@ -200,7 +197,7 @@ feign:
Default configurations can be specified in the `@EnableFeignClients` attribute `defaultConfiguration` in a similar manner as described above. The difference is that this configuration will apply to _all_ feign clients.
If you prefer using configuration properties to configured all `@FeignClient`, you can create configuration properties with `default` feign name.
If you prefer using configuration properties to configure all `@FeignClient`, you can create configuration properties with `default` feign name.
You can use `feign.client.config.feignName.defaultQueryParameters` and `feign.client.config.feignName.defaultRequestHeaders` to specify query parameters and headers that will be sent with every request of the client named `feignName`.
@@ -518,6 +515,14 @@ feign.compression.request.min-request-size=2048
These properties allow you to be selective about the compressed media types and minimum request threshold length.
For http clients except OkHttpClient, default gzip decoder can be enabled to decode gzip response in UTF-8 encoding:
[source,java]
----
feign.compression.response.enabled=true
feign.compression.response.useGzipDecoder=true
----
=== Feign logging
A logger is created for each Feign client created. By default the name of the logger is the full class name of the interface used to create the Feign client. Feign logging only responds to the `DEBUG` level.
@@ -689,21 +694,20 @@ public interface DemoTemplate {
----
=== Feign `CollectionFormat` support
We support `feign.CollectionFormat` by providing the `@CollectionFormat` annotation.
You can annotate a Feign client method (or the whole class to affect all methods) with it by passing the desired `feign.CollectionFormat` as annotation value.
We support `feign.CollectionFormat` by providing the `@CollectionFormat` annotation.You can annotate a Feign client method with it by passing the desired `feign.CollectionFormat` as annotation value.
In the following example, the `CSV` format is used instead of the default `EXPLODED` to process the method.
[source,java,indent=0]
----
@FeignClient(name = "demo")
protected interface PageableFeignClient {
protected interface PageableFeignClient {
@CollectionFormat(feign.CollectionFormat.CSV)
@GetMapping(path = "/page")
ResponseEntity performRequest(Pageable page);
@CollectionFormat(feign.CollectionFormat.CSV)
@GetMapping(path = "/page")
ResponseEntity performRequest(Pageable page);
}
}
----
TIP: Set the `CSV` format while sending `Pageable` as a query parameter in order for it to be encoded correctly.
+3 -3
View File
@@ -4,14 +4,14 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-openfeign</artifactId>
<version>3.1.0-M4</version>
<version>3.0.8-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Cloud OpenFeign</name>
<description>Spring Cloud OpenFeign</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>3.1.0-M3</version>
<version>3.0.5</version>
<relativePath/>
</parent>
<scm>
@@ -26,7 +26,7 @@
<properties>
<main.basedir>${basedir}</main.basedir>
<jackson.version>2.11.3</jackson.version>
<spring-cloud-commons.version>3.1.0-M3</spring-cloud-commons.version>
<spring-cloud-commons.version>3.0.7-SNAPSHOT</spring-cloud-commons.version>
<!-- Plugin versions -->
<maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version>
+3 -3
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>3.1.0-M4</version>
<version>3.0.8-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-openfeign-core</artifactId>
@@ -183,13 +183,13 @@
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.14.0</version>
<version>3.19.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.10.3</version>
<version>0.10.4</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -25,10 +25,9 @@ import java.lang.annotation.Target;
* Indicates which collection format should be used while processing the annotated method.
*
* @author Olga Maciaszek-Sharma
* @author Sam Kruglov
* @see feign.CollectionFormat
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CollectionFormat {
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 the original author or authors.
* Copyright 2016-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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -58,6 +58,7 @@ import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory;
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor;
import org.springframework.cloud.openfeign.support.DefaultGzipDecoderConfiguration;
import org.springframework.cloud.openfeign.support.FeignEncoderProperties;
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
import org.springframework.cloud.openfeign.support.PageJacksonModule;
@@ -86,6 +87,7 @@ import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResour
@ConditionalOnClass(Feign.class)
@EnableConfigurationProperties({ FeignClientProperties.class, FeignHttpClientProperties.class,
FeignEncoderProperties.class })
@Import(DefaultGzipDecoderConfiguration.class)
public class FeignAutoConfiguration {
private static final Log LOG = LogFactory.getLog(FeignAutoConfiguration.class);
@@ -310,6 +312,7 @@ public class FeignAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(OAuth2ClientContext.class)
@ConditionalOnProperty("feign.oauth2.enabled")
@Deprecated // spring-security-oauth2 reached EOL
protected static class Oauth2FeignConfiguration {
@Bean
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -17,6 +17,7 @@
package org.springframework.cloud.openfeign;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.LinkedHashMap;
@@ -29,6 +30,7 @@ import feign.Target;
import org.springframework.cloud.client.circuitbreaker.CircuitBreaker;
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.client.circuitbreaker.NoFallbackAvailableException;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
@@ -95,15 +97,29 @@ class FeignCircuitBreakerInvocationHandler implements InvocationHandler {
try {
return this.fallbackMethodMap.get(method).invoke(fallback, args);
}
catch (Exception e) {
throw new IllegalStateException(e);
catch (Exception exception) {
unwrapAndRethrow(exception);
}
return null;
};
return circuitBreaker.run(supplier, fallbackFunction);
}
return circuitBreaker.run(supplier);
}
private void unwrapAndRethrow(Exception exception) {
if (exception instanceof InvocationTargetException || exception instanceof NoFallbackAvailableException) {
Throwable underlyingException = exception.getCause();
if (underlyingException instanceof RuntimeException) {
throw (RuntimeException) underlyingException;
}
if (underlyingException != null) {
throw new IllegalStateException(underlyingException);
}
throw new IllegalStateException(exception);
}
}
private Supplier<Object> asSupplier(final Method method, final Object[] args) {
final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
return () -> {
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -443,6 +443,9 @@ public class FeignClientFactoryBean
}
private String cleanPath() {
if (path == null) {
return "";
}
String path = this.path.trim();
if (StringUtils.hasLength(path)) {
if (!path.startsWith("/")) {
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2021 the original author or authors.
* Copyright 2021-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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -47,7 +47,6 @@ import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
import org.springframework.cloud.openfeign.clientconfig.FeignClientConfigurer;
import org.springframework.cloud.openfeign.support.AbstractFormWriter;
import org.springframework.cloud.openfeign.support.FeignEncoderProperties;
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
import org.springframework.cloud.openfeign.support.PageableSpringEncoder;
import org.springframework.cloud.openfeign.support.PageableSpringQueryMapEncoder;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
@@ -71,7 +70,6 @@ import static feign.form.ContentType.MULTIPART;
* @author Jonatan Ivanov
* @author Olga Maciaszek-Sharma
* @author Hyeonmin Park
* @author Yanming Zhou
*/
@Configuration(proxyBeanMethods = false)
public class FeignClientsConfiguration {
@@ -99,25 +97,22 @@ public class FeignClientsConfiguration {
@Bean
@ConditionalOnMissingBean
public Decoder feignDecoder(ObjectProvider<HttpMessageConverterCustomizer> customizers) {
return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(messageConverters, customizers)));
public Decoder feignDecoder() {
return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnMissingClass("org.springframework.data.domain.Pageable")
public Encoder feignEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider,
ObjectProvider<HttpMessageConverterCustomizer> customizers) {
return springEncoder(formWriterProvider, encoderProperties, customizers);
public Encoder feignEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider) {
return springEncoder(formWriterProvider, encoderProperties);
}
@Bean
@ConditionalOnClass(name = "org.springframework.data.domain.Pageable")
@ConditionalOnMissingBean
public Encoder feignEncoderPageable(ObjectProvider<AbstractFormWriter> formWriterProvider,
ObjectProvider<HttpMessageConverterCustomizer> customizers) {
PageableSpringEncoder encoder = new PageableSpringEncoder(
springEncoder(formWriterProvider, encoderProperties, customizers));
public Encoder feignEncoderPageable(ObjectProvider<AbstractFormWriter> formWriterProvider) {
PageableSpringEncoder encoder = new PageableSpringEncoder(springEncoder(formWriterProvider, encoderProperties));
if (springDataWebProperties != null) {
encoder.setPageParameter(springDataWebProperties.getPageable().getPageParameter());
@@ -131,26 +126,20 @@ public class FeignClientsConfiguration {
@ConditionalOnClass(name = "org.springframework.data.domain.Pageable")
@ConditionalOnMissingBean
public QueryMapEncoder feignQueryMapEncoderPageable() {
PageableSpringQueryMapEncoder queryMapEncoder = new PageableSpringQueryMapEncoder();
if (springDataWebProperties != null) {
queryMapEncoder.setPageParameter(springDataWebProperties.getPageable().getPageParameter());
queryMapEncoder.setSizeParameter(springDataWebProperties.getPageable().getSizeParameter());
queryMapEncoder.setSortParameter(springDataWebProperties.getSort().getSortParameter());
}
return queryMapEncoder;
return new PageableSpringQueryMapEncoder();
}
@Bean
@ConditionalOnMissingBean
public Contract feignContract(ConversionService feignConversionService) {
boolean decodeSlash = feignClientProperties == null || feignClientProperties.isDecodeSlash();
return new SpringMvcContract(parameterProcessors, feignConversionService, decodeSlash);
return new SpringMvcContract(this.parameterProcessors, feignConversionService, decodeSlash);
}
@Bean
public FormattingConversionService feignConversionService() {
FormattingConversionService conversionService = new DefaultFormattingConversionService();
for (FeignFormatterRegistrar feignFormatterRegistrar : feignFormatterRegistrars) {
for (FeignFormatterRegistrar feignFormatterRegistrar : this.feignFormatterRegistrars) {
feignFormatterRegistrar.registerFormatters(conversionService);
}
return conversionService;
@@ -165,7 +154,7 @@ public class FeignClientsConfiguration {
@Bean
@ConditionalOnMissingBean(FeignLoggerFactory.class)
public FeignLoggerFactory feignLoggerFactory() {
return new DefaultFeignLoggerFactory(logger);
return new DefaultFeignLoggerFactory(this.logger);
}
@Bean
@@ -176,15 +165,14 @@ public class FeignClientsConfiguration {
}
private Encoder springEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider,
FeignEncoderProperties encoderProperties, ObjectProvider<HttpMessageConverterCustomizer> customizers) {
FeignEncoderProperties encoderProperties) {
AbstractFormWriter formWriter = formWriterProvider.getIfAvailable();
if (formWriter != null) {
return new SpringEncoder(new SpringPojoFormEncoder(formWriter), messageConverters, encoderProperties,
customizers);
return new SpringEncoder(new SpringPojoFormEncoder(formWriter), this.messageConverters, encoderProperties);
}
else {
return new SpringEncoder(new SpringFormEncoder(), messageConverters, encoderProperties, customizers);
return new SpringEncoder(new SpringFormEncoder(), this.messageConverters, encoderProperties);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -302,7 +302,11 @@ class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLo
if (resolver == null) {
return resolved;
}
return String.valueOf(resolver.evaluate(resolved, new BeanExpressionContext(beanFactory, null)));
Object evaluateValue = resolver.evaluate(resolved, new BeanExpressionContext(beanFactory, null));
if (evaluateValue != null) {
return String.valueOf(evaluateValue);
}
return null;
}
return value;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2020 the original author or authors.
* Copyright 2020-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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 the original author or authors.
* Copyright 2016-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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,67 +0,0 @@
/*
* Copyright 2013-2021 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.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import feign.MethodMetadata;
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.CookieValue;
import static feign.Util.checkState;
import static feign.Util.emptyToNull;
/**
* @{link CookieValue} annotation processor.
* @author Gong Yi
*
*/
public class CookieValueParameterProcessor implements AnnotatedParameterProcessor {
private static final Class<CookieValue> ANNOTATION = CookieValue.class;
@Override
public Class<? extends Annotation> getAnnotationType() {
return ANNOTATION;
}
@Override
public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) {
int parameterIndex = context.getParameterIndex();
MethodMetadata data = context.getMethodMetadata();
CookieValue cookie = ANNOTATION.cast(annotation);
String name = cookie.value().trim();
checkState(emptyToNull(name) != null, "Cookie.name() was empty on parameter %s", parameterIndex);
context.setParameterName(name);
String cookieExpression = data.template().headers().getOrDefault(HttpHeaders.COOKIE, Arrays.asList("")).stream()
.findFirst().orElse("");
if (cookieExpression.length() == 0) {
cookieExpression = String.format("%s={%s}", name, name);
}
else {
cookieExpression += String.format("; %s={%s}", name, name);
}
data.template().removeHeader(HttpHeaders.COOKIE);
data.template().header(HttpHeaders.COOKIE, cookieExpression);
return true;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -34,7 +34,6 @@ import static feign.Util.emptyToNull;
*
* @author Jakub Narloch
* @author Abhijit Sarkar
* @author Yanming Zhou
* @see AnnotatedParameterProcessor
*/
public class PathVariableParameterProcessor implements AnnotatedParameterProcessor {
@@ -55,8 +54,7 @@ public class PathVariableParameterProcessor implements AnnotatedParameterProcess
MethodMetadata data = context.getMethodMetadata();
String varName = '{' + name + '}';
String varNameRegex = ".*\\{" + name + "(:[^}]+)?\\}.*";
if (!data.template().url().matches(varNameRegex) && !searchMapValues(data.template().queries(), varName)
if (!data.template().url().contains(varName) && !searchMapValues(data.template().queries(), varName)
&& !searchMapValues(data.template().headers(), varName)) {
data.formParams().add(name);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2019 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2021 the original author or authors.
* Copyright 2016-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.
@@ -16,18 +16,26 @@
package org.springframework.cloud.openfeign.hateoas;
import java.util.Collections;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.hateoas.config.HateoasConfiguration;
import org.springframework.hateoas.config.WebConverters;
import org.springframework.hateoas.RepresentationModel;
import org.springframework.hateoas.mediatype.hal.HalMediaTypeConfiguration;
import org.springframework.hateoas.server.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
import static org.springframework.hateoas.MediaTypes.HAL_JSON;
/**
* @author Hector Espert
@@ -35,15 +43,23 @@ import org.springframework.hateoas.config.WebConverters;
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication
@ConditionalOnClass(WebConverters.class)
@ConditionalOnClass(RepresentationModel.class)
@AutoConfigureAfter({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
RepositoryRestMvcAutoConfiguration.class, HateoasConfiguration.class })
RepositoryRestMvcAutoConfiguration.class })
public class FeignHalAutoConfiguration {
@Bean
@ConditionalOnBean(WebConverters.class)
HttpMessageConverterCustomizer webConvertersCustomizer(WebConverters webConverters) {
return new WebConvertersCustomizer(webConverters);
@ConditionalOnBean(HalMediaTypeConfiguration.class)
@ConditionalOnMissingBean
public TypeConstrainedMappingJackson2HttpMessageConverter halJacksonHttpMessageConverter(
ObjectProvider<ObjectMapper> objectMapper, HalMediaTypeConfiguration halConfiguration) {
ObjectMapper mapper = objectMapper.getIfAvailable(ObjectMapper::new).copy();
halConfiguration.configureObjectMapper(mapper);
TypeConstrainedMappingJackson2HttpMessageConverter converter = new TypeConstrainedMappingJackson2HttpMessageConverter(
RepresentationModel.class);
converter.setSupportedMediaTypes(Collections.singletonList(HAL_JSON));
converter.setObjectMapper(mapper);
return converter;
}
}
@@ -1,41 +0,0 @@
/*
* Copyright 2016-2021 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.hateoas;
import java.util.List;
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
import org.springframework.hateoas.config.WebConverters;
import org.springframework.http.converter.HttpMessageConverter;
/**
* @author Olga Maciaszek-Sharma
*/
public class WebConvertersCustomizer implements HttpMessageConverterCustomizer {
private final WebConverters webConverters;
public WebConvertersCustomizer(WebConverters webConverters) {
this.webConverters = webConverters;
}
@Override
public void accept(List<HttpMessageConverter<?>> httpMessageConverters) {
webConverters.augmentClient(httpMessageConverters);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -70,7 +70,7 @@ import static org.springframework.cloud.openfeign.loadbalancer.LoadBalancerUtils
@SuppressWarnings({ "rawtypes", "unchecked" })
public class RetryableFeignBlockingLoadBalancerClient implements Client {
private static final Log LOG = LogFactory.getLog(FeignBlockingLoadBalancerClient.class);
private static final Log LOG = LogFactory.getLog(RetryableFeignBlockingLoadBalancerClient.class);
private final Client delegate;
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2019 the original author or authors.
* Copyright 2015-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.
@@ -43,6 +43,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken;
* @author Tim Ysewyn
* @since 3.0.0
*/
@Deprecated // spring-security-oauth2 reached EOL
public class OAuth2FeignRequestInterceptor implements RequestInterceptor {
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -0,0 +1,80 @@
/*
* 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.support;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.zip.GZIPInputStream;
import feign.FeignException;
import feign.Response;
import feign.codec.Decoder;
import org.springframework.cloud.openfeign.encoding.HttpEncoding;
/**
* When response is compressed as gzip, this decompresses and uses {@link SpringDecoder}
* to decode.
*
* @author Jaesik Kim
*/
public class DefaultGzipDecoder implements Decoder {
private Decoder decoder;
public DefaultGzipDecoder(Decoder decoder) {
this.decoder = decoder;
}
@Override
public Object decode(final Response response, Type type) throws IOException, FeignException {
Collection<String> encoding = response.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)
? response.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER) : null;
if (encoding != null) {
if (encoding.contains(HttpEncoding.GZIP_ENCODING)) {
String decompressedBody = decompress(response);
if (decompressedBody != null) {
Response decompressedResponse = response.toBuilder().body(decompressedBody.getBytes()).build();
return decoder.decode(decompressedResponse, type);
}
}
}
return decoder.decode(response, type);
}
private String decompress(Response response) throws IOException {
if (response.body() == null) {
return null;
}
try (GZIPInputStream gzipInputStream = new GZIPInputStream(response.body().asInputStream());
BufferedReader reader = new BufferedReader(
new InputStreamReader(gzipInputStream, StandardCharsets.UTF_8))) {
String outputString = "";
String line;
while ((line = reader.readLine()) != null) {
outputString += line;
}
return outputString;
}
}
}
@@ -0,0 +1,58 @@
/*
* 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.support;
import feign.codec.Decoder;
import feign.optionals.OptionalDecoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Configures Default Gzip Decoder.
*
* @author Jaesik Kim
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty("feign.compression.response.enabled")
// The OK HTTP client uses "transparent" compression.
// If the accept-encoding header is present, it disables transparent compression
@ConditionalOnMissingBean(type = "okhttp3.OkHttpClient")
@AutoConfigureAfter(FeignAutoConfiguration.class)
public class DefaultGzipDecoderConfiguration {
private ObjectFactory<HttpMessageConverters> messageConverters;
public DefaultGzipDecoderConfiguration(ObjectFactory<HttpMessageConverters> messageConverters) {
this.messageConverters = messageConverters;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty("feign.compression.response.useGzipDecoder")
public Decoder defaultGzipDecoder() {
return new OptionalDecoder(
new ResponseEntityDecoder(new DefaultGzipDecoder(new SpringDecoder(messageConverters))));
}
}
@@ -1,54 +0,0 @@
/*
* Copyright 2013-2021 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.support;
import java.util.function.Consumer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
/**
* @author Olga Maciaszek-Sharma
*/
class EmptyObjectProvider<T> implements ObjectProvider<T> {
@Override
public T getObject(Object... args) throws BeansException {
return null;
}
@Override
public T getIfAvailable() throws BeansException {
return null;
}
@Override
public T getIfUnique() throws BeansException {
return null;
}
@Override
public T getObject() throws BeansException {
return null;
}
@Override
public void forEach(Consumer action) {
// do nothing
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,33 +0,0 @@
/*
* Copyright 2016-2021 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.support;
import java.util.List;
import java.util.function.Consumer;
import org.springframework.http.converter.HttpMessageConverter;
/**
* Allows customising {@link HttpMessageConverter} objects passed via {@link Consumer}
* parameter.
*
* @author Olga Maciaszek-Sharma
* @since 3.1.0
*/
public interface HttpMessageConverterCustomizer extends Consumer<List<HttpMessageConverter<?>>> {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -22,6 +22,7 @@ import java.util.function.Function;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.Module;
@@ -38,6 +39,8 @@ import org.springframework.data.domain.Sort;
*
* @author Pascal Büttiker
* @author Olga Maciaszek-Sharma
* @author Pedro Mendes
* @author Nikita Konev
*/
public class PageJacksonModule extends Module {
@@ -57,6 +60,7 @@ public class PageJacksonModule extends Module {
}
@JsonDeserialize(as = SimplePageImpl.class)
@JsonIgnoreProperties(ignoreUnknown = true)
private interface PageMixIn {
}
@@ -69,15 +73,19 @@ public class PageJacksonModule extends Module {
@JsonProperty("size") int size, @JsonProperty("totalElements") @JsonAlias({ "total-elements",
"total_elements", "totalelements", "TotalElements" }) long totalElements,
@JsonProperty("sort") Sort sort) {
PageRequest pageRequest;
if (sort != null) {
pageRequest = PageRequest.of(number, size, sort);
if (size > 0) {
PageRequest pageRequest;
if (sort != null) {
pageRequest = PageRequest.of(number, size, sort);
}
else {
pageRequest = PageRequest.of(number, size);
}
delegate = new PageImpl<>(content, pageRequest, totalElements);
}
else {
pageRequest = PageRequest.of(number, size);
delegate = new PageImpl<>(content);
}
delegate = new PageImpl<>(content, pageRequest, totalElements);
}
@JsonProperty
@@ -176,6 +184,33 @@ public class PageJacksonModule extends Module {
return delegate.iterator();
}
@JsonIgnore
@Override
public Pageable getPageable() {
return delegate.getPageable();
}
@JsonIgnore
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public String toString() {
return delegate.toString();
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -32,7 +32,6 @@ import org.springframework.data.domain.Sort;
* Provides support for encoding spring Pageable via composition.
*
* @author Pascal Büttiker
* @author Yanming Zhou
*/
public class PageableSpringEncoder implements Encoder {
@@ -83,8 +82,8 @@ public class PageableSpringEncoder implements Encoder {
Pageable pageable = (Pageable) object;
if (pageable.isPaged()) {
template.query(pageParameter, String.valueOf(pageable.getPageNumber()));
template.query(sizeParameter, String.valueOf(pageable.getPageSize()));
template.query(pageParameter, pageable.getPageNumber() + "");
template.query(sizeParameter, pageable.getPageSize() + "");
}
if (pageable.getSort() != null) {
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -31,38 +31,10 @@ import org.springframework.data.domain.Sort;
* {@link org.springframework.cloud.openfeign.SpringQueryMap}.
*
* @author Hyeonmin Park
* @author Yanming Zhou
* @since 2.2.8
*/
public class PageableSpringQueryMapEncoder extends BeanQueryMapEncoder {
/**
* Page index parameter name.
*/
private String pageParameter = "page";
/**
* Page size parameter name.
*/
private String sizeParameter = "size";
/**
* Sort parameter name.
*/
private String sortParameter = "sort";
public void setPageParameter(String pageParameter) {
this.pageParameter = pageParameter;
}
public void setSizeParameter(String sizeParameter) {
this.sizeParameter = sizeParameter;
}
public void setSortParameter(String sortParameter) {
this.sortParameter = sortParameter;
}
@Override
public Map<String, Object> encode(Object object) {
if (supports(object)) {
@@ -72,8 +44,8 @@ public class PageableSpringQueryMapEncoder extends BeanQueryMapEncoder {
Pageable pageable = (Pageable) object;
if (pageable.isPaged()) {
queryMap.put(pageParameter, pageable.getPageNumber());
queryMap.put(sizeParameter, pageable.getPageSize());
queryMap.put("page", pageable.getPageNumber());
queryMap.put("size", pageable.getPageSize());
}
if (pageable.getSort() != null) {
@@ -97,7 +69,7 @@ public class PageableSpringQueryMapEncoder extends BeanQueryMapEncoder {
sortQueries.add(order.getProperty() + "%2C" + order.getDirection());
}
if (!sortQueries.isEmpty()) {
queryMap.put(sortParameter, sortQueries);
queryMap.put("sort", sortQueries);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -21,7 +21,6 @@ import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.List;
import feign.FeignException;
import feign.Response;
@@ -29,48 +28,31 @@ import feign.codec.DecodeException;
import feign.codec.Decoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.client.HttpMessageConverterExtractor;
import static org.springframework.cloud.openfeign.support.FeignUtils.getHttpHeaders;
/**
* @author Spencer Gibb
* @author Olga Maciaszek-Sharma
*/
public class SpringDecoder implements Decoder {
private final ObjectFactory<HttpMessageConverters> messageConverters;
private ObjectFactory<HttpMessageConverters> messageConverters;
private final ObjectProvider<HttpMessageConverterCustomizer> customizers;
/**
* @deprecated in favour of
* {@link SpringDecoder#SpringDecoder(ObjectFactory, ObjectProvider)}
*/
@Deprecated
public SpringDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
this(messageConverters, new EmptyObjectProvider<>());
}
public SpringDecoder(ObjectFactory<HttpMessageConverters> messageConverters,
ObjectProvider<HttpMessageConverterCustomizer> customizers) {
this.messageConverters = messageConverters;
this.customizers = customizers;
}
@Override
public Object decode(final Response response, Type type) throws IOException, FeignException {
if (type instanceof Class || type instanceof ParameterizedType || type instanceof WildcardType) {
List<HttpMessageConverter<?>> converters = messageConverters.getObject().getConverters();
customizers.forEach(customizer -> customizer.accept(converters));
@SuppressWarnings({ "unchecked", "rawtypes" })
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(type, converters);
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(type,
this.messageConverters.getObject().getConverters());
return extractor.extractData(new FeignResponseAdapter(response));
}
@@ -88,23 +70,23 @@ public class SpringDecoder implements Decoder {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.valueOf(response.status());
return HttpStatus.valueOf(this.response.status());
}
@Override
public int getRawStatusCode() throws IOException {
return response.status();
return this.response.status();
}
@Override
public String getStatusText() throws IOException {
return response.reason();
return this.response.reason();
}
@Override
public void close() {
try {
response.body().close();
this.response.body().close();
}
catch (IOException ex) {
// Ignore exception on close...
@@ -113,12 +95,12 @@ public class SpringDecoder implements Decoder {
@Override
public InputStream getBody() throws IOException {
return response.body().asInputStream();
return this.response.body().asInputStream();
}
@Override
public HttpHeaders getHeaders() {
return getHttpHeaders(response.headers());
return getHttpHeaders(this.response.headers());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -24,7 +24,6 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
@@ -36,7 +35,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.encoding.HttpEncoding;
import org.springframework.http.HttpHeaders;
@@ -76,37 +74,19 @@ public class SpringEncoder implements Encoder {
private final FeignEncoderProperties encoderProperties;
private final ObjectProvider<HttpMessageConverterCustomizer> customizers;
public SpringEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
this(new SpringFormEncoder(), messageConverters);
}
/**
* @deprecated in favour of
* {@link SpringEncoder#SpringEncoder(SpringFormEncoder, ObjectFactory, FeignEncoderProperties, ObjectProvider)}
*/
@Deprecated
public SpringEncoder(SpringFormEncoder springFormEncoder, ObjectFactory<HttpMessageConverters> messageConverters) {
this(springFormEncoder, messageConverters, new FeignEncoderProperties());
}
/**
* @deprecated in favour of
* {@link SpringEncoder#SpringEncoder(SpringFormEncoder, ObjectFactory, FeignEncoderProperties, ObjectProvider)}
*/
@Deprecated
public SpringEncoder(SpringFormEncoder springFormEncoder, ObjectFactory<HttpMessageConverters> messageConverters,
FeignEncoderProperties encoderProperties) {
this(springFormEncoder, messageConverters, encoderProperties, new EmptyObjectProvider<>());
}
public SpringEncoder(SpringFormEncoder springFormEncoder, ObjectFactory<HttpMessageConverters> messageConverters,
FeignEncoderProperties encoderProperties, ObjectProvider<HttpMessageConverterCustomizer> customizers) {
this.springFormEncoder = springFormEncoder;
this.messageConverters = messageConverters;
this.encoderProperties = encoderProperties;
this.customizers = customizers;
}
@Override
@@ -137,9 +117,7 @@ public class SpringEncoder implements Encoder {
private void encodeWithMessageConverter(Object requestBody, Type bodyType, RequestTemplate request,
MediaType requestContentType) {
List<HttpMessageConverter<?>> converters = messageConverters.getObject().getConverters();
customizers.forEach(customizer -> customizer.accept(converters));
for (HttpMessageConverter messageConverter : converters) {
for (HttpMessageConverter messageConverter : this.messageConverters.getObject().getConverters()) {
FeignOutputMessage outputMessage;
try {
if (messageConverter instanceof GenericHttpMessageConverter) {
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -40,7 +40,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
import org.springframework.cloud.openfeign.CollectionFormat;
import org.springframework.cloud.openfeign.annotation.CookieValueParameterProcessor;
import org.springframework.cloud.openfeign.annotation.MatrixVariableParameterProcessor;
import org.springframework.cloud.openfeign.annotation.PathVariableParameterProcessor;
import org.springframework.cloud.openfeign.annotation.QueryMapParameterProcessor;
@@ -82,7 +81,6 @@ import static org.springframework.core.annotation.AnnotatedElementUtils.findMerg
* @author Artyom Romanenko
* @author Darren Foong
* @author Ram Anaswara
* @author Sam Kruglov
*/
public class SpringMvcContract extends Contract.BaseContract implements ResourceLoaderAware {
@@ -181,10 +179,6 @@ public class SpringMvcContract extends Contract.BaseContract implements Resource
+ ". @RequestMapping annotation is not allowed on @FeignClient interfaces.");
throw new IllegalArgumentException("@RequestMapping annotation not allowed on @FeignClient interfaces");
}
CollectionFormat collectionFormat = findMergedAnnotation(clz, CollectionFormat.class);
if (collectionFormat != null) {
data.template().collectionFormat(collectionFormat.value());
}
}
@Override
@@ -341,7 +335,6 @@ public class SpringMvcContract extends Contract.BaseContract implements Resource
annotatedArgumentResolvers.add(new RequestHeaderParameterProcessor());
annotatedArgumentResolvers.add(new QueryMapParameterProcessor());
annotatedArgumentResolvers.add(new RequestPartParameterProcessor());
annotatedArgumentResolvers.add(new CookieValueParameterProcessor());
return annotatedArgumentResolvers;
}
@@ -44,6 +44,12 @@
"description": "Enables the response from Feign to be compressed.",
"defaultValue": "false"
},
{
"name": "feign.compression.response.useGzipDecoder",
"type": "java.lang.Boolean",
"description": "Enables the default gzip decoder to be used.",
"defaultValue": "false"
},
{
"name": "feign.compression.request.enabled",
"type": "java.lang.Boolean",
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -39,16 +39,15 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Jaesik Kim
* @author Olga Maciaszek-Sharma
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = GzipDecodingTests.Application.class,
@SpringBootTest(classes = DefaultGzipDecoderTests.Application.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
value = { "spring.application.name=defaultGzipDecoderTests", "feign.compression.response.enabled=true",
"feign.client.config.default.loggerLevel=none", "feign.metrics.enabled=false",
"feign.compression.response.useGzipDecoder=true", "feign.client.config.default.loggerLevel=full",
"logging.level.org.springframework.cloud.openfeign=DEBUG" })
@DirtiesContext
public class GzipDecodingTests extends FeignClientFactoryBean {
public class DefaultGzipDecoderTests extends FeignClientFactoryBean {
@Autowired
FeignContext context;
@@ -56,7 +55,7 @@ public class GzipDecodingTests extends FeignClientFactoryBean {
@Value("${local.server.port}")
private int port = 0;
public GzipDecodingTests() {
public DefaultGzipDecoderTests() {
setName("tests");
setContextId("test");
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2021 the original author or authors.
* Copyright 2021-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.
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2021 the original author or authors.
* Copyright 2021-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.
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2021 the original author or authors.
* Copyright 2021-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.
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2020 the original author or authors.
* Copyright 2020-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.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* 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.
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2021 the original author or authors.
* Copyright 2021-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.

Some files were not shown because too many files have changed in this diff Show More