Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5113db4e3 | ||
|
|
a98f379e68 | ||
|
|
7b5d469839 | ||
|
|
816eaa6abf | ||
|
|
4d9a7c4ddd | ||
|
|
ab1f1f43a8 | ||
|
|
c51117d556 | ||
|
|
d6ad74a933 | ||
|
|
6aa6684d13 | ||
|
|
11098e9a99 | ||
|
|
36cc521a81 | ||
|
|
3a79850467 | ||
|
|
117e2c2b01 | ||
|
|
80de4e6b66 | ||
|
|
5f4acbe80e |
@@ -1,14 +0,0 @@
|
|||||||
# EditorConfig is awesome: https://EditorConfig.org
|
|
||||||
|
|
||||||
# top-most EditorConfig file
|
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
indent_style = tab
|
|
||||||
indent_size = 4
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
[*.yml]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
+63
-65
@@ -1,68 +1,66 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<settings>
|
<settings>
|
||||||
<servers>
|
<servers>
|
||||||
<server>
|
<server>
|
||||||
<id>repo.spring.io</id>
|
<id>repo.spring.io</id>
|
||||||
<username>${env.CI_DEPLOY_USERNAME}</username>
|
<username>${env.CI_DEPLOY_USERNAME}</username>
|
||||||
<password>${env.CI_DEPLOY_PASSWORD}</password>
|
<password>${env.CI_DEPLOY_PASSWORD}</password>
|
||||||
</server>
|
</server>
|
||||||
</servers>
|
</servers>
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<!--
|
<!--
|
||||||
N.B. this profile is only here to support users and IDEs that do not use Maven 3.3.
|
N.B. this profile is only here to support users and IDEs that do not use Maven 3.3.
|
||||||
It isn't needed on the command line if you use the wrapper script (mvnw) or if you use
|
It isn't needed on the command line if you use the wrapper script (mvnw) or if you use
|
||||||
a native Maven with the right version. Eclipse users should points their Maven tooling to
|
a native Maven with the right version. Eclipse users should points their Maven tooling to
|
||||||
this settings file, or copy the profile into their ~/.m2/settings.xml.
|
this settings file, or copy the profile into their ~/.m2/settings.xml.
|
||||||
-->
|
-->
|
||||||
<id>spring</id>
|
<id>spring</id>
|
||||||
<activation>
|
<activation><activeByDefault>true</activeByDefault></activation>
|
||||||
<activeByDefault>true</activeByDefault>
|
<repositories>
|
||||||
</activation>
|
<repository>
|
||||||
<repositories>
|
<id>spring-snapshots</id>
|
||||||
<repository>
|
<name>Spring Snapshots</name>
|
||||||
<id>spring-snapshots</id>
|
<url>https://repo.spring.io/libs-snapshot-local</url>
|
||||||
<name>Spring Snapshots</name>
|
<snapshots>
|
||||||
<url>https://repo.spring.io/libs-snapshot-local</url>
|
<enabled>true</enabled>
|
||||||
<snapshots>
|
</snapshots>
|
||||||
<enabled>true</enabled>
|
</repository>
|
||||||
</snapshots>
|
<repository>
|
||||||
</repository>
|
<id>spring-milestones</id>
|
||||||
<repository>
|
<name>Spring Milestones</name>
|
||||||
<id>spring-milestones</id>
|
<url>https://repo.spring.io/libs-milestone-local</url>
|
||||||
<name>Spring Milestones</name>
|
<snapshots>
|
||||||
<url>https://repo.spring.io/libs-milestone-local</url>
|
<enabled>false</enabled>
|
||||||
<snapshots>
|
</snapshots>
|
||||||
<enabled>false</enabled>
|
</repository>
|
||||||
</snapshots>
|
<repository>
|
||||||
</repository>
|
<id>spring-releases</id>
|
||||||
<repository>
|
<name>Spring Releases</name>
|
||||||
<id>spring-releases</id>
|
<url>https://repo.spring.io/release</url>
|
||||||
<name>Spring Releases</name>
|
<snapshots>
|
||||||
<url>https://repo.spring.io/release</url>
|
<enabled>false</enabled>
|
||||||
<snapshots>
|
</snapshots>
|
||||||
<enabled>false</enabled>
|
</repository>
|
||||||
</snapshots>
|
</repositories>
|
||||||
</repository>
|
<pluginRepositories>
|
||||||
</repositories>
|
<pluginRepository>
|
||||||
<pluginRepositories>
|
<id>spring-snapshots</id>
|
||||||
<pluginRepository>
|
<name>Spring Snapshots</name>
|
||||||
<id>spring-snapshots</id>
|
<url>https://repo.spring.io/libs-snapshot-local</url>
|
||||||
<name>Spring Snapshots</name>
|
<snapshots>
|
||||||
<url>https://repo.spring.io/libs-snapshot-local</url>
|
<enabled>true</enabled>
|
||||||
<snapshots>
|
</snapshots>
|
||||||
<enabled>true</enabled>
|
</pluginRepository>
|
||||||
</snapshots>
|
<pluginRepository>
|
||||||
</pluginRepository>
|
<id>spring-milestones</id>
|
||||||
<pluginRepository>
|
<name>Spring Milestones</name>
|
||||||
<id>spring-milestones</id>
|
<url>https://repo.spring.io/libs-milestone-local</url>
|
||||||
<name>Spring Milestones</name>
|
<snapshots>
|
||||||
<url>https://repo.spring.io/libs-milestone-local</url>
|
<enabled>false</enabled>
|
||||||
<snapshots>
|
</snapshots>
|
||||||
<enabled>false</enabled>
|
</pluginRepository>
|
||||||
</snapshots>
|
</pluginRepositories>
|
||||||
</pluginRepository>
|
</profile>
|
||||||
</pluginRepositories>
|
</profiles>
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
</settings>
|
</settings>
|
||||||
|
|||||||
+2
-7
@@ -1,8 +1,4 @@
|
|||||||
////
|
// Do not edit this file (e.g. go instead to src/main/asciidoc)
|
||||||
DO NOT EDIT THIS FILE. IT WAS GENERATED.
|
|
||||||
Manual changes to this file will be lost when it is generated again.
|
|
||||||
Edit the files in the src/main/asciidoc/ directory instead.
|
|
||||||
////
|
|
||||||
|
|
||||||
image:https://circleci.com/gh/spring-cloud/spring-cloud-openfeign.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-openfeign"]
|
image:https://circleci.com/gh/spring-cloud/spring-cloud-openfeign.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-openfeign"]
|
||||||
|
|
||||||
@@ -55,7 +51,7 @@ credentials and you already have those.
|
|||||||
|
|
||||||
The projects that require middleware generally include a
|
The projects that require middleware generally include a
|
||||||
`docker-compose.yml`, so consider using
|
`docker-compose.yml`, so consider using
|
||||||
https://docs.docker.com/compose/[Docker Compose] to run the middeware servers
|
https://compose.docker.io/[Docker Compose] to run the middeware servers
|
||||||
in Docker containers. See the README in the
|
in Docker containers. See the README in the
|
||||||
https://github.com/spring-cloud-samples/scripts[scripts demo
|
https://github.com/spring-cloud-samples/scripts[scripts demo
|
||||||
repository] for specific instructions about the common cases of mongo,
|
repository] for specific instructions about the common cases of mongo,
|
||||||
@@ -245,7 +241,6 @@ $ touch .springformat
|
|||||||
==== Intellij IDEA
|
==== Intellij IDEA
|
||||||
|
|
||||||
In order to setup Intellij you should import our coding conventions, inspection profiles and set up the checkstyle plugin.
|
In order to setup Intellij you should import our coding conventions, inspection profiles and set up the checkstyle plugin.
|
||||||
The following files can be found in the https://github.com/spring-cloud/spring-cloud-build/tree/master/spring-cloud-build-tools[Spring Cloud Build] project.
|
|
||||||
|
|
||||||
.spring-cloud-build-tools/
|
.spring-cloud-build-tools/
|
||||||
----
|
----
|
||||||
|
|||||||
+396
-2008
File diff suppressed because it is too large
Load Diff
+4
-5
@@ -1,12 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-openfeign</artifactId>
|
<artifactId>spring-cloud-openfeign</artifactId>
|
||||||
<version>2.1.3.RELEASE</version>
|
<version>2.0.5.BUILD-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-cloud-openfeign-docs</artifactId>
|
<artifactId>spring-cloud-openfeign-docs</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
@@ -15,7 +14,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<docs.main>spring-cloud-openfeign</docs.main>
|
<docs.main>spring-cloud-openfeign</docs.main>
|
||||||
<main.basedir>${basedir}/..</main.basedir>
|
<main.basedir>${basedir}/..</main.basedir>
|
||||||
<docs.whitelisted.branches>2.0.x,2.1.x</docs.whitelisted.branches>
|
<docs.whitelisted.branches>2.0.x</docs.whitelisted.branches>
|
||||||
</properties>
|
</properties>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ function check_if_anything_to_sync() {
|
|||||||
|
|
||||||
function retrieve_current_branch() {
|
function retrieve_current_branch() {
|
||||||
# Code getting the name of the current branch. For master we want to publish as we did until now
|
# Code getting the name of the current branch. For master we want to publish as we did until now
|
||||||
# http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
|
# https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
|
||||||
# If there is a branch already passed will reuse it - otherwise will try to find it
|
# If there is a branch already passed will reuse it - otherwise will try to find it
|
||||||
CURRENT_BRANCH=${BRANCH}
|
CURRENT_BRANCH=${BRANCH}
|
||||||
if [[ -z "${CURRENT_BRANCH}" ]] ; then
|
if [[ -z "${CURRENT_BRANCH}" ]] ; then
|
||||||
@@ -147,7 +147,7 @@ function copy_docs_for_current_version() {
|
|||||||
COMMIT_CHANGES="yes"
|
COMMIT_CHANGES="yes"
|
||||||
else
|
else
|
||||||
echo -e "Current branch is [${CURRENT_BRANCH}]"
|
echo -e "Current branch is [${CURRENT_BRANCH}]"
|
||||||
# http://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin
|
# https://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin
|
||||||
if [[ ",${WHITELISTED_BRANCHES_VALUE}," = *",${CURRENT_BRANCH},"* ]] ; then
|
if [[ ",${WHITELISTED_BRANCHES_VALUE}," = *",${CURRENT_BRANCH},"* ]] ; then
|
||||||
mkdir -p ${ROOT_FOLDER}/${CURRENT_BRANCH}
|
mkdir -p ${ROOT_FOLDER}/${CURRENT_BRANCH}
|
||||||
echo -e "Branch [${CURRENT_BRANCH}] is whitelisted! Will copy the current docs to the [${CURRENT_BRANCH}] folder"
|
echo -e "Branch [${CURRENT_BRANCH}] is whitelisted! Will copy the current docs to the [${CURRENT_BRANCH}] folder"
|
||||||
|
|||||||
@@ -73,8 +73,6 @@ in your external configuration (see
|
|||||||
|
|
||||||
A central concept in Spring Cloud's Feign support is that of the named client. Each feign client is part of an ensemble of components that work together to contact a remote server on demand, and the ensemble has a name that you give it as an application developer using the `@FeignClient` annotation. Spring Cloud creates a new ensemble as an
|
A central concept in Spring Cloud's Feign support is that of the named client. Each feign client is part of an ensemble of components that work together to contact a remote server on demand, and the ensemble has a name that you give it as an application developer using the `@FeignClient` annotation. Spring Cloud creates a new ensemble as an
|
||||||
`ApplicationContext` on demand for each named client using `FeignClientsConfiguration`. This contains (amongst other things) an `feign.Decoder`, a `feign.Encoder`, and a `feign.Contract`.
|
`ApplicationContext` on demand for each named client using `FeignClientsConfiguration`. This contains (amongst other things) an `feign.Decoder`, a `feign.Encoder`, and a `feign.Contract`.
|
||||||
It is possible to override the name of that ensemble by using the `contextId`
|
|
||||||
attribute of the `@FeignClient` annotation.
|
|
||||||
|
|
||||||
Spring Cloud lets you take full control of the feign client by declaring additional configuration (on top of the `FeignClientsConfiguration`) using `@FeignClient`. Example:
|
Spring Cloud lets you take full control of the feign client by declaring additional configuration (on top of the `FeignClientsConfiguration`) using `@FeignClient`. Example:
|
||||||
|
|
||||||
@@ -92,10 +90,6 @@ NOTE: `FooConfiguration` does not need to be annotated with `@Configuration`. Ho
|
|||||||
|
|
||||||
NOTE: The `serviceId` attribute is now deprecated in favor of the `name` attribute.
|
NOTE: The `serviceId` attribute is now deprecated in favor of the `name` attribute.
|
||||||
|
|
||||||
NOTE: Using `contextId` attribute of the `@FeignClient` annotation in addition to changing the name of
|
|
||||||
the `ApplicationContext` ensemble, it will override the alias of the client name
|
|
||||||
and it will be used as part of the name of the configuration bean created for that client.
|
|
||||||
|
|
||||||
WARNING: Previously, using the `url` attribute, did not require the `name` attribute. Using `name` is now required.
|
WARNING: Previously, using the `url` attribute, did not require the `name` attribute. Using `name` is now required.
|
||||||
|
|
||||||
Placeholders are supported in the `name` and `url` attributes.
|
Placeholders are supported in the `name` and `url` attributes.
|
||||||
@@ -212,27 +206,6 @@ hystrix:
|
|||||||
strategy: SEMAPHORE
|
strategy: SEMAPHORE
|
||||||
----
|
----
|
||||||
|
|
||||||
If we want to create multiple feign clients with the same name or url
|
|
||||||
so that they would point to the same server but each with a different custom configuration then
|
|
||||||
we have to use `contextId` attribute of the `@FeignClient` in order to avoid name
|
|
||||||
collision of these configuration beans.
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
|
||||||
----
|
|
||||||
@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
|
|
||||||
public interface FooClient {
|
|
||||||
//..
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
|
||||||
----
|
|
||||||
@FeignClient(contextId = "barClient", name = "stores", configuration = BarConfiguration.class)
|
|
||||||
public interface BarClient {
|
|
||||||
//..
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Creating Feign Clients Manually
|
=== Creating Feign Clients Manually
|
||||||
|
|
||||||
In some cases it might be necessary to customize your Feign Clients in a way that is not
|
In some cases it might be necessary to customize your Feign Clients in a way that is not
|
||||||
@@ -452,38 +425,4 @@ public class FooConfiguration {
|
|||||||
return Logger.Level.FULL;
|
return Logger.Level.FULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
=== Feign @QueryMap support
|
|
||||||
|
|
||||||
The OpenFeign `@QueryMap` annotation provides support for POJOs to be used as
|
|
||||||
GET parameter maps. Unfortunately, the default OpenFeign QueryMap annotation is
|
|
||||||
incompatible with Spring because it lacks a `value` property.
|
|
||||||
|
|
||||||
Spring Cloud OpenFeign provides an equivalent `@SpringQueryMap` annotation, which
|
|
||||||
is used to annotate a POJO or Map parameter as a query parameter map.
|
|
||||||
|
|
||||||
For example, the `Params` class defines parameters `param1` and `param2`:
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
|
||||||
----
|
|
||||||
// Params.java
|
|
||||||
public class Params {
|
|
||||||
private String param1;
|
|
||||||
private String param2;
|
|
||||||
|
|
||||||
// [Getters and setters omitted for brevity]
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
The following feign client uses the `Params` class by using the `@SpringQueryMap` annotation:
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
|
||||||
----
|
|
||||||
@FeignClient("demo")
|
|
||||||
public class DemoTemplate {
|
|
||||||
|
|
||||||
@GetMapping(path = "/demo")
|
|
||||||
String demoEndpoint(@SpringQueryMap Params params);
|
|
||||||
}
|
|
||||||
----
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
# "License"); you may not use this file except in compliance
|
# "License"); you may not use this file except in compliance
|
||||||
# with the License. You may obtain a copy of the License at
|
# with the License. You may obtain a copy of the License at
|
||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
# Unless required by applicable law or agreed to in writing,
|
# Unless required by applicable law or agreed to in writing,
|
||||||
# software distributed under the License is distributed on an
|
# software distributed under the License is distributed on an
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
@REM "License"); you may not use this file except in compliance
|
@REM "License"); you may not use this file except in compliance
|
||||||
@REM with the License. You may obtain a copy of the License at
|
@REM with the License. You may obtain a copy of the License at
|
||||||
@REM
|
@REM
|
||||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||||
@REM
|
@REM
|
||||||
@REM Unless required by applicable law or agreed to in writing,
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
@REM software distributed under the License is distributed on an
|
@REM software distributed under the License is distributed on an
|
||||||
|
|||||||
@@ -1,33 +1,29 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>spring-cloud-openfeign</artifactId>
|
<artifactId>spring-cloud-openfeign</artifactId>
|
||||||
<version>2.1.3.RELEASE</version>
|
<version>2.0.5.BUILD-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>Spring Cloud OpenFeign</name>
|
<name>Spring Cloud OpenFeign</name>
|
||||||
<description>Spring Cloud OpenFeign</description>
|
<description>Spring Cloud OpenFeign</description>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-build</artifactId>
|
<artifactId>spring-cloud-build</artifactId>
|
||||||
<version>2.1.7.RELEASE</version>
|
<version>2.0.5.BUILD-SNAPSHOT</version>
|
||||||
<relativePath/>
|
<relativePath />
|
||||||
</parent>
|
</parent>
|
||||||
<scm>
|
<scm>
|
||||||
<url>https://github.com/spring-cloud/spring-cloud-openfeign</url>
|
<url>https://github.com/spring-cloud/spring-cloud-openfeign</url>
|
||||||
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-openfeign.git
|
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-openfeign.git</connection>
|
||||||
</connection>
|
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-openfeign.git</developerConnection>
|
||||||
<developerConnection>
|
|
||||||
scm:git:ssh://git@github.com/spring-cloud/spring-cloud-openfeign.git
|
|
||||||
</developerConnection>
|
|
||||||
<tag>HEAD</tag>
|
<tag>HEAD</tag>
|
||||||
</scm>
|
</scm>
|
||||||
<properties>
|
<properties>
|
||||||
<main.basedir>${basedir}</main.basedir>
|
<main.basedir>${basedir}</main.basedir>
|
||||||
<jackson.version>2.7.3</jackson.version>
|
<jackson.version>2.7.3</jackson.version>
|
||||||
<spring-cloud-commons.version>2.1.3.RELEASE</spring-cloud-commons.version>
|
<spring-cloud-commons.version>2.0.3.BUILD-SNAPSHOT</spring-cloud-commons.version>
|
||||||
<spring-cloud-netflix.version>2.1.3.RELEASE</spring-cloud-netflix.version>
|
<spring-cloud-netflix.version>2.0.3.BUILD-SNAPSHOT</spring-cloud-netflix.version>
|
||||||
|
|
||||||
<!-- Plugin versions -->
|
<!-- Plugin versions -->
|
||||||
<maven-compiler-plugin.version>3.6.1</maven-compiler-plugin.version>
|
<maven-compiler-plugin.version>3.6.1</maven-compiler-plugin.version>
|
||||||
@@ -36,15 +32,8 @@
|
|||||||
<surefire.plugin.version>2.19.1</surefire.plugin.version>
|
<surefire.plugin.version>2.19.1</surefire.plugin.version>
|
||||||
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
|
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
|
||||||
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
|
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
|
||||||
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec
|
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
|
||||||
</sonar.jacoco.reportPath>
|
|
||||||
<sonar.language>java</sonar.language>
|
<sonar.language>java</sonar.language>
|
||||||
|
|
||||||
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
|
|
||||||
<maven-checkstyle-plugin.failsOnViolation>true
|
|
||||||
</maven-checkstyle-plugin.failsOnViolation>
|
|
||||||
<maven-checkstyle-plugin.includeTestSourceDirectory>true
|
|
||||||
</maven-checkstyle-plugin.includeTestSourceDirectory>
|
|
||||||
</properties>
|
</properties>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
@@ -57,13 +46,11 @@
|
|||||||
<additionalConfig>
|
<additionalConfig>
|
||||||
<file>
|
<file>
|
||||||
<name>.settings/org.eclipse.jdt.ui.prefs</name>
|
<name>.settings/org.eclipse.jdt.ui.prefs</name>
|
||||||
<location>${main.basedir}/eclipse/org.eclipse.jdt.ui.prefs
|
<location>${main.basedir}/eclipse/org.eclipse.jdt.ui.prefs</location>
|
||||||
</location>
|
|
||||||
</file>
|
</file>
|
||||||
<file>
|
<file>
|
||||||
<name>.settings/org.eclipse.jdt.core.prefs</name>
|
<name>.settings/org.eclipse.jdt.core.prefs</name>
|
||||||
<location>${main.basedir}/eclipse/org.eclipse.jdt.core.prefs
|
<location>${main.basedir}/eclipse/org.eclipse.jdt.core.prefs</location>
|
||||||
</location>
|
|
||||||
</file>
|
</file>
|
||||||
</additionalConfig>
|
</additionalConfig>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -76,26 +63,8 @@
|
|||||||
<target>1.8</target>
|
<target>1.8</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>io.spring.javaformat</groupId>
|
|
||||||
<artifactId>spring-javaformat-maven-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<reporting>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</reporting>
|
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -137,7 +106,7 @@
|
|||||||
<module>spring-cloud-openfeign-core</module>
|
<module>spring-cloud-openfeign-core</module>
|
||||||
<module>spring-cloud-starter-openfeign</module>
|
<module>spring-cloud-starter-openfeign</module>
|
||||||
<module>docs</module>
|
<module>docs</module>
|
||||||
</modules>
|
</modules>
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>spring</id>
|
<id>spring</id>
|
||||||
@@ -215,8 +184,7 @@
|
|||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<propertyName>surefireArgLine</propertyName>
|
<propertyName>surefireArgLine</propertyName>
|
||||||
<destFile>${project.build.directory}/jacoco.exec
|
<destFile>${project.build.directory}/jacoco.exec</destFile>
|
||||||
</destFile>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
@@ -227,8 +195,7 @@
|
|||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<!-- Sets the path to the file which contains the execution data. -->
|
<!-- Sets the path to the file which contains the execution data. -->
|
||||||
<dataFile>${project.build.directory}/jacoco.exec
|
<dataFile>${project.build.directory}/jacoco.exec</dataFile>
|
||||||
</dataFile>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-openfeign</artifactId>
|
<artifactId>spring-cloud-openfeign</artifactId>
|
||||||
<version>2.1.3.RELEASE</version>
|
<version>2.0.5.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-cloud-openfeign-core</artifactId>
|
<artifactId>spring-cloud-openfeign-core</artifactId>
|
||||||
@@ -158,10 +157,14 @@
|
|||||||
<artifactId>rxjava</artifactId>
|
<artifactId>rxjava</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sun.jersey.contribs</groupId>
|
||||||
|
<artifactId>jersey-apache-client4</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
<artifactId>okhttp</artifactId>
|
<artifactId>okhttp</artifactId>
|
||||||
<version>4.1.0</version>
|
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -184,11 +187,6 @@
|
|||||||
<artifactId>spring-cloud-test-support</artifactId>
|
<artifactId>spring-cloud-test-support</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.data</groupId>
|
|
||||||
<artifactId>spring-data-commons</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.projectreactor</groupId>
|
<groupId>io.projectreactor</groupId>
|
||||||
<artifactId>reactor-test</artifactId>
|
<artifactId>reactor-test</artifactId>
|
||||||
@@ -216,28 +214,22 @@
|
|||||||
<version>3.4.0</version>
|
<version>3.4.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.vavr</groupId>
|
|
||||||
<artifactId>vavr</artifactId>
|
|
||||||
<version>0.10.0</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>java8plus</id>
|
<id>java8plus</id>
|
||||||
<activation>
|
<activation>
|
||||||
<jdk>[1.8,2.0)</jdk>
|
<jdk>[1.8,2.0)</jdk>
|
||||||
</activation>
|
</activation>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<compilerArgs>
|
<compilerArgs>
|
||||||
<arg>-parameters</arg>
|
<arg>-parameters</arg>
|
||||||
</compilerArgs>
|
</compilerArgs>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|||||||
+10
-7
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -32,19 +32,20 @@ public interface AnnotatedParameterProcessor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the processor supported annotation type.
|
* Retrieves the processor supported annotation type.
|
||||||
|
*
|
||||||
* @return the annotation type
|
* @return the annotation type
|
||||||
*/
|
*/
|
||||||
Class<? extends Annotation> getAnnotationType();
|
Class<? extends Annotation> getAnnotationType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the annotated parameter.
|
* Process the annotated parameter.
|
||||||
* @param context the parameter context
|
*
|
||||||
|
* @param context the parameter context
|
||||||
* @param annotation the annotation instance
|
* @param annotation the annotation instance
|
||||||
* @param method the method that contains the annotation
|
* @param method the method that contains the annotation
|
||||||
* @return whether the parameter is http
|
* @return whether the parameter is http
|
||||||
*/
|
*/
|
||||||
boolean processArgument(AnnotatedParameterContext context, Annotation annotation,
|
boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method);
|
||||||
Method method);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the parameter context.
|
* Specifies the parameter context.
|
||||||
@@ -55,30 +56,32 @@ public interface AnnotatedParameterProcessor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the method metadata.
|
* Retrieves the method metadata.
|
||||||
|
*
|
||||||
* @return the method metadata
|
* @return the method metadata
|
||||||
*/
|
*/
|
||||||
MethodMetadata getMethodMetadata();
|
MethodMetadata getMethodMetadata();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the index of the parameter.
|
* Retrieves the index of the parameter.
|
||||||
|
*
|
||||||
* @return the parameter index
|
* @return the parameter index
|
||||||
*/
|
*/
|
||||||
int getParameterIndex();
|
int getParameterIndex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the parameter name.
|
* Sets the parameter name.
|
||||||
|
*
|
||||||
* @param name the name of the parameter
|
* @param name the name of the parameter
|
||||||
*/
|
*/
|
||||||
void setParameterName(String name);
|
void setParameterName(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the template parameter.
|
* Sets the template parameter.
|
||||||
|
*
|
||||||
* @param name the template parameter
|
* @param name the template parameter
|
||||||
* @param rest the existing parameter values
|
* @param rest the existing parameter values
|
||||||
* @return parameters
|
* @return parameters
|
||||||
*/
|
*/
|
||||||
Collection<String> setTemplateParameter(String name, Collection<String> rest);
|
Collection<String> setTemplateParameter(String name, Collection<String> rest);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2019 the original author or authors.
|
* Copyright 2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
@@ -25,9 +26,8 @@ import feign.Target;
|
|||||||
class DefaultTargeter implements Targeter {
|
class DefaultTargeter implements Targeter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign,
|
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
|
||||||
FeignContext context, Target.HardCodedTarget<T> target) {
|
Target.HardCodedTarget<T> target) {
|
||||||
return feign.target(target);
|
return feign.target(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-11
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -25,11 +25,10 @@ import java.lang.annotation.Target;
|
|||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans for interfaces that declare they are feign clients (via
|
* Scans for interfaces that declare they are feign clients (via {@link FeignClient
|
||||||
* {@link org.springframework.cloud.openfeign.FeignClient} <code>@FeignClient</code>).
|
* <code>@FeignClient</code>}). Configures component scanning directives for use with
|
||||||
* Configures component scanning directives for use with
|
* {@link org.springframework.context.annotation.Configuration
|
||||||
* {@link org.springframework.context.annotation.Configuration}
|
* <code>@Configuration</code>} classes.
|
||||||
* <code>@Configuration</code> classes.
|
|
||||||
*
|
*
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
@@ -56,6 +55,7 @@ public @interface EnableFeignClients {
|
|||||||
* <p>
|
* <p>
|
||||||
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based
|
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based
|
||||||
* package names.
|
* package names.
|
||||||
|
*
|
||||||
* @return the array of 'basePackages'.
|
* @return the array of 'basePackages'.
|
||||||
*/
|
*/
|
||||||
String[] basePackages() default {};
|
String[] basePackages() default {};
|
||||||
@@ -66,6 +66,7 @@ public @interface EnableFeignClients {
|
|||||||
* <p>
|
* <p>
|
||||||
* Consider creating a special no-op marker class or interface in each package that
|
* Consider creating a special no-op marker class or interface in each package that
|
||||||
* serves no purpose other than being referenced by this attribute.
|
* serves no purpose other than being referenced by this attribute.
|
||||||
|
*
|
||||||
* @return the array of 'basePackageClasses'.
|
* @return the array of 'basePackageClasses'.
|
||||||
*/
|
*/
|
||||||
Class<?>[] basePackageClasses() default {};
|
Class<?>[] basePackageClasses() default {};
|
||||||
@@ -76,15 +77,12 @@ public @interface EnableFeignClients {
|
|||||||
* {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
|
* {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
|
||||||
*
|
*
|
||||||
* @see FeignClientsConfiguration for the defaults
|
* @see FeignClientsConfiguration for the defaults
|
||||||
* @return list of default configurations
|
|
||||||
*/
|
*/
|
||||||
Class<?>[] defaultConfiguration() default {};
|
Class<?>[] defaultConfiguration() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of classes annotated with @FeignClient. If not empty, disables classpath
|
* List of classes annotated with @FeignClient. If not empty, disables classpath scanning.
|
||||||
* scanning.
|
* @return
|
||||||
* @return list of FeignClient classes
|
|
||||||
*/
|
*/
|
||||||
Class<?>[] clients() default {};
|
Class<?>[] clients() default {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-41
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -22,19 +22,11 @@ import java.util.Timer;
|
|||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.annotation.PreDestroy;
|
|
||||||
|
|
||||||
import feign.Client;
|
|
||||||
import feign.Feign;
|
|
||||||
import feign.httpclient.ApacheHttpClient;
|
|
||||||
import feign.okhttp.OkHttpClient;
|
|
||||||
import okhttp3.ConnectionPool;
|
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.HttpClient;
|
||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.apache.http.config.RegistryBuilder;
|
import org.apache.http.config.RegistryBuilder;
|
||||||
import org.apache.http.conn.HttpClientConnectionManager;
|
import org.apache.http.conn.HttpClientConnectionManager;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
@@ -50,14 +42,21 @@ import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import feign.Client;
|
||||||
|
import feign.Feign;
|
||||||
|
import feign.httpclient.ApacheHttpClient;
|
||||||
|
import feign.okhttp.OkHttpClient;
|
||||||
|
import okhttp3.ConnectionPool;
|
||||||
|
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
* @author Julien Roy
|
* @author Julien Roy
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass(Feign.class)
|
@ConditionalOnClass(Feign.class)
|
||||||
@EnableConfigurationProperties({ FeignClientProperties.class,
|
@EnableConfigurationProperties({FeignClientProperties.class, FeignHttpClientProperties.class})
|
||||||
FeignHttpClientProperties.class })
|
|
||||||
public class FeignAutoConfiguration {
|
public class FeignAutoConfiguration {
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
@@ -78,25 +77,21 @@ public class FeignAutoConfiguration {
|
|||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass(name = "feign.hystrix.HystrixFeign")
|
@ConditionalOnClass(name = "feign.hystrix.HystrixFeign")
|
||||||
protected static class HystrixFeignTargeterConfiguration {
|
protected static class HystrixFeignTargeterConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public Targeter feignTargeter() {
|
public Targeter feignTargeter() {
|
||||||
return new HystrixTargeter();
|
return new HystrixTargeter();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnMissingClass("feign.hystrix.HystrixFeign")
|
@ConditionalOnMissingClass("feign.hystrix.HystrixFeign")
|
||||||
protected static class DefaultFeignTargeterConfiguration {
|
protected static class DefaultFeignTargeterConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public Targeter feignTargeter() {
|
public Targeter feignTargeter() {
|
||||||
return new DefaultTargeter();
|
return new DefaultTargeter();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the following configuration is for alternate feign clients if
|
// the following configuration is for alternate feign clients if
|
||||||
@@ -109,7 +104,6 @@ public class FeignAutoConfiguration {
|
|||||||
@ConditionalOnMissingBean(CloseableHttpClient.class)
|
@ConditionalOnMissingBean(CloseableHttpClient.class)
|
||||||
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
|
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
|
||||||
protected static class HttpClientFeignConfiguration {
|
protected static class HttpClientFeignConfiguration {
|
||||||
|
|
||||||
private final Timer connectionManagerTimer = new Timer(
|
private final Timer connectionManagerTimer = new Timer(
|
||||||
"FeignApacheHttpClientConfiguration.connectionManagerTimer", true);
|
"FeignApacheHttpClientConfiguration.connectionManagerTimer", true);
|
||||||
|
|
||||||
@@ -124,12 +118,10 @@ public class FeignAutoConfiguration {
|
|||||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
||||||
FeignHttpClientProperties httpClientProperties) {
|
FeignHttpClientProperties httpClientProperties) {
|
||||||
final HttpClientConnectionManager connectionManager = connectionManagerFactory
|
final HttpClientConnectionManager connectionManager = connectionManagerFactory
|
||||||
.newConnectionManager(httpClientProperties.isDisableSslValidation(),
|
.newConnectionManager(httpClientProperties.isDisableSslValidation(), httpClientProperties.getMaxConnections(),
|
||||||
httpClientProperties.getMaxConnections(),
|
|
||||||
httpClientProperties.getMaxConnectionsPerRoute(),
|
httpClientProperties.getMaxConnectionsPerRoute(),
|
||||||
httpClientProperties.getTimeToLive(),
|
httpClientProperties.getTimeToLive(),
|
||||||
httpClientProperties.getTimeToLiveUnit(),
|
httpClientProperties.getTimeToLiveUnit(), registryBuilder);
|
||||||
this.registryBuilder);
|
|
||||||
this.connectionManagerTimer.schedule(new TimerTask() {
|
this.connectionManagerTimer.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -147,9 +139,9 @@ public class FeignAutoConfiguration {
|
|||||||
.setConnectTimeout(httpClientProperties.getConnectionTimeout())
|
.setConnectTimeout(httpClientProperties.getConnectionTimeout())
|
||||||
.setRedirectsEnabled(httpClientProperties.isFollowRedirects())
|
.setRedirectsEnabled(httpClientProperties.isFollowRedirects())
|
||||||
.build();
|
.build();
|
||||||
this.httpClient = httpClientFactory.createBuilder()
|
this.httpClient = httpClientFactory.createBuilder().
|
||||||
.setConnectionManager(httpClientConnectionManager)
|
setConnectionManager(httpClientConnectionManager).
|
||||||
.setDefaultRequestConfig(defaultRequestConfig).build();
|
setDefaultRequestConfig(defaultRequestConfig).build();
|
||||||
return this.httpClient;
|
return this.httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,28 +153,26 @@ public class FeignAutoConfiguration {
|
|||||||
|
|
||||||
@PreDestroy
|
@PreDestroy
|
||||||
public void destroy() throws Exception {
|
public void destroy() throws Exception {
|
||||||
this.connectionManagerTimer.cancel();
|
connectionManagerTimer.cancel();
|
||||||
if (this.httpClient != null) {
|
if(httpClient != null) {
|
||||||
this.httpClient.close();
|
httpClient.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass(OkHttpClient.class)
|
@ConditionalOnClass(OkHttpClient.class)
|
||||||
@ConditionalOnMissingClass("com.netflix.loadbalancer.ILoadBalancer")
|
@ConditionalOnMissingClass("com.netflix.loadbalancer.ILoadBalancer")
|
||||||
@ConditionalOnMissingBean(okhttp3.OkHttpClient.class)
|
@ConditionalOnMissingBean(okhttp3.OkHttpClient.class)
|
||||||
@ConditionalOnProperty("feign.okhttp.enabled")
|
@ConditionalOnProperty(value = "feign.okhttp.enabled")
|
||||||
protected static class OkHttpFeignConfiguration {
|
protected static class OkHttpFeignConfiguration {
|
||||||
|
|
||||||
private okhttp3.OkHttpClient okHttpClient;
|
private okhttp3.OkHttpClient okHttpClient;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(ConnectionPool.class)
|
@ConditionalOnMissingBean(ConnectionPool.class)
|
||||||
public ConnectionPool httpClientConnectionPool(
|
public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties,
|
||||||
FeignHttpClientProperties httpClientProperties,
|
OkHttpClientConnectionPoolFactory connectionPoolFactory) {
|
||||||
OkHttpClientConnectionPoolFactory connectionPoolFactory) {
|
|
||||||
Integer maxTotalConnections = httpClientProperties.getMaxConnections();
|
Integer maxTotalConnections = httpClientProperties.getMaxConnections();
|
||||||
Long timeToLive = httpClientProperties.getTimeToLive();
|
Long timeToLive = httpClientProperties.getTimeToLive();
|
||||||
TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
|
TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
|
||||||
@@ -191,23 +181,22 @@ public class FeignAutoConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public okhttp3.OkHttpClient client(OkHttpClientFactory httpClientFactory,
|
public okhttp3.OkHttpClient client(OkHttpClientFactory httpClientFactory,
|
||||||
ConnectionPool connectionPool,
|
ConnectionPool connectionPool, FeignHttpClientProperties httpClientProperties) {
|
||||||
FeignHttpClientProperties httpClientProperties) {
|
|
||||||
Boolean followRedirects = httpClientProperties.isFollowRedirects();
|
Boolean followRedirects = httpClientProperties.isFollowRedirects();
|
||||||
Integer connectTimeout = httpClientProperties.getConnectionTimeout();
|
Integer connectTimeout = httpClientProperties.getConnectionTimeout();
|
||||||
Boolean disableSslValidation = httpClientProperties.isDisableSslValidation();
|
Boolean disableSslValidation = httpClientProperties.isDisableSslValidation();
|
||||||
this.okHttpClient = httpClientFactory.createBuilder(disableSslValidation)
|
this.okHttpClient = httpClientFactory.createBuilder(disableSslValidation).
|
||||||
.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
|
connectTimeout(connectTimeout, TimeUnit.MILLISECONDS).
|
||||||
.followRedirects(followRedirects).connectionPool(connectionPool)
|
followRedirects(followRedirects).
|
||||||
.build();
|
connectionPool(connectionPool).build();
|
||||||
return this.okHttpClient;
|
return this.okHttpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreDestroy
|
@PreDestroy
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
if (this.okHttpClient != null) {
|
if(okHttpClient != null) {
|
||||||
this.okHttpClient.dispatcher().executorService().shutdown();
|
okHttpClient.dispatcher().executorService().shutdown();
|
||||||
this.okHttpClient.connectionPool().evictAll();
|
okHttpClient.connectionPool().evictAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +205,6 @@ public class FeignAutoConfiguration {
|
|||||||
public Client feignClient(okhttp3.OkHttpClient client) {
|
public Client feignClient(okhttp3.OkHttpClient client) {
|
||||||
return new OkHttpClient(client);
|
return new OkHttpClient(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-23
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -42,45 +42,36 @@ public @interface FeignClient {
|
|||||||
* The name of the service with optional protocol prefix. Synonym for {@link #name()
|
* The name of the service with optional protocol prefix. Synonym for {@link #name()
|
||||||
* name}. A name must be specified for all clients, whether or not a url is provided.
|
* name}. A name must be specified for all clients, whether or not a url is provided.
|
||||||
* Can be specified as property key, eg: ${propertyKey}.
|
* Can be specified as property key, eg: ${propertyKey}.
|
||||||
* @return the name of the service with optional protocol prefix
|
|
||||||
*/
|
*/
|
||||||
@AliasFor("name")
|
@AliasFor("name")
|
||||||
String value() default "";
|
String value() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The service id with optional protocol prefix. Synonym for {@link #value() value}.
|
* The service id with optional protocol prefix. Synonym for {@link #value() value}.
|
||||||
|
*
|
||||||
* @deprecated use {@link #name() name} instead
|
* @deprecated use {@link #name() name} instead
|
||||||
* @return the service id with optional protocol prefix
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
String serviceId() default "";
|
String serviceId() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will be used as the bean name instead of name if present, but will not be used
|
* The service id with optional protocol prefix. Synonym for {@link #value() value}.
|
||||||
* as a service id.
|
|
||||||
* @return bean name instead of name if present
|
|
||||||
*/
|
|
||||||
String contextId() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The service id with optional protocol prefix. Synonym for {@link #value()
|
|
||||||
* value}.
|
|
||||||
*/
|
*/
|
||||||
@AliasFor("value")
|
@AliasFor("value")
|
||||||
String name() default "";
|
String name() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the <code>@Qualifier</code> value for the feign client.
|
* Sets the <code>@Qualifier</code> value for the feign client.
|
||||||
*/
|
*/
|
||||||
String qualifier() default "";
|
String qualifier() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return an absolute URL or resolvable hostname (the protocol is optional).
|
* An absolute URL or resolvable hostname (the protocol is optional).
|
||||||
*/
|
*/
|
||||||
String url() default "";
|
String url() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return whether 404s should be decoded instead of throwing FeignExceptions
|
* Whether 404s should be decoded instead of throwing FeignExceptions
|
||||||
*/
|
*/
|
||||||
boolean decode404() default false;
|
boolean decode404() default false;
|
||||||
|
|
||||||
@@ -90,35 +81,33 @@ public @interface FeignClient {
|
|||||||
* {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
|
* {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
|
||||||
*
|
*
|
||||||
* @see FeignClientsConfiguration for the defaults
|
* @see FeignClientsConfiguration for the defaults
|
||||||
* @return list of configurations for feign client
|
|
||||||
*/
|
*/
|
||||||
Class<?>[] configuration() default {};
|
Class<?>[] configuration() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fallback class for the specified Feign client interface. The fallback class must
|
* Fallback class for the specified Feign client interface. The fallback class must
|
||||||
* implement the interface annotated by this annotation and be a valid spring bean.
|
* implement the interface annotated by this annotation and be a valid spring bean.
|
||||||
* @return fallback class for the specified Feign client interface
|
|
||||||
*/
|
*/
|
||||||
Class<?> fallback() default void.class;
|
Class<?> fallback() default void.class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a fallback factory for the specified Feign client interface. The fallback
|
* Define a fallback factory for the specified Feign client interface. The fallback
|
||||||
* factory must produce instances of fallback classes that implement the interface
|
* factory must produce instances of fallback classes that implement the interface
|
||||||
* annotated by {@link FeignClient}. The fallback factory must be a valid spring bean.
|
* annotated by {@link FeignClient}. The fallback factory must be a valid spring
|
||||||
|
* bean.
|
||||||
*
|
*
|
||||||
* @see feign.hystrix.FallbackFactory for details.
|
* @see feign.hystrix.FallbackFactory for details.
|
||||||
* @return fallback factory for the specified Feign client interface
|
|
||||||
*/
|
*/
|
||||||
Class<?> fallbackFactory() default void.class;
|
Class<?> fallbackFactory() default void.class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return path prefix to be used by all method-level mappings. Can be used with or
|
* Path prefix to be used by all method-level mappings. Can be used with or without
|
||||||
* without <code>@RibbonClient</code>.
|
* <code>@RibbonClient</code>.
|
||||||
*/
|
*/
|
||||||
String path() default "";
|
String path() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return whether to mark the feign proxy as a primary bean. Defaults to true.
|
* Whether to mark the feign proxy as a primary bean. Defaults to true.
|
||||||
*/
|
*/
|
||||||
boolean primary() default true;
|
boolean primary() default true;
|
||||||
|
|
||||||
|
|||||||
+3
-16
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -35,15 +35,10 @@ public class FeignClientBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T> Builder<T> forType(final Class<T> type, final String name) {
|
public <T> Builder<T> forType(final Class<T> type, final String name) {
|
||||||
return new Builder<>(this.applicationContext, type, name);
|
return new Builder<>(applicationContext, type, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static class Builder<T> {
|
||||||
* Builder of feign targets.
|
|
||||||
*
|
|
||||||
* @param <T> type of target
|
|
||||||
*/
|
|
||||||
public static final class Builder<T> {
|
|
||||||
|
|
||||||
private FeignClientFactoryBean feignClientFactoryBean;
|
private FeignClientFactoryBean feignClientFactoryBean;
|
||||||
|
|
||||||
@@ -54,7 +49,6 @@ public class FeignClientBuilder {
|
|||||||
this.feignClientFactoryBean.setApplicationContext(applicationContext);
|
this.feignClientFactoryBean.setApplicationContext(applicationContext);
|
||||||
this.feignClientFactoryBean.setType(type);
|
this.feignClientFactoryBean.setType(type);
|
||||||
this.feignClientFactoryBean.setName(FeignClientsRegistrar.getName(name));
|
this.feignClientFactoryBean.setName(FeignClientsRegistrar.getName(name));
|
||||||
this.feignClientFactoryBean.setContextId(FeignClientsRegistrar.getName(name));
|
|
||||||
// preset default values - these values resemble the default values on the
|
// preset default values - these values resemble the default values on the
|
||||||
// FeignClient annotation
|
// FeignClient annotation
|
||||||
this.url("").path("").decode404(false).fallback(void.class)
|
this.url("").path("").decode404(false).fallback(void.class)
|
||||||
@@ -66,11 +60,6 @@ public class FeignClientBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder contextId(final String contextId) {
|
|
||||||
this.feignClientFactoryBean.setContextId(contextId);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder path(final String path) {
|
public Builder path(final String path) {
|
||||||
this.feignClientFactoryBean.setPath(FeignClientsRegistrar.getPath(path));
|
this.feignClientFactoryBean.setPath(FeignClientsRegistrar.getPath(path));
|
||||||
return this;
|
return this;
|
||||||
@@ -100,7 +89,5 @@ public class FeignClientBuilder {
|
|||||||
public <T> T build() {
|
public <T> T build() {
|
||||||
return this.feignClientFactoryBean.getTarget();
|
return this.feignClientFactoryBean.getTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+81
-111
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,6 +19,17 @@ package org.springframework.cloud.openfeign;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
|
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import feign.Client;
|
import feign.Client;
|
||||||
import feign.Contract;
|
import feign.Contract;
|
||||||
import feign.Feign;
|
import feign.Feign;
|
||||||
@@ -31,29 +42,16 @@ import feign.codec.Decoder;
|
|||||||
import feign.codec.Encoder;
|
import feign.codec.Encoder;
|
||||||
import feign.codec.ErrorDecoder;
|
import feign.codec.ErrorDecoder;
|
||||||
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|
||||||
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
* @author Venil Noronha
|
* @author Venil Noronha
|
||||||
* @author Eko Kurniawan Khannedy
|
* @author Eko Kurniawan Khannedy
|
||||||
* @author Gregor Zurowski
|
* @author Gregor Zurowski
|
||||||
*/
|
*/
|
||||||
class FeignClientFactoryBean
|
class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean,
|
||||||
implements FactoryBean<Object>, InitializingBean, ApplicationContextAware {
|
ApplicationContextAware {
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
* WARNING! Nothing in this class should be @Autowired. It causes NPEs because of some
|
* WARNING! Nothing in this class should be @Autowired. It causes NPEs because of some lifecycle race condition.
|
||||||
* lifecycle race condition.
|
|
||||||
***********************************/
|
***********************************/
|
||||||
|
|
||||||
private Class<?> type;
|
private Class<?> type;
|
||||||
@@ -62,8 +60,6 @@ class FeignClientFactoryBean
|
|||||||
|
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
private String contextId;
|
|
||||||
|
|
||||||
private String path;
|
private String path;
|
||||||
|
|
||||||
private boolean decode404;
|
private boolean decode404;
|
||||||
@@ -76,10 +72,14 @@ class FeignClientFactoryBean
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
Assert.hasText(this.contextId, "Context id must be set");
|
|
||||||
Assert.hasText(this.name, "Name must be set");
|
Assert.hasText(this.name, "Name must be set");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||||
|
this.applicationContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
protected Feign.Builder feign(FeignContext context) {
|
protected Feign.Builder feign(FeignContext context) {
|
||||||
FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class);
|
FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class);
|
||||||
Logger logger = loggerFactory.create(this.type);
|
Logger logger = loggerFactory.create(this.type);
|
||||||
@@ -99,33 +99,23 @@ class FeignClientFactoryBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void configureFeign(FeignContext context, Feign.Builder builder) {
|
protected void configureFeign(FeignContext context, Feign.Builder builder) {
|
||||||
FeignClientProperties properties = this.applicationContext
|
FeignClientProperties properties = applicationContext.getBean(FeignClientProperties.class);
|
||||||
.getBean(FeignClientProperties.class);
|
|
||||||
if (properties != null) {
|
if (properties != null) {
|
||||||
if (properties.isDefaultToProperties()) {
|
if (properties.isDefaultToProperties()) {
|
||||||
configureUsingConfiguration(context, builder);
|
configureUsingConfiguration(context, builder);
|
||||||
configureUsingProperties(
|
configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()), builder);
|
||||||
properties.getConfig().get(properties.getDefaultConfig()),
|
configureUsingProperties(properties.getConfig().get(this.name), builder);
|
||||||
builder);
|
} else {
|
||||||
configureUsingProperties(properties.getConfig().get(this.contextId),
|
configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()), builder);
|
||||||
builder);
|
configureUsingProperties(properties.getConfig().get(this.name), builder);
|
||||||
}
|
|
||||||
else {
|
|
||||||
configureUsingProperties(
|
|
||||||
properties.getConfig().get(properties.getDefaultConfig()),
|
|
||||||
builder);
|
|
||||||
configureUsingProperties(properties.getConfig().get(this.contextId),
|
|
||||||
builder);
|
|
||||||
configureUsingConfiguration(context, builder);
|
configureUsingConfiguration(context, builder);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
configureUsingConfiguration(context, builder);
|
configureUsingConfiguration(context, builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void configureUsingConfiguration(FeignContext context,
|
protected void configureUsingConfiguration(FeignContext context, Feign.Builder builder) {
|
||||||
Feign.Builder builder) {
|
|
||||||
Logger.Level level = getOptional(context, Logger.Level.class);
|
Logger.Level level = getOptional(context, Logger.Level.class);
|
||||||
if (level != null) {
|
if (level != null) {
|
||||||
builder.logLevel(level);
|
builder.logLevel(level);
|
||||||
@@ -142,20 +132,18 @@ class FeignClientFactoryBean
|
|||||||
if (options != null) {
|
if (options != null) {
|
||||||
builder.options(options);
|
builder.options(options);
|
||||||
}
|
}
|
||||||
Map<String, RequestInterceptor> requestInterceptors = context
|
Map<String, RequestInterceptor> requestInterceptors = context.getInstances(
|
||||||
.getInstances(this.contextId, RequestInterceptor.class);
|
this.name, RequestInterceptor.class);
|
||||||
if (requestInterceptors != null) {
|
if (requestInterceptors != null) {
|
||||||
builder.requestInterceptors(requestInterceptors.values());
|
builder.requestInterceptors(requestInterceptors.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.decode404) {
|
if (decode404) {
|
||||||
builder.decode404();
|
builder.decode404();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void configureUsingProperties(
|
protected void configureUsingProperties(FeignClientProperties.FeignClientConfiguration config, Feign.Builder builder) {
|
||||||
FeignClientProperties.FeignClientConfiguration config,
|
|
||||||
Feign.Builder builder) {
|
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -165,8 +153,7 @@ class FeignClientFactoryBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.getConnectTimeout() != null && config.getReadTimeout() != null) {
|
if (config.getConnectTimeout() != null && config.getReadTimeout() != null) {
|
||||||
builder.options(new Request.Options(config.getConnectTimeout(),
|
builder.options(new Request.Options(config.getConnectTimeout(), config.getReadTimeout()));
|
||||||
config.getReadTimeout()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.getRetryer() != null) {
|
if (config.getRetryer() != null) {
|
||||||
@@ -179,8 +166,7 @@ class FeignClientFactoryBean
|
|||||||
builder.errorDecoder(errorDecoder);
|
builder.errorDecoder(errorDecoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.getRequestInterceptors() != null
|
if (config.getRequestInterceptors() != null && !config.getRequestInterceptors().isEmpty()) {
|
||||||
&& !config.getRequestInterceptors().isEmpty()) {
|
|
||||||
// this will add request interceptor to builder, not replace existing
|
// this will add request interceptor to builder, not replace existing
|
||||||
for (Class<RequestInterceptor> bean : config.getRequestInterceptors()) {
|
for (Class<RequestInterceptor> bean : config.getRequestInterceptors()) {
|
||||||
RequestInterceptor interceptor = getOrInstantiate(bean);
|
RequestInterceptor interceptor = getOrInstantiate(bean);
|
||||||
@@ -209,24 +195,23 @@ class FeignClientFactoryBean
|
|||||||
|
|
||||||
private <T> T getOrInstantiate(Class<T> tClass) {
|
private <T> T getOrInstantiate(Class<T> tClass) {
|
||||||
try {
|
try {
|
||||||
return this.applicationContext.getBean(tClass);
|
return applicationContext.getBean(tClass);
|
||||||
}
|
} catch (NoSuchBeanDefinitionException e) {
|
||||||
catch (NoSuchBeanDefinitionException e) {
|
|
||||||
return BeanUtils.instantiateClass(tClass);
|
return BeanUtils.instantiateClass(tClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> T get(FeignContext context, Class<T> type) {
|
protected <T> T get(FeignContext context, Class<T> type) {
|
||||||
T instance = context.getInstance(this.contextId, type);
|
T instance = context.getInstance(this.name, type);
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException("No bean found of type " + type + " for "
|
||||||
"No bean found of type " + type + " for " + this.contextId);
|
+ this.name);
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> T getOptional(FeignContext context, Class<T> type) {
|
protected <T> T getOptional(FeignContext context, Class<T> type) {
|
||||||
return context.getInstance(this.contextId, type);
|
return context.getInstance(this.name, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
|
protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
|
||||||
@@ -249,23 +234,23 @@ class FeignClientFactoryBean
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param <T> the target type of the Feign client
|
* @param <T> the target type of the Feign client
|
||||||
* @return a {@link Feign} client created with the specified data and the context
|
* @return a {@link Feign} client created with the specified data and the context information
|
||||||
* information
|
|
||||||
*/
|
*/
|
||||||
<T> T getTarget() {
|
<T> T getTarget() {
|
||||||
FeignContext context = this.applicationContext.getBean(FeignContext.class);
|
FeignContext context = applicationContext.getBean(FeignContext.class);
|
||||||
Feign.Builder builder = feign(context);
|
Feign.Builder builder = feign(context);
|
||||||
|
|
||||||
if (!StringUtils.hasText(this.url)) {
|
if (!StringUtils.hasText(this.url)) {
|
||||||
|
String url;
|
||||||
if (!this.name.startsWith("http")) {
|
if (!this.name.startsWith("http")) {
|
||||||
this.url = "http://" + this.name;
|
url = "http://" + this.name;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.url = this.name;
|
url = this.name;
|
||||||
}
|
}
|
||||||
this.url += cleanPath();
|
url += cleanPath();
|
||||||
return (T) loadBalance(builder, context,
|
return (T) loadBalance(builder, context, new HardCodedTarget<>(this.type,
|
||||||
new HardCodedTarget<>(this.type, this.name, this.url));
|
this.name, url));
|
||||||
}
|
}
|
||||||
if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
|
if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
|
||||||
this.url = "http://" + this.url;
|
this.url = "http://" + this.url;
|
||||||
@@ -276,13 +261,13 @@ class FeignClientFactoryBean
|
|||||||
if (client instanceof LoadBalancerFeignClient) {
|
if (client instanceof LoadBalancerFeignClient) {
|
||||||
// not load balancing because we have a url,
|
// not load balancing because we have a url,
|
||||||
// but ribbon is on the classpath, so unwrap
|
// but ribbon is on the classpath, so unwrap
|
||||||
client = ((LoadBalancerFeignClient) client).getDelegate();
|
client = ((LoadBalancerFeignClient)client).getDelegate();
|
||||||
}
|
}
|
||||||
builder.client(client);
|
builder.client(client);
|
||||||
}
|
}
|
||||||
Targeter targeter = get(context, Targeter.class);
|
Targeter targeter = get(context, Targeter.class);
|
||||||
return (T) targeter.target(this, builder, context,
|
return (T) targeter.target(this, builder, context, new HardCodedTarget<>(
|
||||||
new HardCodedTarget<>(this.type, this.name, url));
|
this.type, this.name, url));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String cleanPath() {
|
private String cleanPath() {
|
||||||
@@ -309,7 +294,7 @@ class FeignClientFactoryBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> getType() {
|
public Class<?> getType() {
|
||||||
return this.type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(Class<?> type) {
|
public void setType(Class<?> type) {
|
||||||
@@ -317,23 +302,15 @@ class FeignClientFactoryBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContextId() {
|
|
||||||
return this.contextId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContextId(String contextId) {
|
|
||||||
this.contextId = contextId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return this.url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUrl(String url) {
|
public void setUrl(String url) {
|
||||||
@@ -341,7 +318,7 @@ class FeignClientFactoryBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getPath() {
|
public String getPath() {
|
||||||
return this.path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPath(String path) {
|
public void setPath(String path) {
|
||||||
@@ -349,7 +326,7 @@ class FeignClientFactoryBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDecode404() {
|
public boolean isDecode404() {
|
||||||
return this.decode404;
|
return decode404;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDecode404(boolean decode404) {
|
public void setDecode404(boolean decode404) {
|
||||||
@@ -357,16 +334,11 @@ class FeignClientFactoryBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ApplicationContext getApplicationContext() {
|
public ApplicationContext getApplicationContext() {
|
||||||
return this.applicationContext;
|
return applicationContext;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
|
||||||
this.applicationContext = context;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> getFallback() {
|
public Class<?> getFallback() {
|
||||||
return this.fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFallback(Class<?> fallback) {
|
public void setFallback(Class<?> fallback) {
|
||||||
@@ -374,7 +346,7 @@ class FeignClientFactoryBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> getFallbackFactory() {
|
public Class<?> getFallbackFactory() {
|
||||||
return this.fallbackFactory;
|
return fallbackFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFallbackFactory(Class<?> fallbackFactory) {
|
public void setFallbackFactory(Class<?> fallbackFactory) {
|
||||||
@@ -383,39 +355,37 @@ class FeignClientFactoryBean
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) return true;
|
||||||
return true;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FeignClientFactoryBean that = (FeignClientFactoryBean) o;
|
FeignClientFactoryBean that = (FeignClientFactoryBean) o;
|
||||||
return Objects.equals(this.applicationContext, that.applicationContext)
|
return Objects.equals(applicationContext, that.applicationContext) &&
|
||||||
&& this.decode404 == that.decode404
|
decode404 == that.decode404 &&
|
||||||
&& Objects.equals(this.fallback, that.fallback)
|
Objects.equals(fallback, that.fallback) &&
|
||||||
&& Objects.equals(this.fallbackFactory, that.fallbackFactory)
|
Objects.equals(fallbackFactory, that.fallbackFactory) &&
|
||||||
&& Objects.equals(this.name, that.name)
|
Objects.equals(name, that.name) &&
|
||||||
&& Objects.equals(this.path, that.path)
|
Objects.equals(path, that.path) &&
|
||||||
&& Objects.equals(this.type, that.type)
|
Objects.equals(type, that.type) &&
|
||||||
&& Objects.equals(this.url, that.url);
|
Objects.equals(url, that.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(this.applicationContext, this.decode404, this.fallback,
|
return Objects.hash(applicationContext, decode404, fallback, fallbackFactory,
|
||||||
this.fallbackFactory, this.name, this.path, this.type, this.url);
|
name, path, type, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new StringBuilder("FeignClientFactoryBean{").append("type=")
|
return new StringBuilder("FeignClientFactoryBean{")
|
||||||
.append(this.type).append(", ").append("name='").append(this.name)
|
.append("type=").append(type).append(", ")
|
||||||
.append("', ").append("url='").append(this.url).append("', ")
|
.append("name='").append(name).append("', ")
|
||||||
.append("path='").append(this.path).append("', ").append("decode404=")
|
.append("url='").append(url).append("', ")
|
||||||
.append(this.decode404).append(", ").append("applicationContext=")
|
.append("path='").append(path).append("', ")
|
||||||
.append(this.applicationContext).append(", ").append("fallback=")
|
.append("decode404=").append(decode404).append(", ")
|
||||||
.append(this.fallback).append(", ").append("fallbackFactory=")
|
.append("applicationContext=").append(applicationContext).append(", ")
|
||||||
.append(this.fallbackFactory).append("}").toString();
|
.append("fallback=").append(fallback).append(", ")
|
||||||
|
.append("fallbackFactory=").append(fallbackFactory)
|
||||||
|
.append("}").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-56
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -13,14 +13,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import feign.Contract;
|
import feign.Contract;
|
||||||
import feign.Logger;
|
import feign.Logger;
|
||||||
import feign.RequestInterceptor;
|
import feign.RequestInterceptor;
|
||||||
@@ -28,9 +22,13 @@ import feign.Retryer;
|
|||||||
import feign.codec.Decoder;
|
import feign.codec.Decoder;
|
||||||
import feign.codec.Encoder;
|
import feign.codec.Encoder;
|
||||||
import feign.codec.ErrorDecoder;
|
import feign.codec.ErrorDecoder;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Eko Kurniawan Khannedy
|
* @author Eko Kurniawan Khannedy
|
||||||
*/
|
*/
|
||||||
@@ -44,7 +42,7 @@ public class FeignClientProperties {
|
|||||||
private Map<String, FeignClientConfiguration> config = new HashMap<>();
|
private Map<String, FeignClientConfiguration> config = new HashMap<>();
|
||||||
|
|
||||||
public boolean isDefaultToProperties() {
|
public boolean isDefaultToProperties() {
|
||||||
return this.defaultToProperties;
|
return defaultToProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultToProperties(boolean defaultToProperties) {
|
public void setDefaultToProperties(boolean defaultToProperties) {
|
||||||
@@ -52,7 +50,7 @@ public class FeignClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getDefaultConfig() {
|
public String getDefaultConfig() {
|
||||||
return this.defaultConfig;
|
return defaultConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultConfig(String defaultConfig) {
|
public void setDefaultConfig(String defaultConfig) {
|
||||||
@@ -60,7 +58,7 @@ public class FeignClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, FeignClientConfiguration> getConfig() {
|
public Map<String, FeignClientConfiguration> getConfig() {
|
||||||
return this.config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConfig(Map<String, FeignClientConfiguration> config) {
|
public void setConfig(Map<String, FeignClientConfiguration> config) {
|
||||||
@@ -69,26 +67,19 @@ public class FeignClientProperties {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) return true;
|
||||||
return true;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FeignClientProperties that = (FeignClientProperties) o;
|
FeignClientProperties that = (FeignClientProperties) o;
|
||||||
return this.defaultToProperties == that.defaultToProperties
|
return defaultToProperties == that.defaultToProperties &&
|
||||||
&& Objects.equals(this.defaultConfig, that.defaultConfig)
|
Objects.equals(defaultConfig, that.defaultConfig) &&
|
||||||
&& Objects.equals(this.config, that.config);
|
Objects.equals(config, that.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(this.defaultToProperties, this.defaultConfig, this.config);
|
return Objects.hash(defaultToProperties, defaultConfig, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Feign client configuration.
|
|
||||||
*/
|
|
||||||
public static class FeignClientConfiguration {
|
public static class FeignClientConfiguration {
|
||||||
|
|
||||||
private Logger.Level loggerLevel;
|
private Logger.Level loggerLevel;
|
||||||
@@ -112,7 +103,7 @@ public class FeignClientProperties {
|
|||||||
private Class<Contract> contract;
|
private Class<Contract> contract;
|
||||||
|
|
||||||
public Logger.Level getLoggerLevel() {
|
public Logger.Level getLoggerLevel() {
|
||||||
return this.loggerLevel;
|
return loggerLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLoggerLevel(Logger.Level loggerLevel) {
|
public void setLoggerLevel(Logger.Level loggerLevel) {
|
||||||
@@ -120,7 +111,7 @@ public class FeignClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Integer getConnectTimeout() {
|
public Integer getConnectTimeout() {
|
||||||
return this.connectTimeout;
|
return connectTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConnectTimeout(Integer connectTimeout) {
|
public void setConnectTimeout(Integer connectTimeout) {
|
||||||
@@ -128,7 +119,7 @@ public class FeignClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Integer getReadTimeout() {
|
public Integer getReadTimeout() {
|
||||||
return this.readTimeout;
|
return readTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReadTimeout(Integer readTimeout) {
|
public void setReadTimeout(Integer readTimeout) {
|
||||||
@@ -136,7 +127,7 @@ public class FeignClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class<Retryer> getRetryer() {
|
public Class<Retryer> getRetryer() {
|
||||||
return this.retryer;
|
return retryer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRetryer(Class<Retryer> retryer) {
|
public void setRetryer(Class<Retryer> retryer) {
|
||||||
@@ -144,7 +135,7 @@ public class FeignClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class<ErrorDecoder> getErrorDecoder() {
|
public Class<ErrorDecoder> getErrorDecoder() {
|
||||||
return this.errorDecoder;
|
return errorDecoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setErrorDecoder(Class<ErrorDecoder> errorDecoder) {
|
public void setErrorDecoder(Class<ErrorDecoder> errorDecoder) {
|
||||||
@@ -152,16 +143,15 @@ public class FeignClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<Class<RequestInterceptor>> getRequestInterceptors() {
|
public List<Class<RequestInterceptor>> getRequestInterceptors() {
|
||||||
return this.requestInterceptors;
|
return requestInterceptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRequestInterceptors(
|
public void setRequestInterceptors(List<Class<RequestInterceptor>> requestInterceptors) {
|
||||||
List<Class<RequestInterceptor>> requestInterceptors) {
|
|
||||||
this.requestInterceptors = requestInterceptors;
|
this.requestInterceptors = requestInterceptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getDecode404() {
|
public Boolean getDecode404() {
|
||||||
return this.decode404;
|
return decode404;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDecode404(Boolean decode404) {
|
public void setDecode404(Boolean decode404) {
|
||||||
@@ -169,7 +159,7 @@ public class FeignClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class<Decoder> getDecoder() {
|
public Class<Decoder> getDecoder() {
|
||||||
return this.decoder;
|
return decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDecoder(Class<Decoder> decoder) {
|
public void setDecoder(Class<Decoder> decoder) {
|
||||||
@@ -177,7 +167,7 @@ public class FeignClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class<Encoder> getEncoder() {
|
public Class<Encoder> getEncoder() {
|
||||||
return this.encoder;
|
return encoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEncoder(Class<Encoder> encoder) {
|
public void setEncoder(Class<Encoder> encoder) {
|
||||||
@@ -185,7 +175,7 @@ public class FeignClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class<Contract> getContract() {
|
public Class<Contract> getContract() {
|
||||||
return this.contract;
|
return contract;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContract(Class<Contract> contract) {
|
public void setContract(Class<Contract> contract) {
|
||||||
@@ -194,32 +184,26 @@ public class FeignClientProperties {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) return true;
|
||||||
return true;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FeignClientConfiguration that = (FeignClientConfiguration) o;
|
FeignClientConfiguration that = (FeignClientConfiguration) o;
|
||||||
return this.loggerLevel == that.loggerLevel
|
return loggerLevel == that.loggerLevel &&
|
||||||
&& Objects.equals(this.connectTimeout, that.connectTimeout)
|
Objects.equals(connectTimeout, that.connectTimeout) &&
|
||||||
&& Objects.equals(this.readTimeout, that.readTimeout)
|
Objects.equals(readTimeout, that.readTimeout) &&
|
||||||
&& Objects.equals(this.retryer, that.retryer)
|
Objects.equals(retryer, that.retryer) &&
|
||||||
&& Objects.equals(this.errorDecoder, that.errorDecoder)
|
Objects.equals(errorDecoder, that.errorDecoder) &&
|
||||||
&& Objects.equals(this.requestInterceptors, that.requestInterceptors)
|
Objects.equals(requestInterceptors, that.requestInterceptors) &&
|
||||||
&& Objects.equals(this.decode404, that.decode404)
|
Objects.equals(decode404, that.decode404) &&
|
||||||
&& Objects.equals(this.encoder, that.encoder)
|
Objects.equals(encoder, that.encoder) &&
|
||||||
&& Objects.equals(this.decoder, that.decoder)
|
Objects.equals(decoder, that.decoder) &&
|
||||||
&& Objects.equals(this.contract, that.contract);
|
Objects.equals(contract, that.contract);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(this.loggerLevel, this.connectTimeout, this.readTimeout,
|
return Objects.hash(loggerLevel, connectTimeout, readTimeout, retryer,
|
||||||
this.retryer, this.errorDecoder, this.requestInterceptors,
|
errorDecoder, requestInterceptors, decode404, encoder, decoder, contract);
|
||||||
this.decode404, this.encoder, this.decoder, this.contract);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-20
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,11 +16,11 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
|
import org.springframework.cloud.context.named.NamedContextFactory;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.springframework.cloud.context.named.NamedContextFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Gregor Zurowski
|
* @author Gregor Zurowski
|
||||||
@@ -31,16 +31,15 @@ class FeignClientSpecification implements NamedContextFactory.Specification {
|
|||||||
|
|
||||||
private Class<?>[] configuration;
|
private Class<?>[] configuration;
|
||||||
|
|
||||||
FeignClientSpecification() {
|
public FeignClientSpecification() {}
|
||||||
}
|
|
||||||
|
|
||||||
FeignClientSpecification(String name, Class<?>[] configuration) {
|
public FeignClientSpecification(String name, Class<?>[] configuration) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
@@ -48,7 +47,7 @@ class FeignClientSpecification implements NamedContextFactory.Specification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class<?>[] getConfiguration() {
|
public Class<?>[] getConfiguration() {
|
||||||
return this.configuration;
|
return configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConfiguration(Class<?>[] configuration) {
|
public void setConfiguration(Class<?>[] configuration) {
|
||||||
@@ -57,27 +56,24 @@ class FeignClientSpecification implements NamedContextFactory.Specification {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) return true;
|
||||||
return true;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FeignClientSpecification that = (FeignClientSpecification) o;
|
FeignClientSpecification that = (FeignClientSpecification) o;
|
||||||
return Objects.equals(this.name, that.name)
|
return Objects.equals(name, that.name) &&
|
||||||
&& Arrays.equals(this.configuration, that.configuration);
|
Arrays.equals(configuration, that.configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(this.name, this.configuration);
|
return Objects.hash(name, configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new StringBuilder("FeignClientSpecification{").append("name='")
|
return new StringBuilder("FeignClientSpecification{")
|
||||||
.append(this.name).append("', ").append("configuration=")
|
.append("name='").append(name).append("', ")
|
||||||
.append(Arrays.toString(this.configuration)).append("}").toString();
|
.append("configuration=").append(Arrays.toString(configuration))
|
||||||
|
.append("}").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-47
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
@@ -19,26 +20,12 @@ package org.springframework.cloud.openfeign;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.Module;
|
|
||||||
import com.netflix.hystrix.HystrixCommand;
|
|
||||||
import feign.Contract;
|
|
||||||
import feign.Feign;
|
|
||||||
import feign.Logger;
|
|
||||||
import feign.Retryer;
|
|
||||||
import feign.codec.Decoder;
|
|
||||||
import feign.codec.Encoder;
|
|
||||||
import feign.hystrix.HystrixFeign;
|
|
||||||
import feign.optionals.OptionalDecoder;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectFactory;
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||||
import org.springframework.cloud.openfeign.support.PageJacksonModule;
|
|
||||||
import org.springframework.cloud.openfeign.support.PageableSpringEncoder;
|
|
||||||
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
|
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
|
||||||
import org.springframework.cloud.openfeign.support.SpringDecoder;
|
import org.springframework.cloud.openfeign.support.SpringDecoder;
|
||||||
import org.springframework.cloud.openfeign.support.SpringEncoder;
|
import org.springframework.cloud.openfeign.support.SpringEncoder;
|
||||||
@@ -50,6 +37,17 @@ import org.springframework.core.convert.ConversionService;
|
|||||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||||
import org.springframework.format.support.FormattingConversionService;
|
import org.springframework.format.support.FormattingConversionService;
|
||||||
|
|
||||||
|
import com.netflix.hystrix.HystrixCommand;
|
||||||
|
|
||||||
|
import feign.Contract;
|
||||||
|
import feign.Feign;
|
||||||
|
import feign.Logger;
|
||||||
|
import feign.Retryer;
|
||||||
|
import feign.codec.Decoder;
|
||||||
|
import feign.codec.Encoder;
|
||||||
|
import feign.hystrix.HystrixFeign;
|
||||||
|
import feign.optionals.OptionalDecoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Venil Noronha
|
* @author Venil Noronha
|
||||||
@@ -72,24 +70,15 @@ public class FeignClientsConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public Decoder feignDecoder() {
|
public Decoder feignDecoder() {
|
||||||
return new OptionalDecoder(
|
return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
|
||||||
new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@ConditionalOnMissingClass("org.springframework.data.domain.Pageable")
|
|
||||||
public Encoder feignEncoder() {
|
public Encoder feignEncoder() {
|
||||||
return new SpringEncoder(this.messageConverters);
|
return new SpringEncoder(this.messageConverters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnClass(name = "org.springframework.data.domain.Pageable")
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
public Encoder feignEncoderPageable() {
|
|
||||||
return new PageableSpringEncoder(new SpringEncoder(this.messageConverters));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public Contract feignContract(ConversionService feignConversionService) {
|
public Contract feignContract(ConversionService feignConversionService) {
|
||||||
@@ -99,12 +88,24 @@ public class FeignClientsConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
public FormattingConversionService feignConversionService() {
|
public FormattingConversionService feignConversionService() {
|
||||||
FormattingConversionService conversionService = new DefaultFormattingConversionService();
|
FormattingConversionService conversionService = new DefaultFormattingConversionService();
|
||||||
for (FeignFormatterRegistrar feignFormatterRegistrar : this.feignFormatterRegistrars) {
|
for (FeignFormatterRegistrar feignFormatterRegistrar : feignFormatterRegistrars) {
|
||||||
feignFormatterRegistrar.registerFormatters(conversionService);
|
feignFormatterRegistrar.registerFormatters(conversionService);
|
||||||
}
|
}
|
||||||
return conversionService;
|
return conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
|
||||||
|
protected static class HystrixFeignConfiguration {
|
||||||
|
@Bean
|
||||||
|
@Scope("prototype")
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@ConditionalOnProperty(name = "feign.hystrix.enabled")
|
||||||
|
public Feign.Builder feignHystrixBuilder() {
|
||||||
|
return HystrixFeign.builder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public Retryer feignRetryer() {
|
public Retryer feignRetryer() {
|
||||||
@@ -121,27 +122,7 @@ public class FeignClientsConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(FeignLoggerFactory.class)
|
@ConditionalOnMissingBean(FeignLoggerFactory.class)
|
||||||
public FeignLoggerFactory feignLoggerFactory() {
|
public FeignLoggerFactory feignLoggerFactory() {
|
||||||
return new DefaultFeignLoggerFactory(this.logger);
|
return new DefaultFeignLoggerFactory(logger);
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnClass(name = "org.springframework.data.domain.Page")
|
|
||||||
public Module pageJacksonModule() {
|
|
||||||
return new PageJacksonModule();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
|
|
||||||
protected static class HystrixFeignConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@Scope("prototype")
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
@ConditionalOnProperty(name = "feign.hystrix.enabled")
|
|
||||||
public Feign.Builder feignHystrixBuilder() {
|
|
||||||
return HystrixFeign.builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+70
-86
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -58,8 +58,8 @@ import org.springframework.util.StringUtils;
|
|||||||
* @author Venil Noronha
|
* @author Venil Noronha
|
||||||
* @author Gang Li
|
* @author Gang Li
|
||||||
*/
|
*/
|
||||||
class FeignClientsRegistrar
|
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
|
||||||
implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
|
ResourceLoaderAware, EnvironmentAware {
|
||||||
|
|
||||||
// patterned after Spring Integration IntegrationComponentScanRegistrar
|
// patterned after Spring Integration IntegrationComponentScanRegistrar
|
||||||
// and RibbonClientsConfigurationRegistgrar
|
// and RibbonClientsConfigurationRegistgrar
|
||||||
@@ -68,68 +68,7 @@ class FeignClientsRegistrar
|
|||||||
|
|
||||||
private Environment environment;
|
private Environment environment;
|
||||||
|
|
||||||
FeignClientsRegistrar() {
|
public FeignClientsRegistrar() {
|
||||||
}
|
|
||||||
|
|
||||||
static void validateFallback(final Class clazz) {
|
|
||||||
Assert.isTrue(!clazz.isInterface(),
|
|
||||||
"Fallback class must implement the interface annotated by @FeignClient");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void validateFallbackFactory(final Class clazz) {
|
|
||||||
Assert.isTrue(!clazz.isInterface(), "Fallback factory must produce instances "
|
|
||||||
+ "of fallback classes that implement the interface annotated by @FeignClient");
|
|
||||||
}
|
|
||||||
|
|
||||||
static String getName(String name) {
|
|
||||||
if (!StringUtils.hasText(name)) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
String host = null;
|
|
||||||
try {
|
|
||||||
String url;
|
|
||||||
if (!name.startsWith("http://") && !name.startsWith("https://")) {
|
|
||||||
url = "http://" + name;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
url = name;
|
|
||||||
}
|
|
||||||
host = new URI(url).getHost();
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (URISyntaxException e) {
|
|
||||||
}
|
|
||||||
Assert.state(host != null, "Service id not legal hostname (" + name + ")");
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static String getUrl(String url) {
|
|
||||||
if (StringUtils.hasText(url) && !(url.startsWith("#{") && url.contains("}"))) {
|
|
||||||
if (!url.contains("://")) {
|
|
||||||
url = "http://" + url;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
new URL(url);
|
|
||||||
}
|
|
||||||
catch (MalformedURLException e) {
|
|
||||||
throw new IllegalArgumentException(url + " is malformed", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
static String getPath(String path) {
|
|
||||||
if (StringUtils.hasText(path)) {
|
|
||||||
path = path.trim();
|
|
||||||
if (!path.startsWith("/")) {
|
|
||||||
path = "/" + path;
|
|
||||||
}
|
|
||||||
if (path.endsWith("/")) {
|
|
||||||
path = path.substring(0, path.length() - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -232,19 +171,16 @@ class FeignClientsRegistrar
|
|||||||
definition.addPropertyValue("path", getPath(attributes));
|
definition.addPropertyValue("path", getPath(attributes));
|
||||||
String name = getName(attributes);
|
String name = getName(attributes);
|
||||||
definition.addPropertyValue("name", name);
|
definition.addPropertyValue("name", name);
|
||||||
String contextId = getContextId(attributes);
|
|
||||||
definition.addPropertyValue("contextId", contextId);
|
|
||||||
definition.addPropertyValue("type", className);
|
definition.addPropertyValue("type", className);
|
||||||
definition.addPropertyValue("decode404", attributes.get("decode404"));
|
definition.addPropertyValue("decode404", attributes.get("decode404"));
|
||||||
definition.addPropertyValue("fallback", attributes.get("fallback"));
|
definition.addPropertyValue("fallback", attributes.get("fallback"));
|
||||||
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
|
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
|
||||||
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
|
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||||
|
|
||||||
String alias = contextId + "FeignClient";
|
String alias = name + "FeignClient";
|
||||||
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
|
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
|
||||||
|
|
||||||
boolean primary = (Boolean) attributes.get("primary"); // has a default, won't be
|
boolean primary = (Boolean)attributes.get("primary"); // has a default, won't be null
|
||||||
// null
|
|
||||||
|
|
||||||
beanDefinition.setPrimary(primary);
|
beanDefinition.setPrimary(primary);
|
||||||
|
|
||||||
@@ -266,6 +202,19 @@ class FeignClientsRegistrar
|
|||||||
validateFallbackFactory(annotation.getClass("fallbackFactory"));
|
validateFallbackFactory(annotation.getClass("fallbackFactory"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void validateFallback(final Class clazz) {
|
||||||
|
Assert.isTrue(
|
||||||
|
!clazz.isInterface(),
|
||||||
|
"Fallback class must implement the interface annotated by @FeignClient"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void validateFallbackFactory(final Class clazz) {
|
||||||
|
Assert.isTrue(!clazz.isInterface(),
|
||||||
|
"Fallback factory must produce instances of fallback classes that implement the interface annotated by @FeignClient"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/* for testing */ String getName(Map<String, Object> attributes) {
|
/* for testing */ String getName(Map<String, Object> attributes) {
|
||||||
String name = (String) attributes.get("serviceId");
|
String name = (String) attributes.get("serviceId");
|
||||||
if (!StringUtils.hasText(name)) {
|
if (!StringUtils.hasText(name)) {
|
||||||
@@ -278,14 +227,26 @@ class FeignClientsRegistrar
|
|||||||
return getName(name);
|
return getName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getContextId(Map<String, Object> attributes) {
|
static String getName(String name) {
|
||||||
String contextId = (String) attributes.get("contextId");
|
if (!StringUtils.hasText(name)) {
|
||||||
if (!StringUtils.hasText(contextId)) {
|
return "";
|
||||||
return getName(attributes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
contextId = resolve(contextId);
|
String host = null;
|
||||||
return getName(contextId);
|
try {
|
||||||
|
String url;
|
||||||
|
if (!name.startsWith("http://") && !name.startsWith("https://")) {
|
||||||
|
url = "http://" + name;
|
||||||
|
} else {
|
||||||
|
url = name;
|
||||||
|
}
|
||||||
|
host = new URI(url).getHost();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (URISyntaxException e) {
|
||||||
|
}
|
||||||
|
Assert.state(host != null, "Service id not legal hostname (" + name + ")");
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String resolve(String value) {
|
private String resolve(String value) {
|
||||||
@@ -300,16 +261,43 @@ class FeignClientsRegistrar
|
|||||||
return getUrl(url);
|
return getUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String getUrl(String url) {
|
||||||
|
if (StringUtils.hasText(url) && !(url.startsWith("#{") && url.contains("}"))) {
|
||||||
|
if (!url.contains("://")) {
|
||||||
|
url = "http://" + url;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
new URL(url);
|
||||||
|
}
|
||||||
|
catch (MalformedURLException e) {
|
||||||
|
throw new IllegalArgumentException(url + " is malformed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
private String getPath(Map<String, Object> attributes) {
|
private String getPath(Map<String, Object> attributes) {
|
||||||
String path = resolve((String) attributes.get("path"));
|
String path = resolve((String) attributes.get("path"));
|
||||||
return getPath(path);
|
return getPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String getPath(String path) {
|
||||||
|
if (StringUtils.hasText(path)) {
|
||||||
|
path = path.trim();
|
||||||
|
if (!path.startsWith("/")) {
|
||||||
|
path = "/" + path;
|
||||||
|
}
|
||||||
|
if (path.endsWith("/")) {
|
||||||
|
path = path.substring(0, path.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
protected ClassPathScanningCandidateComponentProvider getScanner() {
|
protected ClassPathScanningCandidateComponentProvider getScanner() {
|
||||||
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
|
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
|
||||||
@Override
|
@Override
|
||||||
protected boolean isCandidateComponent(
|
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
|
||||||
AnnotatedBeanDefinition beanDefinition) {
|
|
||||||
boolean isCandidate = false;
|
boolean isCandidate = false;
|
||||||
if (beanDefinition.getMetadata().isIndependent()) {
|
if (beanDefinition.getMetadata().isIndependent()) {
|
||||||
if (!beanDefinition.getMetadata().isAnnotation()) {
|
if (!beanDefinition.getMetadata().isAnnotation()) {
|
||||||
@@ -346,7 +334,7 @@ class FeignClientsRegistrar
|
|||||||
}
|
}
|
||||||
return basePackages;
|
return basePackages;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getQualifier(Map<String, Object> client) {
|
private String getQualifier(Map<String, Object> client) {
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -362,10 +350,7 @@ class FeignClientsRegistrar
|
|||||||
if (client == null) {
|
if (client == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String value = (String) client.get("contextId");
|
String value = (String) client.get("value");
|
||||||
if (!StringUtils.hasText(value)) {
|
|
||||||
value = (String) client.get("value");
|
|
||||||
}
|
|
||||||
if (!StringUtils.hasText(value)) {
|
if (!StringUtils.hasText(value)) {
|
||||||
value = (String) client.get("name");
|
value = (String) client.get("name");
|
||||||
}
|
}
|
||||||
@@ -408,9 +393,10 @@ class FeignClientsRegistrar
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link AllTypeFilter} to match if all the given delegates match.
|
* Creates a new {@link AllTypeFilter} to match if all the given delegates match.
|
||||||
|
*
|
||||||
* @param delegates must not be {@literal null}.
|
* @param delegates must not be {@literal null}.
|
||||||
*/
|
*/
|
||||||
AllTypeFilter(List<TypeFilter> delegates) {
|
public AllTypeFilter(List<TypeFilter> delegates) {
|
||||||
Assert.notNull(delegates, "This argument is required, it must not be null");
|
Assert.notNull(delegates, "This argument is required, it must not be null");
|
||||||
this.delegates = delegates;
|
this.delegates = delegates;
|
||||||
}
|
}
|
||||||
@@ -427,7 +413,5 @@ class FeignClientsRegistrar
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
+3
-2
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2019 the original author or authors.
|
* Copyright 2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -27,9 +27,10 @@ public interface FeignLoggerFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method to provide a {@link Logger} for a given {@link Class}.
|
* Factory method to provide a {@link Logger} for a given {@link Class}.
|
||||||
|
*
|
||||||
* @param type the {@link Class} for which a {@link Logger} instance is to be created
|
* @param type the {@link Class} for which a {@link Logger} instance is to be created
|
||||||
* @return a {@link Logger} instance
|
* @return a {@link Logger} instance
|
||||||
*/
|
*/
|
||||||
Logger create(Class<?> type);
|
public Logger create(Class<?> type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-28
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,10 +12,13 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import feign.Feign;
|
import feign.Feign;
|
||||||
import feign.Target;
|
import feign.Target;
|
||||||
import feign.hystrix.FallbackFactory;
|
import feign.hystrix.FallbackFactory;
|
||||||
@@ -30,70 +33,66 @@ import feign.hystrix.SetterFactory;
|
|||||||
class HystrixTargeter implements Targeter {
|
class HystrixTargeter implements Targeter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign,
|
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
|
||||||
FeignContext context, Target.HardCodedTarget<T> target) {
|
Target.HardCodedTarget<T> target) {
|
||||||
if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
|
if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
|
||||||
return feign.target(target);
|
return feign.target(target);
|
||||||
}
|
}
|
||||||
feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign;
|
feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign;
|
||||||
SetterFactory setterFactory = getOptional(factory.getName(), context,
|
SetterFactory setterFactory = getOptional(factory.getName(), context,
|
||||||
SetterFactory.class);
|
SetterFactory.class);
|
||||||
if (setterFactory != null) {
|
if (setterFactory != null) {
|
||||||
builder.setterFactory(setterFactory);
|
builder.setterFactory(setterFactory);
|
||||||
}
|
}
|
||||||
Class<?> fallback = factory.getFallback();
|
Class<?> fallback = factory.getFallback();
|
||||||
if (fallback != void.class) {
|
if (fallback != void.class) {
|
||||||
return targetWithFallback(factory.getName(), context, target, builder,
|
return targetWithFallback(factory.getName(), context, target, builder, fallback);
|
||||||
fallback);
|
|
||||||
}
|
}
|
||||||
Class<?> fallbackFactory = factory.getFallbackFactory();
|
Class<?> fallbackFactory = factory.getFallbackFactory();
|
||||||
if (fallbackFactory != void.class) {
|
if (fallbackFactory != void.class) {
|
||||||
return targetWithFallbackFactory(factory.getName(), context, target, builder,
|
return targetWithFallbackFactory(factory.getName(), context, target, builder, fallbackFactory);
|
||||||
fallbackFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return feign.target(target);
|
return feign.target(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T targetWithFallbackFactory(String feignClientName, FeignContext context,
|
private <T> T targetWithFallbackFactory(String feignClientName, FeignContext context,
|
||||||
Target.HardCodedTarget<T> target, HystrixFeign.Builder builder,
|
Target.HardCodedTarget<T> target,
|
||||||
Class<?> fallbackFactoryClass) {
|
HystrixFeign.Builder builder,
|
||||||
FallbackFactory<? extends T> fallbackFactory = (FallbackFactory<? extends T>) getFromContext(
|
Class<?> fallbackFactoryClass) {
|
||||||
"fallbackFactory", feignClientName, context, fallbackFactoryClass,
|
FallbackFactory<? extends T> fallbackFactory = (FallbackFactory<? extends T>)
|
||||||
FallbackFactory.class);
|
getFromContext("fallbackFactory", feignClientName, context, fallbackFactoryClass, FallbackFactory.class);
|
||||||
return builder.target(target, fallbackFactory);
|
return builder.target(target, fallbackFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private <T> T targetWithFallback(String feignClientName, FeignContext context,
|
private <T> T targetWithFallback(String feignClientName, FeignContext context,
|
||||||
Target.HardCodedTarget<T> target, HystrixFeign.Builder builder,
|
Target.HardCodedTarget<T> target,
|
||||||
Class<?> fallback) {
|
HystrixFeign.Builder builder, Class<?> fallback) {
|
||||||
T fallbackInstance = getFromContext("fallback", feignClientName, context,
|
T fallbackInstance = getFromContext("fallback", feignClientName, context, fallback, target.type());
|
||||||
fallback, target.type());
|
|
||||||
return builder.target(target, fallbackInstance);
|
return builder.target(target, fallbackInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T getFromContext(String fallbackMechanism, String feignClientName,
|
private <T> T getFromContext(String fallbackMechanism, String feignClientName, FeignContext context,
|
||||||
FeignContext context, Class<?> beanType, Class<T> targetType) {
|
Class<?> beanType, Class<T> targetType) {
|
||||||
Object fallbackInstance = context.getInstance(feignClientName, beanType);
|
Object fallbackInstance = context.getInstance(feignClientName, beanType);
|
||||||
if (fallbackInstance == null) {
|
if (fallbackInstance == null) {
|
||||||
throw new IllegalStateException(String.format(
|
throw new IllegalStateException(String.format(
|
||||||
"No " + fallbackMechanism
|
"No " + fallbackMechanism + " instance of type %s found for feign client %s",
|
||||||
+ " instance of type %s found for feign client %s",
|
beanType, feignClientName));
|
||||||
beanType, feignClientName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!targetType.isAssignableFrom(beanType)) {
|
if (!targetType.isAssignableFrom(beanType)) {
|
||||||
throw new IllegalStateException(String.format("Incompatible "
|
throw new IllegalStateException(
|
||||||
+ fallbackMechanism
|
String.format(
|
||||||
+ " instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s",
|
"Incompatible " + fallbackMechanism + " instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s",
|
||||||
beanType, targetType, feignClientName));
|
beanType, targetType, feignClientName));
|
||||||
}
|
}
|
||||||
return (T) fallbackInstance;
|
return (T) fallbackInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T getOptional(String feignClientName, FeignContext context,
|
private <T> T getOptional(String feignClientName, FeignContext context,
|
||||||
Class<T> beanType) {
|
Class<T> beanType) {
|
||||||
return context.getInstance(feignClientName, beanType);
|
return context.getInstance(feignClientName, beanType);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-53
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2019 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;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import feign.QueryMap;
|
|
||||||
|
|
||||||
import org.springframework.core.annotation.AliasFor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spring MVC equivalent of OpenFeign's {@link feign.QueryMap} parameter annotation.
|
|
||||||
*
|
|
||||||
* @author Aram Peres
|
|
||||||
* @see feign.QueryMap
|
|
||||||
* @see org.springframework.cloud.openfeign.annotation.QueryMapParameterProcessor
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ ElementType.PARAMETER })
|
|
||||||
public @interface SpringQueryMap {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see QueryMap#encoded()
|
|
||||||
* @return alias for {@link #encoded()}.
|
|
||||||
*/
|
|
||||||
@AliasFor("encoded")
|
|
||||||
boolean value() default false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see QueryMap#encoded()
|
|
||||||
* @return Specifies whether parameter names and values are already encoded.
|
|
||||||
*/
|
|
||||||
@AliasFor("value")
|
|
||||||
boolean encoded() default false;
|
|
||||||
|
|
||||||
}
|
|
||||||
+4
-5
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
@@ -23,8 +24,6 @@ import feign.Target;
|
|||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
*/
|
*/
|
||||||
interface Targeter {
|
interface Targeter {
|
||||||
|
<T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
|
||||||
<T> T target(FeignClientFactoryBean factory, Feign.Builder feign,
|
Target.HardCodedTarget<T> target);
|
||||||
FeignContext context, Target.HardCodedTarget<T> target);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-8
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -21,11 +21,11 @@ import java.lang.reflect.Method;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import feign.MethodMetadata;
|
|
||||||
|
|
||||||
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
|
||||||
|
import feign.MethodMetadata;
|
||||||
|
|
||||||
import static feign.Util.checkState;
|
import static feign.Util.checkState;
|
||||||
import static feign.Util.emptyToNull;
|
import static feign.Util.emptyToNull;
|
||||||
|
|
||||||
@@ -46,12 +46,10 @@ public class PathVariableParameterProcessor implements AnnotatedParameterProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processArgument(AnnotatedParameterContext context,
|
public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) {
|
||||||
Annotation annotation, Method method) {
|
|
||||||
String name = ANNOTATION.cast(annotation).value();
|
String name = ANNOTATION.cast(annotation).value();
|
||||||
checkState(emptyToNull(name) != null,
|
checkState(emptyToNull(name) != null,
|
||||||
"PathVariable annotation was empty on param %s.",
|
"PathVariable annotation was empty on param %s.", context.getParameterIndex());
|
||||||
context.getParameterIndex());
|
|
||||||
context.setParameterName(name);
|
context.setParameterName(name);
|
||||||
|
|
||||||
MethodMetadata data = context.getMethodMetadata();
|
MethodMetadata data = context.getMethodMetadata();
|
||||||
@@ -76,5 +74,4 @@ public class PathVariableParameterProcessor implements AnnotatedParameterProcess
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-54
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2019 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 feign.MethodMetadata;
|
|
||||||
|
|
||||||
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
|
||||||
import org.springframework.cloud.openfeign.SpringQueryMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link SpringQueryMap} parameter processor.
|
|
||||||
*
|
|
||||||
* @author Aram Peres
|
|
||||||
* @see AnnotatedParameterProcessor
|
|
||||||
*/
|
|
||||||
public class QueryMapParameterProcessor implements AnnotatedParameterProcessor {
|
|
||||||
|
|
||||||
private static final Class<SpringQueryMap> ANNOTATION = SpringQueryMap.class;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends Annotation> getAnnotationType() {
|
|
||||||
return ANNOTATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean processArgument(AnnotatedParameterContext context,
|
|
||||||
Annotation annotation, Method method) {
|
|
||||||
int paramIndex = context.getParameterIndex();
|
|
||||||
MethodMetadata metadata = context.getMethodMetadata();
|
|
||||||
if (metadata.queryMapIndex() == null) {
|
|
||||||
metadata.queryMapIndex(paramIndex);
|
|
||||||
metadata.queryMapEncoded(SpringQueryMap.class.cast(annotation).encoded());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+6
-10
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -21,11 +21,11 @@ import java.lang.reflect.Method;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import feign.MethodMetadata;
|
|
||||||
|
|
||||||
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
||||||
import org.springframework.web.bind.annotation.RequestHeader;
|
import org.springframework.web.bind.annotation.RequestHeader;
|
||||||
|
|
||||||
|
import feign.MethodMetadata;
|
||||||
|
|
||||||
import static feign.Util.checkState;
|
import static feign.Util.checkState;
|
||||||
import static feign.Util.emptyToNull;
|
import static feign.Util.emptyToNull;
|
||||||
|
|
||||||
@@ -46,15 +46,13 @@ public class RequestHeaderParameterProcessor implements AnnotatedParameterProces
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processArgument(AnnotatedParameterContext context,
|
public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) {
|
||||||
Annotation annotation, Method method) {
|
|
||||||
int parameterIndex = context.getParameterIndex();
|
int parameterIndex = context.getParameterIndex();
|
||||||
Class<?> parameterType = method.getParameterTypes()[parameterIndex];
|
Class<?> parameterType = method.getParameterTypes()[parameterIndex];
|
||||||
MethodMetadata data = context.getMethodMetadata();
|
MethodMetadata data = context.getMethodMetadata();
|
||||||
|
|
||||||
if (Map.class.isAssignableFrom(parameterType)) {
|
if (Map.class.isAssignableFrom(parameterType)) {
|
||||||
checkState(data.headerMapIndex() == null,
|
checkState(data.headerMapIndex() == null, "Header map can only be present once.");
|
||||||
"Header map can only be present once.");
|
|
||||||
data.headerMapIndex(parameterIndex);
|
data.headerMapIndex(parameterIndex);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -65,10 +63,8 @@ public class RequestHeaderParameterProcessor implements AnnotatedParameterProces
|
|||||||
"RequestHeader.value() was empty on parameter %s", parameterIndex);
|
"RequestHeader.value() was empty on parameter %s", parameterIndex);
|
||||||
context.setParameterName(name);
|
context.setParameterName(name);
|
||||||
|
|
||||||
Collection<String> header = context.setTemplateParameter(name,
|
Collection<String> header = context.setTemplateParameter(name, data.template().headers().get(name));
|
||||||
data.template().headers().get(name));
|
|
||||||
data.template().header(name, header);
|
data.template().header(name, header);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-9
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -21,14 +21,14 @@ import java.lang.reflect.Method;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import feign.MethodMetadata;
|
|
||||||
|
|
||||||
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
import static feign.Util.checkState;
|
import static feign.Util.checkState;
|
||||||
import static feign.Util.emptyToNull;
|
import static feign.Util.emptyToNull;
|
||||||
|
|
||||||
|
import feign.MethodMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link RequestParam} parameter processor.
|
* {@link RequestParam} parameter processor.
|
||||||
*
|
*
|
||||||
@@ -46,15 +46,13 @@ public class RequestParamParameterProcessor implements AnnotatedParameterProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processArgument(AnnotatedParameterContext context,
|
public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) {
|
||||||
Annotation annotation, Method method) {
|
|
||||||
int parameterIndex = context.getParameterIndex();
|
int parameterIndex = context.getParameterIndex();
|
||||||
Class<?> parameterType = method.getParameterTypes()[parameterIndex];
|
Class<?> parameterType = method.getParameterTypes()[parameterIndex];
|
||||||
MethodMetadata data = context.getMethodMetadata();
|
MethodMetadata data = context.getMethodMetadata();
|
||||||
|
|
||||||
if (Map.class.isAssignableFrom(parameterType)) {
|
if (Map.class.isAssignableFrom(parameterType)) {
|
||||||
checkState(data.queryMapIndex() == null,
|
checkState(data.queryMapIndex() == null, "Query map can only be present once.");
|
||||||
"Query map can only be present once.");
|
|
||||||
data.queryMapIndex(parameterIndex);
|
data.queryMapIndex(parameterIndex);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -63,7 +61,8 @@ public class RequestParamParameterProcessor implements AnnotatedParameterProcess
|
|||||||
RequestParam requestParam = ANNOTATION.cast(annotation);
|
RequestParam requestParam = ANNOTATION.cast(annotation);
|
||||||
String name = requestParam.value();
|
String name = requestParam.value();
|
||||||
checkState(emptyToNull(name) != null,
|
checkState(emptyToNull(name) != null,
|
||||||
"RequestParam.value() was empty on parameter %s", parameterIndex);
|
"RequestParam.value() was empty on parameter %s",
|
||||||
|
parameterIndex);
|
||||||
context.setParameterName(name);
|
context.setParameterName(name);
|
||||||
|
|
||||||
Collection<String> query = context.setTemplateParameter(name,
|
Collection<String> query = context.setTemplateParameter(name,
|
||||||
@@ -71,5 +70,4 @@ public class RequestParamParameterProcessor implements AnnotatedParameterProcess
|
|||||||
data.template().query(name, query);
|
data.template().query(name, query);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -18,7 +18,6 @@ package org.springframework.cloud.openfeign.encoding;
|
|||||||
|
|
||||||
import feign.RequestInterceptor;
|
import feign.RequestInterceptor;
|
||||||
import feign.RequestTemplate;
|
import feign.RequestTemplate;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,6 +34,7 @@ public abstract class BaseRequestInterceptor implements RequestInterceptor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of {@link BaseRequestInterceptor}.
|
* Creates new instance of {@link BaseRequestInterceptor}.
|
||||||
|
*
|
||||||
* @param properties the encoding properties
|
* @param properties the encoding properties
|
||||||
*/
|
*/
|
||||||
protected BaseRequestInterceptor(FeignClientEncodingProperties properties) {
|
protected BaseRequestInterceptor(FeignClientEncodingProperties properties) {
|
||||||
@@ -44,12 +44,12 @@ public abstract class BaseRequestInterceptor implements RequestInterceptor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the header if it wasn't yet specified.
|
* Adds the header if it wasn't yet specified.
|
||||||
|
*
|
||||||
* @param requestTemplate the request
|
* @param requestTemplate the request
|
||||||
* @param name the header name
|
* @param name the header name
|
||||||
* @param values the header values
|
* @param values the header values
|
||||||
*/
|
*/
|
||||||
protected void addHeader(RequestTemplate requestTemplate, String name,
|
protected void addHeader(RequestTemplate requestTemplate, String name, String... values) {
|
||||||
String... values) {
|
|
||||||
|
|
||||||
if (!requestTemplate.headers().containsKey(name)) {
|
if (!requestTemplate.headers().containsKey(name)) {
|
||||||
requestTemplate.header(name, values);
|
requestTemplate.header(name, values);
|
||||||
@@ -57,7 +57,7 @@ public abstract class BaseRequestInterceptor implements RequestInterceptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected FeignClientEncodingProperties getProperties() {
|
protected FeignClientEncodingProperties getProperties() {
|
||||||
return this.properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-6
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -40,16 +40,14 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
@ConditionalOnClass(Feign.class)
|
@ConditionalOnClass(Feign.class)
|
||||||
@ConditionalOnBean(Client.class)
|
@ConditionalOnBean(Client.class)
|
||||||
@ConditionalOnProperty(value = "feign.compression.response.enabled", matchIfMissing = false)
|
@ConditionalOnProperty(value = "feign.compression.response.enabled", matchIfMissing = false)
|
||||||
// The OK HTTP client uses "transparent" compression.
|
//The OK HTTP client uses "transparent" compression.
|
||||||
// If the accept-encoding header is present it disable transparent compression
|
//If the accept-encoding header is present it disable transparent compression
|
||||||
@ConditionalOnMissingBean(type = "okhttp3.OkHttpClient")
|
@ConditionalOnMissingBean(type = "okhttp3.OkHttpClient")
|
||||||
@AutoConfigureAfter(FeignAutoConfiguration.class)
|
@AutoConfigureAfter(FeignAutoConfiguration.class)
|
||||||
public class FeignAcceptGzipEncodingAutoConfiguration {
|
public class FeignAcceptGzipEncodingAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public FeignAcceptGzipEncodingInterceptor feignAcceptGzipEncodingInterceptor(
|
public FeignAcceptGzipEncodingInterceptor feignAcceptGzipEncodingInterceptor(FeignClientEncodingProperties properties) {
|
||||||
FeignClientEncodingProperties properties) {
|
|
||||||
return new FeignAcceptGzipEncodingInterceptor(properties);
|
return new FeignAcceptGzipEncodingInterceptor(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-11
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,11 +19,10 @@ package org.springframework.cloud.openfeign.encoding;
|
|||||||
import feign.RequestTemplate;
|
import feign.RequestTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables the HTTP response payload compression by specifying the {@code Accept-Encoding}
|
* Enables the HTTP response payload compression by specifying the {@code Accept-Encoding} headers.
|
||||||
* headers. Although this does not yet mean that the requests will be compressed, it
|
* Although this does not yet mean that the requests will be compressed, it requires the remote server
|
||||||
* requires the remote server to understand the header and be configured to compress
|
* to understand the header and be configured to compress responses. Still no all responses might be compressed
|
||||||
* responses. Still no all responses might be compressed based on the media type matching
|
* based on the media type matching and other factors like the response content length.
|
||||||
* and other factors like the response content length.
|
|
||||||
*
|
*
|
||||||
* @author Jakub Narloch
|
* @author Jakub Narloch
|
||||||
*/
|
*/
|
||||||
@@ -31,10 +30,10 @@ public class FeignAcceptGzipEncodingInterceptor extends BaseRequestInterceptor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of {@link FeignAcceptGzipEncodingInterceptor}.
|
* Creates new instance of {@link FeignAcceptGzipEncodingInterceptor}.
|
||||||
|
*
|
||||||
* @param properties the encoding properties
|
* @param properties the encoding properties
|
||||||
*/
|
*/
|
||||||
protected FeignAcceptGzipEncodingInterceptor(
|
protected FeignAcceptGzipEncodingInterceptor(FeignClientEncodingProperties properties) {
|
||||||
FeignClientEncodingProperties properties) {
|
|
||||||
super(properties);
|
super(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,8 +43,7 @@ public class FeignAcceptGzipEncodingInterceptor extends BaseRequestInterceptor {
|
|||||||
@Override
|
@Override
|
||||||
public void apply(RequestTemplate template) {
|
public void apply(RequestTemplate template) {
|
||||||
|
|
||||||
addHeader(template, HttpEncoding.ACCEPT_ENCODING_HEADER,
|
addHeader(template, HttpEncoding.ACCEPT_ENCODING_HEADER, HttpEncoding.GZIP_ENCODING,
|
||||||
HttpEncoding.GZIP_ENCODING, HttpEncoding.DEFLATE_ENCODING);
|
HttpEncoding.DEFLATE_ENCODING);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-20
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,11 +16,11 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign.encoding;
|
package org.springframework.cloud.openfeign.encoding;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Feign encoding properties.
|
* The Feign encoding properties.
|
||||||
*
|
*
|
||||||
@@ -32,8 +32,7 @@ public class FeignClientEncodingProperties {
|
|||||||
/**
|
/**
|
||||||
* The list of supported mime types.
|
* The list of supported mime types.
|
||||||
*/
|
*/
|
||||||
private String[] mimeTypes = new String[] { "text/xml", "application/xml",
|
private String[] mimeTypes = new String[]{"text/xml", "application/xml", "application/json"};
|
||||||
"application/json" };
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The minimum threshold content size.
|
* The minimum threshold content size.
|
||||||
@@ -41,7 +40,7 @@ public class FeignClientEncodingProperties {
|
|||||||
private int minRequestSize = 2048;
|
private int minRequestSize = 2048;
|
||||||
|
|
||||||
public String[] getMimeTypes() {
|
public String[] getMimeTypes() {
|
||||||
return this.mimeTypes;
|
return mimeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMimeTypes(String[] mimeTypes) {
|
public void setMimeTypes(String[] mimeTypes) {
|
||||||
@@ -49,7 +48,7 @@ public class FeignClientEncodingProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getMinRequestSize() {
|
public int getMinRequestSize() {
|
||||||
return this.minRequestSize;
|
return minRequestSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMinRequestSize(int minRequestSize) {
|
public void setMinRequestSize(int minRequestSize) {
|
||||||
@@ -58,28 +57,24 @@ public class FeignClientEncodingProperties {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) return true;
|
||||||
return true;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FeignClientEncodingProperties that = (FeignClientEncodingProperties) o;
|
FeignClientEncodingProperties that = (FeignClientEncodingProperties) o;
|
||||||
return Arrays.equals(this.mimeTypes, that.mimeTypes)
|
return Arrays.equals(mimeTypes, that.mimeTypes) &&
|
||||||
&& Objects.equals(this.minRequestSize, that.minRequestSize);
|
Objects.equals(minRequestSize, that.minRequestSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(this.mimeTypes, this.minRequestSize);
|
return Objects.hash(mimeTypes, minRequestSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new StringBuilder("FeignClientEncodingProperties{").append("mimeTypes=")
|
return new StringBuilder("FeignClientEncodingProperties{")
|
||||||
.append(Arrays.toString(this.mimeTypes)).append(", ")
|
.append("mimeTypes=").append(Arrays.toString(mimeTypes)).append(", ")
|
||||||
.append("minRequestSize=").append(this.minRequestSize).append("}")
|
.append("minRequestSize=").append(minRequestSize)
|
||||||
.toString();
|
.append("}").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-6
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -39,17 +39,15 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
@EnableConfigurationProperties(FeignClientEncodingProperties.class)
|
@EnableConfigurationProperties(FeignClientEncodingProperties.class)
|
||||||
@ConditionalOnClass(Feign.class)
|
@ConditionalOnClass(Feign.class)
|
||||||
@ConditionalOnBean(Client.class)
|
@ConditionalOnBean(Client.class)
|
||||||
// The OK HTTP client uses "transparent" compression.
|
//The OK HTTP client uses "transparent" compression.
|
||||||
// If the content-encoding header is present it disable transparent compression
|
//If the content-encoding header is present it disable transparent compression
|
||||||
@ConditionalOnMissingBean(type = "okhttp3.OkHttpClient")
|
@ConditionalOnMissingBean(type = "okhttp3.OkHttpClient")
|
||||||
@ConditionalOnProperty(value = "feign.compression.request.enabled", matchIfMissing = false)
|
@ConditionalOnProperty(value = "feign.compression.request.enabled", matchIfMissing = false)
|
||||||
@AutoConfigureAfter(FeignAutoConfiguration.class)
|
@AutoConfigureAfter(FeignAutoConfiguration.class)
|
||||||
public class FeignContentGzipEncodingAutoConfiguration {
|
public class FeignContentGzipEncodingAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public FeignContentGzipEncodingInterceptor feignContentGzipEncodingInterceptor(
|
public FeignContentGzipEncodingInterceptor feignContentGzipEncodingInterceptor(FeignClientEncodingProperties properties) {
|
||||||
FeignClientEncodingProperties properties) {
|
|
||||||
return new FeignContentGzipEncodingInterceptor(properties);
|
return new FeignContentGzipEncodingInterceptor(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-14
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,14 +16,13 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign.encoding;
|
package org.springframework.cloud.openfeign.encoding;
|
||||||
|
|
||||||
|
import feign.RequestTemplate;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import feign.RequestTemplate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables the HTTP request payload compression by specifying the {@code Content-Encoding}
|
* Enables the HTTP request payload compression by specifying the {@code Content-Encoding} headers.
|
||||||
* headers.
|
|
||||||
*
|
*
|
||||||
* @author Jakub Narloch
|
* @author Jakub Narloch
|
||||||
*/
|
*/
|
||||||
@@ -31,10 +30,10 @@ public class FeignContentGzipEncodingInterceptor extends BaseRequestInterceptor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of {@link FeignContentGzipEncodingInterceptor}.
|
* Creates new instance of {@link FeignContentGzipEncodingInterceptor}.
|
||||||
|
*
|
||||||
* @param properties the encoding properties
|
* @param properties the encoding properties
|
||||||
*/
|
*/
|
||||||
protected FeignContentGzipEncodingInterceptor(
|
protected FeignContentGzipEncodingInterceptor(FeignClientEncodingProperties properties) {
|
||||||
FeignClientEncodingProperties properties) {
|
|
||||||
super(properties);
|
super(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,13 +44,14 @@ public class FeignContentGzipEncodingInterceptor extends BaseRequestInterceptor
|
|||||||
public void apply(RequestTemplate template) {
|
public void apply(RequestTemplate template) {
|
||||||
|
|
||||||
if (requiresCompression(template)) {
|
if (requiresCompression(template)) {
|
||||||
addHeader(template, HttpEncoding.CONTENT_ENCODING_HEADER,
|
addHeader(template, HttpEncoding.CONTENT_ENCODING_HEADER, HttpEncoding.GZIP_ENCODING,
|
||||||
HttpEncoding.GZIP_ENCODING, HttpEncoding.DEFLATE_ENCODING);
|
HttpEncoding.DEFLATE_ENCODING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the request requires GZIP compression.
|
* Returns whether the request requires GZIP compression.
|
||||||
|
*
|
||||||
* @param template the request template
|
* @param template the request template
|
||||||
* @return true if request requires compression, false otherwise
|
* @return true if request requires compression, false otherwise
|
||||||
*/
|
*/
|
||||||
@@ -64,6 +64,7 @@ public class FeignContentGzipEncodingInterceptor extends BaseRequestInterceptor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the request content length exceed configured minimum size.
|
* Returns whether the request content length exceed configured minimum size.
|
||||||
|
*
|
||||||
* @param contentLength the content length header value
|
* @param contentLength the content length header value
|
||||||
* @return true if length is grater than minimum size, false otherwise
|
* @return true if length is grater than minimum size, false otherwise
|
||||||
*/
|
*/
|
||||||
@@ -77,14 +78,14 @@ public class FeignContentGzipEncodingInterceptor extends BaseRequestInterceptor
|
|||||||
final String strLen = contentLength.iterator().next();
|
final String strLen = contentLength.iterator().next();
|
||||||
final long length = Long.parseLong(strLen);
|
final long length = Long.parseLong(strLen);
|
||||||
return length > getProperties().getMinRequestSize();
|
return length > getProperties().getMinRequestSize();
|
||||||
}
|
} catch (NumberFormatException ex) {
|
||||||
catch (NumberFormatException ex) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the content mime types matches the configures mime types.
|
* Returns whether the content mime types matches the configures mime types.
|
||||||
|
*
|
||||||
* @param contentTypes the content types
|
* @param contentTypes the content types
|
||||||
* @return true if any specified content type matches the request content types
|
* @return true if any specified content type matches the request content types
|
||||||
*/
|
*/
|
||||||
@@ -93,8 +94,7 @@ public class FeignContentGzipEncodingInterceptor extends BaseRequestInterceptor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getProperties().getMimeTypes() == null
|
if (getProperties().getMimeTypes() == null || getProperties().getMimeTypes().length == 0) {
|
||||||
|| getProperties().getMimeTypes().length == 0) {
|
|
||||||
// no specific mime types has been set - matching everything
|
// no specific mime types has been set - matching everything
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -107,5 +107,4 @@ public class FeignContentGzipEncodingInterceptor extends BaseRequestInterceptor
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -52,5 +52,4 @@ public interface HttpEncoding {
|
|||||||
* The Deflate encoding.
|
* The Deflate encoding.
|
||||||
*/
|
*/
|
||||||
String DEFLATE_ENCODING = "deflate";
|
String DEFLATE_ENCODING = "deflate";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-17
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -18,14 +18,14 @@ package org.springframework.cloud.openfeign.ribbon;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.netflix.client.config.IClientConfig;
|
|
||||||
import com.netflix.loadbalancer.ILoadBalancer;
|
|
||||||
|
|
||||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
|
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
|
||||||
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
|
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
|
||||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||||
|
|
||||||
|
import com.netflix.client.config.IClientConfig;
|
||||||
|
import com.netflix.loadbalancer.ILoadBalancer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for SpringLoadBalancer instances that caches the entries created.
|
* Factory for SpringLoadBalancer instances that caches the entries created.
|
||||||
*
|
*
|
||||||
@@ -36,9 +36,8 @@ import org.springframework.util.ConcurrentReferenceHashMap;
|
|||||||
*/
|
*/
|
||||||
public class CachingSpringLoadBalancerFactory {
|
public class CachingSpringLoadBalancerFactory {
|
||||||
|
|
||||||
protected final SpringClientFactory factory;
|
private final SpringClientFactory factory;
|
||||||
|
private LoadBalancedRetryFactory loadBalancedRetryFactory = null;
|
||||||
protected LoadBalancedRetryFactory loadBalancedRetryFactory = null;
|
|
||||||
|
|
||||||
private volatile Map<String, FeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>();
|
private volatile Map<String, FeignLoadBalancer> cache = new ConcurrentReferenceHashMap<>();
|
||||||
|
|
||||||
@@ -46,27 +45,23 @@ public class CachingSpringLoadBalancerFactory {
|
|||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachingSpringLoadBalancerFactory(SpringClientFactory factory,
|
public CachingSpringLoadBalancerFactory(SpringClientFactory factory, LoadBalancedRetryFactory loadBalancedRetryPolicyFactory) {
|
||||||
LoadBalancedRetryFactory loadBalancedRetryPolicyFactory) {
|
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.loadBalancedRetryFactory = loadBalancedRetryPolicyFactory;
|
this.loadBalancedRetryFactory = loadBalancedRetryPolicyFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FeignLoadBalancer create(String clientName) {
|
public FeignLoadBalancer create(String clientName) {
|
||||||
FeignLoadBalancer client = this.cache.get(clientName);
|
FeignLoadBalancer client = this.cache.get(clientName);
|
||||||
if (client != null) {
|
if(client != null) {
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
IClientConfig config = this.factory.getClientConfig(clientName);
|
IClientConfig config = this.factory.getClientConfig(clientName);
|
||||||
ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
|
ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
|
||||||
ServerIntrospector serverIntrospector = this.factory.getInstance(clientName,
|
ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class);
|
||||||
ServerIntrospector.class);
|
client = loadBalancedRetryFactory != null ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,
|
||||||
client = this.loadBalancedRetryFactory != null
|
loadBalancedRetryFactory) : new FeignLoadBalancer(lb, config, serverIntrospector);
|
||||||
? new RetryableFeignLoadBalancer(lb, config, serverIntrospector,
|
|
||||||
this.loadBalancedRetryFactory)
|
|
||||||
: new FeignLoadBalancer(lb, config, serverIntrospector);
|
|
||||||
this.cache.put(clientName, client);
|
this.cache.put(clientName, client);
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+5
-7
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,12 +12,12 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign.ribbon;
|
package org.springframework.cloud.openfeign.ribbon;
|
||||||
|
|
||||||
import feign.Client;
|
import feign.Client;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -28,13 +28,11 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
class DefaultFeignLoadBalancedConfiguration {
|
class DefaultFeignLoadBalancedConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
|
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
|
||||||
SpringClientFactory clientFactory) {
|
SpringClientFactory clientFactory) {
|
||||||
return new LoadBalancerFeignClient(new Client.Default(null, null), cachingFactory,
|
return new LoadBalancerFeignClient(new Client.Default(null, null),
|
||||||
clientFactory);
|
cachingFactory, clientFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-40
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign.ribbon;
|
package org.springframework.cloud.openfeign.ribbon;
|
||||||
|
|
||||||
|
import feign.Client;
|
||||||
|
import feign.Request;
|
||||||
|
import feign.Response;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -25,6 +29,11 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.cloud.netflix.ribbon.RibbonProperties;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.HttpRequest;
|
||||||
import com.netflix.client.AbstractLoadBalancerAwareClient;
|
import com.netflix.client.AbstractLoadBalancerAwareClient;
|
||||||
import com.netflix.client.ClientException;
|
import com.netflix.client.ClientException;
|
||||||
import com.netflix.client.ClientRequest;
|
import com.netflix.client.ClientRequest;
|
||||||
@@ -34,15 +43,6 @@ import com.netflix.client.RetryHandler;
|
|||||||
import com.netflix.client.config.IClientConfig;
|
import com.netflix.client.config.IClientConfig;
|
||||||
import com.netflix.loadbalancer.ILoadBalancer;
|
import com.netflix.loadbalancer.ILoadBalancer;
|
||||||
import com.netflix.loadbalancer.Server;
|
import com.netflix.loadbalancer.Server;
|
||||||
import feign.Client;
|
|
||||||
import feign.Request;
|
|
||||||
import feign.Response;
|
|
||||||
|
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonProperties;
|
|
||||||
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.HttpRequest;
|
|
||||||
|
|
||||||
import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToSecureConnectionIfNeeded;
|
import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToSecureConnectionIfNeeded;
|
||||||
|
|
||||||
@@ -51,23 +51,18 @@ import static org.springframework.cloud.netflix.ribbon.RibbonUtils.updateToSecur
|
|||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
* @author Ryan Baxter
|
* @author Ryan Baxter
|
||||||
* @author Tim Ysewyn
|
* @author Tim Ysewyn
|
||||||
* @author Olga Maciaszek-Sharma
|
|
||||||
*/
|
*/
|
||||||
public class FeignLoadBalancer extends
|
public class FeignLoadBalancer extends
|
||||||
AbstractLoadBalancerAwareClient<FeignLoadBalancer.RibbonRequest, FeignLoadBalancer.RibbonResponse> {
|
AbstractLoadBalancerAwareClient<FeignLoadBalancer.RibbonRequest, FeignLoadBalancer.RibbonResponse> {
|
||||||
|
|
||||||
private final RibbonProperties ribbon;
|
private final RibbonProperties ribbon;
|
||||||
|
|
||||||
protected int connectTimeout;
|
protected int connectTimeout;
|
||||||
|
|
||||||
protected int readTimeout;
|
protected int readTimeout;
|
||||||
|
|
||||||
protected IClientConfig clientConfig;
|
protected IClientConfig clientConfig;
|
||||||
|
|
||||||
protected ServerIntrospector serverIntrospector;
|
protected ServerIntrospector serverIntrospector;
|
||||||
|
|
||||||
public FeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig,
|
public FeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig,
|
||||||
ServerIntrospector serverIntrospector) {
|
ServerIntrospector serverIntrospector) {
|
||||||
super(lb, clientConfig);
|
super(lb, clientConfig);
|
||||||
this.setRetryHandler(RetryHandler.DEFAULT);
|
this.setRetryHandler(RetryHandler.DEFAULT);
|
||||||
this.clientConfig = clientConfig;
|
this.clientConfig = clientConfig;
|
||||||
@@ -84,7 +79,8 @@ public class FeignLoadBalancer extends
|
|||||||
Request.Options options;
|
Request.Options options;
|
||||||
if (configOverride != null) {
|
if (configOverride != null) {
|
||||||
RibbonProperties override = RibbonProperties.from(configOverride);
|
RibbonProperties override = RibbonProperties.from(configOverride);
|
||||||
options = new Request.Options(override.connectTimeout(this.connectTimeout),
|
options = new Request.Options(
|
||||||
|
override.connectTimeout(this.connectTimeout),
|
||||||
override.readTimeout(this.readTimeout));
|
override.readTimeout(this.readTimeout));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -101,7 +97,7 @@ public class FeignLoadBalancer extends
|
|||||||
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
|
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
|
||||||
requestConfig);
|
requestConfig);
|
||||||
}
|
}
|
||||||
if (!request.toRequest().httpMethod().name().equals("GET")) {
|
if (!request.toRequest().method().equals("GET")) {
|
||||||
return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(),
|
return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(),
|
||||||
requestConfig);
|
requestConfig);
|
||||||
}
|
}
|
||||||
@@ -113,18 +109,16 @@ public class FeignLoadBalancer extends
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI reconstructURIWithServer(Server server, URI original) {
|
public URI reconstructURIWithServer(Server server, URI original) {
|
||||||
URI uri = updateToSecureConnectionIfNeeded(original, this.clientConfig,
|
URI uri = updateToSecureConnectionIfNeeded(original, this.clientConfig, this.serverIntrospector, server);
|
||||||
this.serverIntrospector, server);
|
|
||||||
return super.reconstructURIWithServer(server, uri);
|
return super.reconstructURIWithServer(server, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class RibbonRequest extends ClientRequest implements Cloneable {
|
protected static class RibbonRequest extends ClientRequest implements Cloneable {
|
||||||
|
|
||||||
private final Request request;
|
private final Request request;
|
||||||
|
|
||||||
private final Client client;
|
private final Client client;
|
||||||
|
|
||||||
protected RibbonRequest(Client client, Request request, URI uri) {
|
RibbonRequest(Client client, Request request, URI uri) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
setUri(uri);
|
setUri(uri);
|
||||||
this.request = toRequest(request);
|
this.request = toRequest(request);
|
||||||
@@ -133,8 +127,7 @@ public class FeignLoadBalancer extends
|
|||||||
private Request toRequest(Request request) {
|
private Request toRequest(Request request) {
|
||||||
Map<String, Collection<String>> headers = new LinkedHashMap<>(
|
Map<String, Collection<String>> headers = new LinkedHashMap<>(
|
||||||
request.headers());
|
request.headers());
|
||||||
return Request.create(request.httpMethod(), getUri().toASCIIString(), headers,
|
return Request.create(request.method(),getUri().toASCIIString(),headers,request.body(),request.charset());
|
||||||
request.requestBody());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Request toRequest() {
|
Request toRequest() {
|
||||||
@@ -149,8 +142,7 @@ public class FeignLoadBalancer extends
|
|||||||
return new HttpRequest() {
|
return new HttpRequest() {
|
||||||
@Override
|
@Override
|
||||||
public HttpMethod getMethod() {
|
public HttpMethod getMethod() {
|
||||||
return HttpMethod
|
return HttpMethod.resolve(RibbonRequest.this.toRequest().method());
|
||||||
.resolve(RibbonRequest.this.toRequest().httpMethod().name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -166,9 +158,8 @@ public class FeignLoadBalancer extends
|
|||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
public HttpHeaders getHeaders() {
|
||||||
Map<String, List<String>> headers = new HashMap<>();
|
Map<String, List<String>> headers = new HashMap<>();
|
||||||
Map<String, Collection<String>> feignHeaders = RibbonRequest.this
|
Map<String, Collection<String>> feignHeaders = RibbonRequest.this.toRequest().headers();
|
||||||
.toRequest().headers();
|
for(String key : feignHeaders.keySet()) {
|
||||||
for (String key : feignHeaders.keySet()) {
|
|
||||||
headers.put(key, new ArrayList<String>(feignHeaders.get(key)));
|
headers.put(key, new ArrayList<String>(feignHeaders.get(key)));
|
||||||
}
|
}
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
@@ -179,28 +170,19 @@ public class FeignLoadBalancer extends
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request getRequest() {
|
|
||||||
return this.request;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Client getClient() {
|
|
||||||
return this.client;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object clone() {
|
public Object clone() {
|
||||||
return new RibbonRequest(this.client, this.request, getUri());
|
return new RibbonRequest(this.client, this.request, getUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class RibbonResponse implements IResponse {
|
protected static class RibbonResponse implements IResponse {
|
||||||
|
|
||||||
private final URI uri;
|
private final URI uri;
|
||||||
|
|
||||||
private final Response response;
|
private final Response response;
|
||||||
|
|
||||||
protected RibbonResponse(URI uri, Response response) {
|
RibbonResponse(URI uri, Response response) {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.response = response;
|
this.response = response;
|
||||||
}
|
}
|
||||||
@@ -243,4 +225,4 @@ public class FeignLoadBalancer extends
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+36
-46
@@ -1,17 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* * Copyright 2013-2016 the original author or authors.
|
||||||
* you may not use this file except in compliance with the License.
|
* *
|
||||||
* You may obtain a copy of the License at
|
* * 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.
|
||||||
*
|
*
|
||||||
* 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.ribbon;
|
package org.springframework.cloud.openfeign.ribbon;
|
||||||
@@ -32,13 +34,9 @@ import org.springframework.retry.RetryContext;
|
|||||||
* @author Ryan Baxter
|
* @author Ryan Baxter
|
||||||
*/
|
*/
|
||||||
public class FeignRetryPolicy extends InterceptorRetryPolicy {
|
public class FeignRetryPolicy extends InterceptorRetryPolicy {
|
||||||
|
|
||||||
private HttpRequest request;
|
private HttpRequest request;
|
||||||
|
|
||||||
private String serviceId;
|
private String serviceId;
|
||||||
|
public FeignRetryPolicy(HttpRequest request, LoadBalancedRetryPolicy policy, ServiceInstanceChooser serviceInstanceChooser, String serviceName) {
|
||||||
public FeignRetryPolicy(HttpRequest request, LoadBalancedRetryPolicy policy,
|
|
||||||
ServiceInstanceChooser serviceInstanceChooser, String serviceName) {
|
|
||||||
super(request, policy, serviceInstanceChooser, serviceName);
|
super(request, policy, serviceInstanceChooser, serviceName);
|
||||||
this.request = request;
|
this.request = request;
|
||||||
this.serviceId = serviceName;
|
this.serviceId = serviceName;
|
||||||
@@ -47,18 +45,17 @@ public class FeignRetryPolicy extends InterceptorRetryPolicy {
|
|||||||
@Override
|
@Override
|
||||||
public boolean canRetry(RetryContext context) {
|
public boolean canRetry(RetryContext context) {
|
||||||
/*
|
/*
|
||||||
* In InterceptorRetryPolicy.canRetry we ask the LoadBalancer to choose a server
|
* In InterceptorRetryPolicy.canRetry we ask the LoadBalancer to choose a server if one is not
|
||||||
* if one is not set in the retry context and then return true. RetryTemplat calls
|
* set in the retry context and then return true. RetryTemplat calls the canRetry method of
|
||||||
* the canRetry method of the policy even on its first execution. So the fact that
|
* the policy even on its first execution. So the fact that we didnt have a service instance set
|
||||||
* we didnt have a service instance set in the RetryContext signaled that it was
|
* in the RetryContext signaled that it was the first execution and we should return true.
|
||||||
* the first execution and we should return true.
|
|
||||||
*
|
*
|
||||||
* In the Feign scenario, Feign as actually already queried the load balancer for
|
* In the Feign scenario, Feign as actually already queried the load balancer for a service instance
|
||||||
* a service instance and we set that service instance in the context when we call
|
* and we set that service instance in the context when we call the open method of the policy. So in
|
||||||
* the open method of the policy. So in the Feign case we just return true if the
|
* the Feign case we just return true if the retry count is 0 indicating we haven't yet made a failed
|
||||||
* retry count is 0 indicating we haven't yet made a failed request.
|
* request.
|
||||||
*/
|
*/
|
||||||
if (context.getRetryCount() == 0) {
|
if(context.getRetryCount() == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.canRetry(context);
|
return super.canRetry(context);
|
||||||
@@ -67,25 +64,20 @@ public class FeignRetryPolicy extends InterceptorRetryPolicy {
|
|||||||
@Override
|
@Override
|
||||||
public RetryContext open(RetryContext parent) {
|
public RetryContext open(RetryContext parent) {
|
||||||
/*
|
/*
|
||||||
* With Feign (unlike Ribbon) the request already has the URI for the service
|
* With Feign (unlike Ribbon) the request already has the URI for the service instance
|
||||||
* instance we are going to make the request to, so extract that information and
|
* we are going to make the request to, so extract that information and set the service
|
||||||
* set the service instance in the context. In the Ribbon scenario the URI in the
|
* instance in the context. In the Ribbon scenario the URI in the request object still has
|
||||||
* request object still has the service id so we choose and set the service
|
* the service id so we choose and set the service instance later on.
|
||||||
* instance later on.
|
|
||||||
*/
|
*/
|
||||||
LoadBalancedRetryContext context = new LoadBalancedRetryContext(parent,
|
LoadBalancedRetryContext context = new LoadBalancedRetryContext(parent, this.request);
|
||||||
this.request);
|
context.setServiceInstance(new FeignRetryPolicyServiceInstance(serviceId, request));
|
||||||
context.setServiceInstance(
|
|
||||||
new FeignRetryPolicyServiceInstance(this.serviceId, this.request));
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FeignRetryPolicyServiceInstance implements ServiceInstance {
|
class FeignRetryPolicyServiceInstance implements ServiceInstance {
|
||||||
|
|
||||||
private String serviceId;
|
private String serviceId;
|
||||||
|
|
||||||
private HttpRequest request;
|
private HttpRequest request;
|
||||||
|
|
||||||
private Map<String, String> metadata;
|
private Map<String, String> metadata;
|
||||||
|
|
||||||
FeignRetryPolicyServiceInstance(String serviceId, HttpRequest request) {
|
FeignRetryPolicyServiceInstance(String serviceId, HttpRequest request) {
|
||||||
@@ -96,34 +88,32 @@ public class FeignRetryPolicy extends InterceptorRetryPolicy {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getServiceId() {
|
public String getServiceId() {
|
||||||
return this.serviceId;
|
return serviceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHost() {
|
public String getHost() {
|
||||||
return this.request.getURI().getHost();
|
return request.getURI().getHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPort() {
|
public int getPort() {
|
||||||
return this.request.getURI().getPort();
|
return request.getURI().getPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSecure() {
|
public boolean isSecure() {
|
||||||
return "https".equals(this.request.getURI().getScheme());
|
return "https".equals(request.getURI().getScheme());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URI getUri() {
|
public URI getUri() {
|
||||||
return this.request.getURI();
|
return request.getURI();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getMetadata() {
|
public Map<String, String> getMetadata() {
|
||||||
return this.metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
+11
-11
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,24 +16,25 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign.ribbon;
|
package org.springframework.cloud.openfeign.ribbon;
|
||||||
|
|
||||||
import com.netflix.loadbalancer.ILoadBalancer;
|
|
||||||
import feign.Feign;
|
|
||||||
import feign.Request;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
|
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
|
||||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
|
||||||
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
|
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
|
||||||
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
|
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
|
|
||||||
|
import com.netflix.loadbalancer.ILoadBalancer;
|
||||||
|
|
||||||
|
import feign.Feign;
|
||||||
|
import feign.Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Autoconfiguration to be activated if Feign is in use and needs to be use Ribbon as a
|
* Autoconfiguration to be activated if Feign is in use and needs to be use Ribbon as a
|
||||||
* load balancer.
|
* load balancer.
|
||||||
@@ -44,9 +45,8 @@ import org.springframework.context.annotation.Primary;
|
|||||||
@Configuration
|
@Configuration
|
||||||
@AutoConfigureBefore(FeignAutoConfiguration.class)
|
@AutoConfigureBefore(FeignAutoConfiguration.class)
|
||||||
@EnableConfigurationProperties({ FeignHttpClientProperties.class })
|
@EnableConfigurationProperties({ FeignHttpClientProperties.class })
|
||||||
// Order is important here, last should be the default, first should be optional
|
//Order is important here, last should be the default, first should be optional
|
||||||
// see
|
// see https://github.com/spring-cloud/spring-cloud-netflix/issues/2086#issuecomment-316281653
|
||||||
// https://github.com/spring-cloud/spring-cloud-netflix/issues/2086#issuecomment-316281653
|
|
||||||
@Import({ HttpClientFeignLoadBalancedConfiguration.class,
|
@Import({ HttpClientFeignLoadBalancedConfiguration.class,
|
||||||
OkHttpFeignLoadBalancedConfiguration.class,
|
OkHttpFeignLoadBalancedConfiguration.class,
|
||||||
DefaultFeignLoadBalancedConfiguration.class })
|
DefaultFeignLoadBalancedConfiguration.class })
|
||||||
@@ -66,7 +66,8 @@ public class FeignRibbonClientAutoConfiguration {
|
|||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
|
@ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
|
||||||
public CachingSpringLoadBalancerFactory retryabeCachingLBClientFactory(
|
public CachingSpringLoadBalancerFactory retryabeCachingLBClientFactory(
|
||||||
SpringClientFactory factory, LoadBalancedRetryFactory retryFactory) {
|
SpringClientFactory factory,
|
||||||
|
LoadBalancedRetryFactory retryFactory) {
|
||||||
return new CachingSpringLoadBalancerFactory(factory, retryFactory);
|
return new CachingSpringLoadBalancerFactory(factory, retryFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,5 +76,4 @@ public class FeignRibbonClientAutoConfiguration {
|
|||||||
public Request.Options feignRequestOptions() {
|
public Request.Options feignRequestOptions() {
|
||||||
return LoadBalancerFeignClient.DEFAULT_OPTIONS;
|
return LoadBalancerFeignClient.DEFAULT_OPTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-43
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,32 +12,31 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign.ribbon;
|
package org.springframework.cloud.openfeign.ribbon;
|
||||||
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
import javax.annotation.PreDestroy;
|
|
||||||
|
|
||||||
import feign.Client;
|
import feign.Client;
|
||||||
import feign.httpclient.ApacheHttpClient;
|
import feign.httpclient.ApacheHttpClient;
|
||||||
|
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.HttpClient;
|
||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.apache.http.config.RegistryBuilder;
|
import org.apache.http.config.RegistryBuilder;
|
||||||
import org.apache.http.conn.HttpClientConnectionManager;
|
import org.apache.http.conn.HttpClientConnectionManager;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
|
||||||
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
|
||||||
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
|
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@@ -49,18 +48,9 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
|
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
|
||||||
class HttpClientFeignLoadBalancedConfiguration {
|
class HttpClientFeignLoadBalancedConfiguration {
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean(Client.class)
|
|
||||||
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
|
|
||||||
SpringClientFactory clientFactory, HttpClient httpClient) {
|
|
||||||
ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
|
|
||||||
return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnMissingBean(CloseableHttpClient.class)
|
@ConditionalOnMissingBean(CloseableHttpClient.class)
|
||||||
protected static class HttpClientFeignConfiguration {
|
protected static class HttpClientFeignConfiguration {
|
||||||
|
|
||||||
private final Timer connectionManagerTimer = new Timer(
|
private final Timer connectionManagerTimer = new Timer(
|
||||||
"FeignApacheHttpClientConfiguration.connectionManagerTimer", true);
|
"FeignApacheHttpClientConfiguration.connectionManagerTimer", true);
|
||||||
|
|
||||||
@@ -75,12 +65,10 @@ class HttpClientFeignLoadBalancedConfiguration {
|
|||||||
ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
|
||||||
FeignHttpClientProperties httpClientProperties) {
|
FeignHttpClientProperties httpClientProperties) {
|
||||||
final HttpClientConnectionManager connectionManager = connectionManagerFactory
|
final HttpClientConnectionManager connectionManager = connectionManagerFactory
|
||||||
.newConnectionManager(httpClientProperties.isDisableSslValidation(),
|
.newConnectionManager(httpClientProperties.isDisableSslValidation(), httpClientProperties.getMaxConnections(),
|
||||||
httpClientProperties.getMaxConnections(),
|
|
||||||
httpClientProperties.getMaxConnectionsPerRoute(),
|
httpClientProperties.getMaxConnectionsPerRoute(),
|
||||||
httpClientProperties.getTimeToLive(),
|
httpClientProperties.getTimeToLive(),
|
||||||
httpClientProperties.getTimeToLiveUnit(),
|
httpClientProperties.getTimeToLiveUnit(), registryBuilder);
|
||||||
this.registryBuilder);
|
|
||||||
this.connectionManagerTimer.schedule(new TimerTask() {
|
this.connectionManagerTimer.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -92,47 +80,49 @@ class HttpClientFeignLoadBalancedConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "feign.compression.response.enabled", havingValue = "true")
|
@ConditionalOnProperty(value = "feign.compression.response.enabled", havingValue = "true")
|
||||||
public CloseableHttpClient customHttpClient(
|
public CloseableHttpClient customHttpClient(HttpClientConnectionManager httpClientConnectionManager,
|
||||||
HttpClientConnectionManager httpClientConnectionManager,
|
FeignHttpClientProperties httpClientProperties) {
|
||||||
FeignHttpClientProperties httpClientProperties) {
|
HttpClientBuilder builder = HttpClientBuilder.create().disableCookieManagement().useSystemProperties();
|
||||||
HttpClientBuilder builder = HttpClientBuilder.create()
|
this.httpClient = createClient(builder, httpClientConnectionManager, httpClientProperties);
|
||||||
.disableCookieManagement().useSystemProperties();
|
|
||||||
this.httpClient = createClient(builder, httpClientConnectionManager,
|
|
||||||
httpClientProperties);
|
|
||||||
return this.httpClient;
|
return this.httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "feign.compression.response.enabled", havingValue = "false", matchIfMissing = true)
|
@ConditionalOnProperty(value = "feign.compression.response.enabled", havingValue = "false", matchIfMissing = true)
|
||||||
public CloseableHttpClient httpClient(ApacheHttpClientFactory httpClientFactory,
|
public CloseableHttpClient httpClient(ApacheHttpClientFactory httpClientFactory, HttpClientConnectionManager httpClientConnectionManager,
|
||||||
HttpClientConnectionManager httpClientConnectionManager,
|
FeignHttpClientProperties httpClientProperties) {
|
||||||
FeignHttpClientProperties httpClientProperties) {
|
this.httpClient = createClient(httpClientFactory.createBuilder(), httpClientConnectionManager, httpClientProperties);
|
||||||
this.httpClient = createClient(httpClientFactory.createBuilder(),
|
|
||||||
httpClientConnectionManager, httpClientProperties);
|
|
||||||
return this.httpClient;
|
return this.httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CloseableHttpClient createClient(HttpClientBuilder builder,
|
private CloseableHttpClient createClient(HttpClientBuilder builder, HttpClientConnectionManager httpClientConnectionManager,
|
||||||
HttpClientConnectionManager httpClientConnectionManager,
|
FeignHttpClientProperties httpClientProperties) {
|
||||||
FeignHttpClientProperties httpClientProperties) {
|
|
||||||
RequestConfig defaultRequestConfig = RequestConfig.custom()
|
RequestConfig defaultRequestConfig = RequestConfig.custom()
|
||||||
.setConnectTimeout(httpClientProperties.getConnectionTimeout())
|
.setConnectTimeout(httpClientProperties.getConnectionTimeout())
|
||||||
.setRedirectsEnabled(httpClientProperties.isFollowRedirects())
|
.setRedirectsEnabled(httpClientProperties.isFollowRedirects())
|
||||||
.build();
|
.build();
|
||||||
CloseableHttpClient httpClient = builder
|
CloseableHttpClient httpClient = builder.setDefaultRequestConfig(defaultRequestConfig).
|
||||||
.setDefaultRequestConfig(defaultRequestConfig)
|
setConnectionManager(httpClientConnectionManager).build();
|
||||||
.setConnectionManager(httpClientConnectionManager).build();
|
|
||||||
return httpClient;
|
return httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreDestroy
|
@PreDestroy
|
||||||
public void destroy() throws Exception {
|
public void destroy() throws Exception {
|
||||||
this.connectionManagerTimer.cancel();
|
connectionManagerTimer.cancel();
|
||||||
if (this.httpClient != null) {
|
if(httpClient != null) {
|
||||||
this.httpClient.close();
|
httpClient.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(Client.class)
|
||||||
|
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
|
||||||
|
SpringClientFactory clientFactory, HttpClient httpClient) {
|
||||||
|
ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
|
||||||
|
return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-31
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,16 +19,17 @@ package org.springframework.cloud.openfeign.ribbon;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||||
|
|
||||||
import com.netflix.client.ClientException;
|
import com.netflix.client.ClientException;
|
||||||
import com.netflix.client.config.CommonClientConfigKey;
|
import com.netflix.client.config.CommonClientConfigKey;
|
||||||
import com.netflix.client.config.DefaultClientConfigImpl;
|
import com.netflix.client.config.DefaultClientConfigImpl;
|
||||||
import com.netflix.client.config.IClientConfig;
|
import com.netflix.client.config.IClientConfig;
|
||||||
|
|
||||||
import feign.Client;
|
import feign.Client;
|
||||||
import feign.Request;
|
import feign.Request;
|
||||||
import feign.Response;
|
import feign.Response;
|
||||||
|
|
||||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*
|
*
|
||||||
@@ -38,37 +39,17 @@ public class LoadBalancerFeignClient implements Client {
|
|||||||
static final Request.Options DEFAULT_OPTIONS = new Request.Options();
|
static final Request.Options DEFAULT_OPTIONS = new Request.Options();
|
||||||
|
|
||||||
private final Client delegate;
|
private final Client delegate;
|
||||||
|
|
||||||
private CachingSpringLoadBalancerFactory lbClientFactory;
|
private CachingSpringLoadBalancerFactory lbClientFactory;
|
||||||
|
|
||||||
private SpringClientFactory clientFactory;
|
private SpringClientFactory clientFactory;
|
||||||
|
|
||||||
public LoadBalancerFeignClient(Client delegate,
|
public LoadBalancerFeignClient(Client delegate,
|
||||||
CachingSpringLoadBalancerFactory lbClientFactory,
|
CachingSpringLoadBalancerFactory lbClientFactory,
|
||||||
SpringClientFactory clientFactory) {
|
SpringClientFactory clientFactory) {
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
this.lbClientFactory = lbClientFactory;
|
this.lbClientFactory = lbClientFactory;
|
||||||
this.clientFactory = clientFactory;
|
this.clientFactory = clientFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
static URI cleanUrl(String originalUrl, String host) {
|
|
||||||
String newUrl = originalUrl;
|
|
||||||
if (originalUrl.startsWith("https://")) {
|
|
||||||
newUrl = originalUrl.substring(0, 8)
|
|
||||||
+ originalUrl.substring(8 + host.length());
|
|
||||||
}
|
|
||||||
else if (originalUrl.startsWith("http")) {
|
|
||||||
newUrl = originalUrl.substring(0, 7)
|
|
||||||
+ originalUrl.substring(7 + host.length());
|
|
||||||
}
|
|
||||||
StringBuffer buffer = new StringBuffer(newUrl);
|
|
||||||
if ((newUrl.startsWith("https://") && newUrl.length() == 8)
|
|
||||||
|| (newUrl.startsWith("http://") && newUrl.length() == 7)) {
|
|
||||||
buffer.append("/");
|
|
||||||
}
|
|
||||||
return URI.create(buffer.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response execute(Request request, Request.Options options) throws IOException {
|
public Response execute(Request request, Request.Options options) throws IOException {
|
||||||
try {
|
try {
|
||||||
@@ -79,8 +60,8 @@ public class LoadBalancerFeignClient implements Client {
|
|||||||
this.delegate, request, uriWithoutHost);
|
this.delegate, request, uriWithoutHost);
|
||||||
|
|
||||||
IClientConfig requestConfig = getClientConfig(options, clientName);
|
IClientConfig requestConfig = getClientConfig(options, clientName);
|
||||||
return lbClient(clientName)
|
return lbClient(clientName).executeWithLoadBalancer(ribbonRequest,
|
||||||
.executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse();
|
requestConfig).toResponse();
|
||||||
}
|
}
|
||||||
catch (ClientException e) {
|
catch (ClientException e) {
|
||||||
IOException io = findIOException(e);
|
IOException io = findIOException(e);
|
||||||
@@ -95,8 +76,7 @@ public class LoadBalancerFeignClient implements Client {
|
|||||||
IClientConfig requestConfig;
|
IClientConfig requestConfig;
|
||||||
if (options == DEFAULT_OPTIONS) {
|
if (options == DEFAULT_OPTIONS) {
|
||||||
requestConfig = this.clientFactory.getClientConfig(clientName);
|
requestConfig = this.clientFactory.getClientConfig(clientName);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
requestConfig = new FeignOptionsClientConfig(options);
|
requestConfig = new FeignOptionsClientConfig(options);
|
||||||
}
|
}
|
||||||
return requestConfig;
|
return requestConfig;
|
||||||
@@ -116,13 +96,28 @@ public class LoadBalancerFeignClient implements Client {
|
|||||||
return this.delegate;
|
return this.delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static URI cleanUrl(String originalUrl, String host) {
|
||||||
|
String newUrl = originalUrl;
|
||||||
|
if(originalUrl.startsWith("https://")) {
|
||||||
|
newUrl = originalUrl.substring(0, 8) + originalUrl.substring(8 + host.length());
|
||||||
|
} else if(originalUrl.startsWith("http")) {
|
||||||
|
newUrl = originalUrl.substring(0, 7) + originalUrl.substring(7 + host.length());
|
||||||
|
}
|
||||||
|
StringBuffer buffer = new StringBuffer(newUrl);
|
||||||
|
if((newUrl.startsWith("https://") && newUrl.length() == 8) ||
|
||||||
|
(newUrl.startsWith("http://") && newUrl.length() == 7)) {
|
||||||
|
buffer.append("/");
|
||||||
|
}
|
||||||
|
return URI.create(buffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
private FeignLoadBalancer lbClient(String clientName) {
|
private FeignLoadBalancer lbClient(String clientName) {
|
||||||
return this.lbClientFactory.create(clientName);
|
return this.lbClientFactory.create(clientName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class FeignOptionsClientConfig extends DefaultClientConfigImpl {
|
static class FeignOptionsClientConfig extends DefaultClientConfigImpl {
|
||||||
|
|
||||||
FeignOptionsClientConfig(Request.Options options) {
|
public FeignOptionsClientConfig(Request.Options options) {
|
||||||
setProperty(CommonClientConfigKey.ConnectTimeout,
|
setProperty(CommonClientConfigKey.ConnectTimeout,
|
||||||
options.connectTimeoutMillis());
|
options.connectTimeoutMillis());
|
||||||
setProperty(CommonClientConfigKey.ReadTimeout, options.readTimeoutMillis());
|
setProperty(CommonClientConfigKey.ReadTimeout, options.readTimeoutMillis());
|
||||||
@@ -139,5 +134,4 @@ public class LoadBalancerFeignClient implements Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-30
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,25 +12,24 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign.ribbon;
|
package org.springframework.cloud.openfeign.ribbon;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.annotation.PreDestroy;
|
|
||||||
|
|
||||||
import feign.Client;
|
import feign.Client;
|
||||||
import feign.okhttp.OkHttpClient;
|
import feign.okhttp.OkHttpClient;
|
||||||
import okhttp3.ConnectionPool;
|
import okhttp3.ConnectionPool;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory;
|
import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory;
|
||||||
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
|
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
|
||||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
|
||||||
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
|
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@@ -39,28 +38,18 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass(OkHttpClient.class)
|
@ConditionalOnClass(OkHttpClient.class)
|
||||||
@ConditionalOnProperty("feign.okhttp.enabled")
|
@ConditionalOnProperty(value = "feign.okhttp.enabled")
|
||||||
class OkHttpFeignLoadBalancedConfiguration {
|
class OkHttpFeignLoadBalancedConfiguration {
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean(Client.class)
|
|
||||||
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
|
|
||||||
SpringClientFactory clientFactory, okhttp3.OkHttpClient okHttpClient) {
|
|
||||||
OkHttpClient delegate = new OkHttpClient(okHttpClient);
|
|
||||||
return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnMissingBean(okhttp3.OkHttpClient.class)
|
@ConditionalOnMissingBean(okhttp3.OkHttpClient.class)
|
||||||
protected static class OkHttpFeignConfiguration {
|
protected static class OkHttpFeignConfiguration {
|
||||||
|
|
||||||
private okhttp3.OkHttpClient okHttpClient;
|
private okhttp3.OkHttpClient okHttpClient;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(ConnectionPool.class)
|
@ConditionalOnMissingBean(ConnectionPool.class)
|
||||||
public ConnectionPool httpClientConnectionPool(
|
public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties,
|
||||||
FeignHttpClientProperties httpClientProperties,
|
OkHttpClientConnectionPoolFactory connectionPoolFactory) {
|
||||||
OkHttpClientConnectionPoolFactory connectionPoolFactory) {
|
|
||||||
Integer maxTotalConnections = httpClientProperties.getMaxConnections();
|
Integer maxTotalConnections = httpClientProperties.getMaxConnections();
|
||||||
Long timeToLive = httpClientProperties.getTimeToLive();
|
Long timeToLive = httpClientProperties.getTimeToLive();
|
||||||
TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
|
TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
|
||||||
@@ -69,26 +58,30 @@ class OkHttpFeignLoadBalancedConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public okhttp3.OkHttpClient client(OkHttpClientFactory httpClientFactory,
|
public okhttp3.OkHttpClient client(OkHttpClientFactory httpClientFactory,
|
||||||
ConnectionPool connectionPool,
|
ConnectionPool connectionPool, FeignHttpClientProperties httpClientProperties) {
|
||||||
FeignHttpClientProperties httpClientProperties) {
|
|
||||||
Boolean followRedirects = httpClientProperties.isFollowRedirects();
|
Boolean followRedirects = httpClientProperties.isFollowRedirects();
|
||||||
Integer connectTimeout = httpClientProperties.getConnectionTimeout();
|
Integer connectTimeout = httpClientProperties.getConnectionTimeout();
|
||||||
this.okHttpClient = httpClientFactory
|
this.okHttpClient = httpClientFactory.createBuilder(httpClientProperties.isDisableSslValidation()).
|
||||||
.createBuilder(httpClientProperties.isDisableSslValidation())
|
connectTimeout(connectTimeout, TimeUnit.MILLISECONDS).
|
||||||
.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
|
followRedirects(followRedirects).
|
||||||
.followRedirects(followRedirects).connectionPool(connectionPool)
|
connectionPool(connectionPool).build();
|
||||||
.build();
|
|
||||||
return this.okHttpClient;
|
return this.okHttpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreDestroy
|
@PreDestroy
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
if (this.okHttpClient != null) {
|
if(okHttpClient != null) {
|
||||||
this.okHttpClient.dispatcher().executorService().shutdown();
|
okHttpClient.dispatcher().executorService().shutdown();
|
||||||
this.okHttpClient.connectionPool().evictAll();
|
okHttpClient.connectionPool().evictAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(Client.class)
|
||||||
|
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
|
||||||
|
SpringClientFactory clientFactory, okhttp3.OkHttpClient okHttpClient) {
|
||||||
|
OkHttpClient delegate = new OkHttpClient(okHttpClient);
|
||||||
|
return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-58
@@ -1,32 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* * Copyright 2013-2016 the original author or authors.
|
||||||
* you may not use this file except in compliance with the License.
|
* *
|
||||||
* You may obtain a copy of the License at
|
* * 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.
|
||||||
*
|
*
|
||||||
* 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.ribbon;
|
package org.springframework.cloud.openfeign.ribbon;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import com.netflix.client.DefaultLoadBalancerRetryHandler;
|
|
||||||
import com.netflix.client.RequestSpecificRetryHandler;
|
|
||||||
import com.netflix.client.config.IClientConfig;
|
|
||||||
import com.netflix.loadbalancer.ILoadBalancer;
|
|
||||||
import com.netflix.loadbalancer.Server;
|
|
||||||
import feign.Request;
|
import feign.Request;
|
||||||
import feign.Response;
|
import feign.Response;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRecoveryCallback;
|
import org.springframework.cloud.client.loadbalancer.LoadBalancedRecoveryCallback;
|
||||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext;
|
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryContext;
|
||||||
@@ -44,82 +40,71 @@ import org.springframework.retry.backoff.NoBackOffPolicy;
|
|||||||
import org.springframework.retry.policy.NeverRetryPolicy;
|
import org.springframework.retry.policy.NeverRetryPolicy;
|
||||||
import org.springframework.retry.support.RetryTemplate;
|
import org.springframework.retry.support.RetryTemplate;
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.util.StreamUtils;
|
||||||
|
import com.netflix.client.DefaultLoadBalancerRetryHandler;
|
||||||
|
import com.netflix.client.RequestSpecificRetryHandler;
|
||||||
|
import com.netflix.client.config.IClientConfig;
|
||||||
|
import com.netflix.loadbalancer.ILoadBalancer;
|
||||||
|
import com.netflix.loadbalancer.Server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link FeignLoadBalancer} that leverages Spring Retry to retry failed requests.
|
* A {@link FeignLoadBalancer} that leverages Spring Retry to retry failed requests.
|
||||||
*
|
|
||||||
* @author Ryan Baxter
|
* @author Ryan Baxter
|
||||||
* @author Gang Li
|
* @author Gang Li
|
||||||
*/
|
*/
|
||||||
public class RetryableFeignLoadBalancer extends FeignLoadBalancer
|
public class RetryableFeignLoadBalancer extends FeignLoadBalancer implements ServiceInstanceChooser {
|
||||||
implements ServiceInstanceChooser {
|
|
||||||
|
|
||||||
private final LoadBalancedRetryFactory loadBalancedRetryFactory;
|
private final LoadBalancedRetryFactory loadBalancedRetryFactory;
|
||||||
|
|
||||||
public RetryableFeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig,
|
public RetryableFeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig, ServerIntrospector serverIntrospector,
|
||||||
ServerIntrospector serverIntrospector,
|
LoadBalancedRetryFactory loadBalancedRetryFactory) {
|
||||||
LoadBalancedRetryFactory loadBalancedRetryFactory) {
|
|
||||||
super(lb, clientConfig, serverIntrospector);
|
super(lb, clientConfig, serverIntrospector);
|
||||||
this.loadBalancedRetryFactory = loadBalancedRetryFactory;
|
this.loadBalancedRetryFactory = loadBalancedRetryFactory;
|
||||||
this.setRetryHandler(new DefaultLoadBalancerRetryHandler(clientConfig));
|
this.setRetryHandler(new DefaultLoadBalancerRetryHandler(clientConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RibbonResponse execute(final RibbonRequest request,
|
public RibbonResponse execute(final RibbonRequest request, IClientConfig configOverride)
|
||||||
IClientConfig configOverride) throws IOException {
|
throws IOException {
|
||||||
final Request.Options options;
|
final Request.Options options;
|
||||||
if (configOverride != null) {
|
if (configOverride != null) {
|
||||||
RibbonProperties ribbon = RibbonProperties.from(configOverride);
|
RibbonProperties ribbon = RibbonProperties.from(configOverride);
|
||||||
options = new Request.Options(ribbon.connectTimeout(this.connectTimeout),
|
options = new Request.Options(
|
||||||
|
ribbon.connectTimeout(this.connectTimeout),
|
||||||
ribbon.readTimeout(this.readTimeout));
|
ribbon.readTimeout(this.readTimeout));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
options = new Request.Options(this.connectTimeout, this.readTimeout);
|
options = new Request.Options(this.connectTimeout, this.readTimeout);
|
||||||
}
|
}
|
||||||
final LoadBalancedRetryPolicy retryPolicy = this.loadBalancedRetryFactory
|
final LoadBalancedRetryPolicy retryPolicy = loadBalancedRetryFactory.createRetryPolicy(this.getClientName(), this);
|
||||||
.createRetryPolicy(this.getClientName(), this);
|
|
||||||
RetryTemplate retryTemplate = new RetryTemplate();
|
RetryTemplate retryTemplate = new RetryTemplate();
|
||||||
BackOffPolicy backOffPolicy = this.loadBalancedRetryFactory
|
BackOffPolicy backOffPolicy = loadBalancedRetryFactory.createBackOffPolicy(this.getClientName());
|
||||||
.createBackOffPolicy(this.getClientName());
|
retryTemplate.setBackOffPolicy(backOffPolicy == null ? new NoBackOffPolicy() : backOffPolicy);
|
||||||
retryTemplate.setBackOffPolicy(
|
RetryListener[] retryListeners = this.loadBalancedRetryFactory.createRetryListeners(this.getClientName());
|
||||||
backOffPolicy == null ? new NoBackOffPolicy() : backOffPolicy);
|
|
||||||
RetryListener[] retryListeners = this.loadBalancedRetryFactory
|
|
||||||
.createRetryListeners(this.getClientName());
|
|
||||||
if (retryListeners != null && retryListeners.length != 0) {
|
if (retryListeners != null && retryListeners.length != 0) {
|
||||||
retryTemplate.setListeners(retryListeners);
|
retryTemplate.setListeners(retryListeners);
|
||||||
}
|
}
|
||||||
retryTemplate.setRetryPolicy(retryPolicy == null ? new NeverRetryPolicy()
|
retryTemplate.setRetryPolicy(retryPolicy == null ? new NeverRetryPolicy()
|
||||||
: new FeignRetryPolicy(request.toHttpRequest(), retryPolicy, this,
|
: new FeignRetryPolicy(request.toHttpRequest(), retryPolicy, this, this.getClientName()));
|
||||||
this.getClientName()));
|
|
||||||
return retryTemplate.execute(new RetryCallback<RibbonResponse, IOException>() {
|
return retryTemplate.execute(new RetryCallback<RibbonResponse, IOException>() {
|
||||||
@Override
|
@Override
|
||||||
public RibbonResponse doWithRetry(RetryContext retryContext)
|
public RibbonResponse doWithRetry(RetryContext retryContext) throws IOException {
|
||||||
throws IOException {
|
|
||||||
Request feignRequest = null;
|
Request feignRequest = null;
|
||||||
// on retries the policy will choose the server and set it in the context
|
//on retries the policy will choose the server and set it in the context
|
||||||
// extract the server and update the request being made
|
//extract the server and update the request being made
|
||||||
if (retryContext instanceof LoadBalancedRetryContext) {
|
if (retryContext instanceof LoadBalancedRetryContext) {
|
||||||
ServiceInstance service = ((LoadBalancedRetryContext) retryContext)
|
ServiceInstance service = ((LoadBalancedRetryContext) retryContext).getServiceInstance();
|
||||||
.getServiceInstance();
|
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
feignRequest = ((RibbonRequest) request
|
feignRequest = ((RibbonRequest) request.replaceUri(reconstructURIWithServer(new Server(service.getHost(), service.getPort()), request.getUri()))).toRequest();
|
||||||
.replaceUri(reconstructURIWithServer(
|
|
||||||
new Server(service.getHost(), service.getPort()),
|
|
||||||
request.getUri()))).toRequest();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (feignRequest == null) {
|
if (feignRequest == null) {
|
||||||
feignRequest = request.toRequest();
|
feignRequest = request.toRequest();
|
||||||
}
|
}
|
||||||
Response response = request.client().execute(feignRequest, options);
|
Response response = request.client().execute(feignRequest, options);
|
||||||
if (retryPolicy != null
|
if (retryPolicy != null && retryPolicy.retryableStatusCode(response.status())) {
|
||||||
&& retryPolicy.retryableStatusCode(response.status())) {
|
byte[] byteArray = response.body() == null ? new byte[]{} : StreamUtils.copyToByteArray(response.body().asInputStream());
|
||||||
byte[] byteArray = response.body() == null ? new byte[] {}
|
|
||||||
: StreamUtils
|
|
||||||
.copyToByteArray(response.body().asInputStream());
|
|
||||||
response.close();
|
response.close();
|
||||||
throw new RibbonResponseStatusCodeException(
|
throw new RibbonResponseStatusCodeException(RetryableFeignLoadBalancer.this.clientName, response,
|
||||||
RetryableFeignLoadBalancer.this.clientName, response,
|
|
||||||
byteArray, request.getUri());
|
byteArray, request.getUri());
|
||||||
}
|
}
|
||||||
return new RibbonResponse(request.getUri(), response);
|
return new RibbonResponse(request.getUri(), response);
|
||||||
@@ -135,8 +120,7 @@ public class RetryableFeignLoadBalancer extends FeignLoadBalancer
|
|||||||
@Override
|
@Override
|
||||||
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
|
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
|
||||||
FeignLoadBalancer.RibbonRequest request, IClientConfig requestConfig) {
|
FeignLoadBalancer.RibbonRequest request, IClientConfig requestConfig) {
|
||||||
return new RequestSpecificRetryHandler(false, false, this.getRetryHandler(),
|
return new RequestSpecificRetryHandler(false, false, this.getRetryHandler(), requestConfig);
|
||||||
requestConfig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -144,5 +128,4 @@ public class RetryableFeignLoadBalancer extends FeignLoadBalancer
|
|||||||
return new RibbonLoadBalancerClient.RibbonServer(serviceId,
|
return new RibbonLoadBalancerClient.RibbonServer(serviceId,
|
||||||
this.getLoadBalancer().chooseServer(serviceId));
|
this.getLoadBalancer().chooseServer(serviceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-14
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -13,37 +13,33 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign.ribbon;
|
package org.springframework.cloud.openfeign.ribbon;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import feign.Response;
|
import feign.Response;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
import org.springframework.cloud.client.loadbalancer.RetryableStatusCodeException;
|
import org.springframework.cloud.client.loadbalancer.RetryableStatusCodeException;
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link RetryableStatusCodeException} for {@link Response}s.
|
* A {@link RetryableStatusCodeException} for {@link Response}s
|
||||||
*
|
|
||||||
* @author Ryan Baxter
|
* @author Ryan Baxter
|
||||||
*/
|
*/
|
||||||
public class RibbonResponseStatusCodeException extends RetryableStatusCodeException {
|
public class RibbonResponseStatusCodeException extends RetryableStatusCodeException {
|
||||||
|
private Response response;
|
||||||
|
|
||||||
private final Response response;
|
public RibbonResponseStatusCodeException(String serviceId, Response response, byte[] body, URI uri) {
|
||||||
|
|
||||||
public RibbonResponseStatusCodeException(String serviceId, Response response,
|
|
||||||
byte[] body, URI uri) {
|
|
||||||
super(serviceId, response.status(), response, uri);
|
super(serviceId, response.status(), response, uri);
|
||||||
this.response = Response.builder()
|
this.response = Response.builder().body(new ByteArrayInputStream(body), body.length)
|
||||||
.body(new ByteArrayInputStream(body), body.length)
|
|
||||||
.headers(response.headers()).reason(response.reason())
|
.headers(response.headers()).reason(response.reason())
|
||||||
.status(response.status()).request(response.request()).build();
|
.status(response.status()).request(response.request()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response getResponse() {
|
public Response getResponse() {
|
||||||
return this.response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-29
@@ -1,19 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2019 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;
|
package org.springframework.cloud.openfeign.support;
|
||||||
|
|
||||||
import com.netflix.hystrix.HystrixCommand;
|
import com.netflix.hystrix.HystrixCommand;
|
||||||
@@ -22,11 +6,8 @@ import com.netflix.hystrix.HystrixThreadPoolKey;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience class for implementing feign fallbacks that return {@link HystrixCommand}.
|
* Convenience class for implementing feign fallbacks that return {@link HystrixCommand}.
|
||||||
* Also useful for return types of {@link rx.Observable} and
|
* Also useful for return types of {@link rx.Observable} and {@link java.util.concurrent.Future}.
|
||||||
* {@link java.util.concurrent.Future}. For those return types, just call
|
* For those return types, just call {@link FallbackCommand#observe()} or {@link FallbackCommand#queue()} respectively.
|
||||||
* {@link FallbackCommand#observe()} or {@link FallbackCommand#queue()} respectively.
|
|
||||||
*
|
|
||||||
* @param <T> result type
|
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
*/
|
*/
|
||||||
public class FallbackCommand<T> extends HystrixCommand<T> {
|
public class FallbackCommand<T> extends HystrixCommand<T> {
|
||||||
@@ -47,21 +28,17 @@ public class FallbackCommand<T> extends HystrixCommand<T> {
|
|||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FallbackCommand(T result, HystrixCommandGroupKey group,
|
public FallbackCommand(T result, HystrixCommandGroupKey group, int executionIsolationThreadTimeoutInMilliseconds) {
|
||||||
int executionIsolationThreadTimeoutInMilliseconds) {
|
|
||||||
super(group, executionIsolationThreadTimeoutInMilliseconds);
|
super(group, executionIsolationThreadTimeoutInMilliseconds);
|
||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FallbackCommand(T result, HystrixCommandGroupKey group,
|
public FallbackCommand(T result, HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool) {
|
||||||
HystrixThreadPoolKey threadPool) {
|
|
||||||
super(group, threadPool);
|
super(group, threadPool);
|
||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FallbackCommand(T result, HystrixCommandGroupKey group,
|
public FallbackCommand(T result, HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool, int executionIsolationThreadTimeoutInMilliseconds) {
|
||||||
HystrixThreadPoolKey threadPool,
|
|
||||||
int executionIsolationThreadTimeoutInMilliseconds) {
|
|
||||||
super(group, threadPool, executionIsolationThreadTimeoutInMilliseconds);
|
super(group, threadPool, executionIsolationThreadTimeoutInMilliseconds);
|
||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
@@ -75,5 +52,4 @@ public class FallbackCommand<T> extends HystrixCommand<T> {
|
|||||||
protected T run() throws Exception {
|
protected T run() throws Exception {
|
||||||
return this.result;
|
return this.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-60
@@ -1,23 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* * Copyright 2013-2016 the original author or authors.
|
||||||
* you may not use this file except in compliance with the License.
|
* *
|
||||||
* You may obtain a copy of the License at
|
* * 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.
|
||||||
*
|
*
|
||||||
* 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;
|
package org.springframework.cloud.openfeign.support;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,65 +26,26 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||||||
*/
|
*/
|
||||||
@ConfigurationProperties(prefix = "feign.httpclient")
|
@ConfigurationProperties(prefix = "feign.httpclient")
|
||||||
public class FeignHttpClientProperties {
|
public class FeignHttpClientProperties {
|
||||||
|
|
||||||
/**
|
|
||||||
* Default value for disabling SSL validation.
|
|
||||||
*/
|
|
||||||
public static final boolean DEFAULT_DISABLE_SSL_VALIDATION = false;
|
public static final boolean DEFAULT_DISABLE_SSL_VALIDATION = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default value for max number od connections.
|
|
||||||
*/
|
|
||||||
public static final int DEFAULT_MAX_CONNECTIONS = 200;
|
public static final int DEFAULT_MAX_CONNECTIONS = 200;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default value for max number od connections per route.
|
|
||||||
*/
|
|
||||||
public static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 50;
|
public static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 50;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default value for time to live.
|
|
||||||
*/
|
|
||||||
public static final long DEFAULT_TIME_TO_LIVE = 900L;
|
public static final long DEFAULT_TIME_TO_LIVE = 900L;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default time to live unit.
|
|
||||||
*/
|
|
||||||
public static final TimeUnit DEFAULT_TIME_TO_LIVE_UNIT = TimeUnit.SECONDS;
|
public static final TimeUnit DEFAULT_TIME_TO_LIVE_UNIT = TimeUnit.SECONDS;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default value for following redirects.
|
|
||||||
*/
|
|
||||||
public static final boolean DEFAULT_FOLLOW_REDIRECTS = true;
|
public static final boolean DEFAULT_FOLLOW_REDIRECTS = true;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default value for connection timeout.
|
|
||||||
*/
|
|
||||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 2000;
|
public static final int DEFAULT_CONNECTION_TIMEOUT = 2000;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default value for connection timer repeat.
|
|
||||||
*/
|
|
||||||
public static final int DEFAULT_CONNECTION_TIMER_REPEAT = 3000;
|
public static final int DEFAULT_CONNECTION_TIMER_REPEAT = 3000;
|
||||||
|
|
||||||
private boolean disableSslValidation = DEFAULT_DISABLE_SSL_VALIDATION;
|
private boolean disableSslValidation = DEFAULT_DISABLE_SSL_VALIDATION;
|
||||||
|
|
||||||
private int maxConnections = DEFAULT_MAX_CONNECTIONS;
|
private int maxConnections = DEFAULT_MAX_CONNECTIONS;
|
||||||
|
|
||||||
private int maxConnectionsPerRoute = DEFAULT_MAX_CONNECTIONS_PER_ROUTE;
|
private int maxConnectionsPerRoute = DEFAULT_MAX_CONNECTIONS_PER_ROUTE;
|
||||||
|
|
||||||
private long timeToLive = DEFAULT_TIME_TO_LIVE;
|
private long timeToLive = DEFAULT_TIME_TO_LIVE;
|
||||||
|
|
||||||
private TimeUnit timeToLiveUnit = DEFAULT_TIME_TO_LIVE_UNIT;
|
private TimeUnit timeToLiveUnit = DEFAULT_TIME_TO_LIVE_UNIT;
|
||||||
|
|
||||||
private boolean followRedirects = DEFAULT_FOLLOW_REDIRECTS;
|
private boolean followRedirects = DEFAULT_FOLLOW_REDIRECTS;
|
||||||
|
|
||||||
private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
|
private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
|
||||||
|
|
||||||
private int connectionTimerRepeat = DEFAULT_CONNECTION_TIMER_REPEAT;
|
private int connectionTimerRepeat = DEFAULT_CONNECTION_TIMER_REPEAT;
|
||||||
|
|
||||||
public int getConnectionTimerRepeat() {
|
public int getConnectionTimerRepeat() {
|
||||||
return this.connectionTimerRepeat;
|
return connectionTimerRepeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConnectionTimerRepeat(int connectionTimerRepeat) {
|
public void setConnectionTimerRepeat(int connectionTimerRepeat) {
|
||||||
@@ -91,7 +53,7 @@ public class FeignHttpClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDisableSslValidation() {
|
public boolean isDisableSslValidation() {
|
||||||
return this.disableSslValidation;
|
return disableSslValidation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisableSslValidation(boolean disableSslValidation) {
|
public void setDisableSslValidation(boolean disableSslValidation) {
|
||||||
@@ -99,7 +61,7 @@ public class FeignHttpClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxConnections() {
|
public int getMaxConnections() {
|
||||||
return this.maxConnections;
|
return maxConnections;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMaxConnections(int maxConnections) {
|
public void setMaxConnections(int maxConnections) {
|
||||||
@@ -107,7 +69,7 @@ public class FeignHttpClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxConnectionsPerRoute() {
|
public int getMaxConnectionsPerRoute() {
|
||||||
return this.maxConnectionsPerRoute;
|
return maxConnectionsPerRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMaxConnectionsPerRoute(int maxConnectionsPerRoute) {
|
public void setMaxConnectionsPerRoute(int maxConnectionsPerRoute) {
|
||||||
@@ -115,7 +77,7 @@ public class FeignHttpClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long getTimeToLive() {
|
public long getTimeToLive() {
|
||||||
return this.timeToLive;
|
return timeToLive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTimeToLive(long timeToLive) {
|
public void setTimeToLive(long timeToLive) {
|
||||||
@@ -123,7 +85,7 @@ public class FeignHttpClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TimeUnit getTimeToLiveUnit() {
|
public TimeUnit getTimeToLiveUnit() {
|
||||||
return this.timeToLiveUnit;
|
return timeToLiveUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTimeToLiveUnit(TimeUnit timeToLiveUnit) {
|
public void setTimeToLiveUnit(TimeUnit timeToLiveUnit) {
|
||||||
@@ -131,7 +93,7 @@ public class FeignHttpClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFollowRedirects() {
|
public boolean isFollowRedirects() {
|
||||||
return this.followRedirects;
|
return followRedirects;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFollowRedirects(boolean followRedirects) {
|
public void setFollowRedirects(boolean followRedirects) {
|
||||||
@@ -139,11 +101,10 @@ public class FeignHttpClientProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getConnectionTimeout() {
|
public int getConnectionTimeout() {
|
||||||
return this.connectionTimeout;
|
return connectionTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConnectionTimeout(int connectionTimeout) {
|
public void setConnectionTimeout(int connectionTimeout) {
|
||||||
this.connectionTimeout = connectionTimeout;
|
this.connectionTimeout = connectionTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-17
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -24,17 +24,10 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
|
||||||
import static java.util.Optional.ofNullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
* @author Olga Maciaszek-Sharma
|
|
||||||
*/
|
*/
|
||||||
public final class FeignUtils {
|
public class FeignUtils {
|
||||||
|
|
||||||
private FeignUtils() {
|
|
||||||
throw new IllegalStateException("Can't instantiate a utility class");
|
|
||||||
}
|
|
||||||
|
|
||||||
static HttpHeaders getHttpHeaders(Map<String, Collection<String>> headers) {
|
static HttpHeaders getHttpHeaders(Map<String, Collection<String>> headers) {
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
@@ -54,12 +47,4 @@ public final class FeignUtils {
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Collection<String> addTemplateParameter(Collection<String> possiblyNull,
|
|
||||||
String paramName) {
|
|
||||||
Collection<String> params = ofNullable(possiblyNull).map(ArrayList::new)
|
|
||||||
.orElse(new ArrayList<>());
|
|
||||||
params.add(String.format("{%s}", paramName));
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-171
@@ -1,171 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2018 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.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.fasterxml.jackson.core.Version;
|
|
||||||
import com.fasterxml.jackson.databind.Module;
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
|
||||||
|
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.PageImpl;
|
|
||||||
import org.springframework.data.domain.PageRequest;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.domain.Sort;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This jackson module provides support to deserialize spring {@link Page} objects.
|
|
||||||
*
|
|
||||||
* @author Pascal Büttiker
|
|
||||||
*/
|
|
||||||
public class PageJacksonModule extends Module {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getModuleName() {
|
|
||||||
return "PageJacksonModule";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Version version() {
|
|
||||||
return new Version(0, 1, 0, "", null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setupModule(SetupContext context) {
|
|
||||||
context.setMixInAnnotations(Page.class, PageMixIn.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonDeserialize(as = SimplePageImpl.class)
|
|
||||||
private interface PageMixIn {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class SimplePageImpl<T> implements Page<T> {
|
|
||||||
|
|
||||||
private final Page<T> delegate;
|
|
||||||
|
|
||||||
SimplePageImpl(@JsonProperty("content") List<T> content,
|
|
||||||
@JsonProperty("page") int number, @JsonProperty("size") int size,
|
|
||||||
@JsonProperty("totalElements") long totalElements) {
|
|
||||||
delegate = new PageImpl<>(content, PageRequest.of(number, size),
|
|
||||||
totalElements);
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@Override
|
|
||||||
public int getTotalPages() {
|
|
||||||
return delegate.getTotalPages();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@Override
|
|
||||||
public long getTotalElements() {
|
|
||||||
return delegate.getTotalElements();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty("page")
|
|
||||||
@Override
|
|
||||||
public int getNumber() {
|
|
||||||
return delegate.getNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@Override
|
|
||||||
public int getSize() {
|
|
||||||
return delegate.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@Override
|
|
||||||
public int getNumberOfElements() {
|
|
||||||
return delegate.getNumberOfElements();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@Override
|
|
||||||
public List<T> getContent() {
|
|
||||||
return delegate.getContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@Override
|
|
||||||
public boolean hasContent() {
|
|
||||||
return delegate.hasContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Override
|
|
||||||
public Sort getSort() {
|
|
||||||
return delegate.getSort();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@Override
|
|
||||||
public boolean isFirst() {
|
|
||||||
return delegate.isFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@Override
|
|
||||||
public boolean isLast() {
|
|
||||||
return delegate.isLast();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return delegate.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Override
|
|
||||||
public boolean hasPrevious() {
|
|
||||||
return delegate.hasPrevious();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Override
|
|
||||||
public Pageable nextPageable() {
|
|
||||||
return delegate.nextPageable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Override
|
|
||||||
public Pageable previousPageable() {
|
|
||||||
return delegate.previousPageable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Override
|
|
||||||
public <S> Page<S> map(Function<? super T, ? extends S> converter) {
|
|
||||||
return delegate.map(converter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Override
|
|
||||||
public Iterator<T> iterator() {
|
|
||||||
return delegate.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-122
@@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2018 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.lang.reflect.Type;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import feign.RequestTemplate;
|
|
||||||
import feign.codec.EncodeException;
|
|
||||||
import feign.codec.Encoder;
|
|
||||||
|
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.domain.Sort;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides support for encoding spring Pageable via composition.
|
|
||||||
*
|
|
||||||
* @author Pascal Büttiker
|
|
||||||
*/
|
|
||||||
public class PageableSpringEncoder implements Encoder {
|
|
||||||
|
|
||||||
private final Encoder delegate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Page index parameter name.
|
|
||||||
*/
|
|
||||||
private String pageParameter = "page";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Page size parameter name.
|
|
||||||
*/
|
|
||||||
private String sizeParameter = "size";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort parameter name.
|
|
||||||
*/
|
|
||||||
private String sortParameter = "sort";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new PageableSpringEncoder with the given delegate for fallback. If no
|
|
||||||
* delegate is provided and this encoder cant handle the request, an EncodeException
|
|
||||||
* is thrown.
|
|
||||||
* @param delegate The optional delegate.
|
|
||||||
*/
|
|
||||||
public PageableSpringEncoder(Encoder delegate) {
|
|
||||||
this.delegate = delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encode(Object object, Type bodyType, RequestTemplate template)
|
|
||||||
throws EncodeException {
|
|
||||||
|
|
||||||
if (supports(object)) {
|
|
||||||
if (object instanceof Pageable) {
|
|
||||||
Pageable pageable = (Pageable) object;
|
|
||||||
|
|
||||||
if (pageable.isPaged()) {
|
|
||||||
template.query(pageParameter, pageable.getPageNumber() + "");
|
|
||||||
template.query(sizeParameter, pageable.getPageSize() + "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pageable.getSort() != null) {
|
|
||||||
applySort(template, pageable.getSort());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (object instanceof Sort) {
|
|
||||||
Sort sort = (Sort) object;
|
|
||||||
applySort(template, sort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (delegate != null) {
|
|
||||||
delegate.encode(object, bodyType, template);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new EncodeException(
|
|
||||||
"PageableSpringEncoder does not support the given object "
|
|
||||||
+ object.getClass()
|
|
||||||
+ " and no delegate was provided for fallback!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applySort(RequestTemplate template, Sort sort) {
|
|
||||||
Collection<String> existingSorts = template.queries().get("sort");
|
|
||||||
List<String> sortQueries = existingSorts != null ? new ArrayList<>(existingSorts)
|
|
||||||
: new ArrayList<>();
|
|
||||||
if (!sortParameter.equals("sort")) {
|
|
||||||
existingSorts = template.queries().get(sortParameter);
|
|
||||||
if (existingSorts != null) {
|
|
||||||
sortQueries.addAll(existingSorts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Sort.Order order : sort) {
|
|
||||||
sortQueries.add(order.getProperty() + "," + order.getDirection());
|
|
||||||
}
|
|
||||||
if (!sortQueries.isEmpty()) {
|
|
||||||
template.query(sortParameter, sortQueries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean supports(Object object) {
|
|
||||||
return object instanceof Pageable || object instanceof Sort;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+12
-30
@@ -1,19 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2019 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;
|
package org.springframework.cloud.openfeign.support;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -21,21 +5,20 @@ import java.lang.reflect.ParameterizedType;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import feign.FeignException;
|
|
||||||
import feign.Response;
|
|
||||||
import feign.codec.Decoder;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
|
import feign.FeignException;
|
||||||
|
import feign.Response;
|
||||||
|
import feign.codec.Decoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decoder adds compatibility for Spring MVC's ResponseEntity to any other decoder via
|
* Decoder adds compatibility for Spring MVC's ResponseEntity to any other decoder via
|
||||||
* composition.
|
* composition.
|
||||||
*
|
* @author chadjaros
|
||||||
* @author chad jaros
|
|
||||||
*/
|
*/
|
||||||
public class ResponseEntityDecoder implements Decoder {
|
public class ResponseEntityDecoder implements Decoder {
|
||||||
|
|
||||||
@@ -46,12 +29,12 @@ public class ResponseEntityDecoder implements Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object decode(final Response response, Type type)
|
public Object decode(final Response response, Type type) throws IOException,
|
||||||
throws IOException, FeignException {
|
FeignException {
|
||||||
|
|
||||||
if (isParameterizeHttpEntity(type)) {
|
if (isParameterizeHttpEntity(type)) {
|
||||||
type = ((ParameterizedType) type).getActualTypeArguments()[0];
|
type = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||||
Object decodedObject = this.decoder.decode(response, type);
|
Object decodedObject = decoder.decode(response, type);
|
||||||
|
|
||||||
return createResponse(decodedObject, response);
|
return createResponse(decodedObject, response);
|
||||||
}
|
}
|
||||||
@@ -59,7 +42,7 @@ public class ResponseEntityDecoder implements Decoder {
|
|||||||
return createResponse(null, response);
|
return createResponse(null, response);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return this.decoder.decode(response, type);
|
return decoder.decode(response, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,8 +69,7 @@ public class ResponseEntityDecoder implements Decoder {
|
|||||||
headers.put(key, new LinkedList<>(response.headers().get(key)));
|
headers.put(key, new LinkedList<>(response.headers().get(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ResponseEntity<>((T) instance, headers,
|
return new ResponseEntity<>((T) instance, headers, HttpStatus.valueOf(response
|
||||||
HttpStatus.valueOf(response.status()));
|
.status()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
+10
-9
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,21 +12,19 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign.support;
|
package org.springframework.cloud.openfeign.support;
|
||||||
|
|
||||||
|
import static org.springframework.cloud.openfeign.support.FeignUtils.getHttpHeaders;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.lang.reflect.WildcardType;
|
import java.lang.reflect.WildcardType;
|
||||||
|
|
||||||
import feign.FeignException;
|
|
||||||
import feign.Response;
|
|
||||||
import feign.codec.DecodeException;
|
|
||||||
import feign.codec.Decoder;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectFactory;
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
@@ -34,7 +32,10 @@ import org.springframework.http.HttpStatus;
|
|||||||
import org.springframework.http.client.ClientHttpResponse;
|
import org.springframework.http.client.ClientHttpResponse;
|
||||||
import org.springframework.web.client.HttpMessageConverterExtractor;
|
import org.springframework.web.client.HttpMessageConverterExtractor;
|
||||||
|
|
||||||
import static org.springframework.cloud.openfeign.support.FeignUtils.getHttpHeaders;
|
import feign.FeignException;
|
||||||
|
import feign.Response;
|
||||||
|
import feign.codec.DecodeException;
|
||||||
|
import feign.codec.Decoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
@@ -58,11 +59,11 @@ public class SpringDecoder implements Decoder {
|
|||||||
|
|
||||||
return extractor.extractData(new FeignResponseAdapter(response));
|
return extractor.extractData(new FeignResponseAdapter(response));
|
||||||
}
|
}
|
||||||
throw new DecodeException(response.status(),
|
throw new DecodeException(
|
||||||
"type is not an instance of Class or ParameterizedType: " + type);
|
"type is not an instance of Class or ParameterizedType: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class FeignResponseAdapter implements ClientHttpResponse {
|
private class FeignResponseAdapter implements ClientHttpResponse {
|
||||||
|
|
||||||
private final Response response;
|
private final Response response;
|
||||||
|
|
||||||
|
|||||||
+21
-26
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign.support;
|
package org.springframework.cloud.openfeign.support;
|
||||||
@@ -25,14 +26,8 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import feign.Request;
|
|
||||||
import feign.RequestTemplate;
|
|
||||||
import feign.codec.EncodeException;
|
|
||||||
import feign.codec.Encoder;
|
|
||||||
import feign.form.spring.SpringFormEncoder;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectFactory;
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
@@ -43,12 +38,17 @@ import org.springframework.http.converter.HttpMessageConverter;
|
|||||||
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
|
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import feign.RequestTemplate;
|
||||||
|
import feign.codec.EncodeException;
|
||||||
|
import feign.codec.Encoder;
|
||||||
|
import feign.form.spring.SpringFormEncoder;
|
||||||
|
|
||||||
import static org.springframework.cloud.openfeign.support.FeignUtils.getHeaders;
|
import static org.springframework.cloud.openfeign.support.FeignUtils.getHeaders;
|
||||||
import static org.springframework.cloud.openfeign.support.FeignUtils.getHttpHeaders;
|
import static org.springframework.cloud.openfeign.support.FeignUtils.getHttpHeaders;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
* @author Scien Jus
|
* @author ScienJus
|
||||||
*/
|
*/
|
||||||
public class SpringEncoder implements Encoder {
|
public class SpringEncoder implements Encoder {
|
||||||
|
|
||||||
@@ -78,13 +78,12 @@ public class SpringEncoder implements Encoder {
|
|||||||
|
|
||||||
if (bodyType != null && bodyType.equals(MultipartFile.class)) {
|
if (bodyType != null && bodyType.equals(MultipartFile.class)) {
|
||||||
if (Objects.equals(requestContentType, MediaType.MULTIPART_FORM_DATA)) {
|
if (Objects.equals(requestContentType, MediaType.MULTIPART_FORM_DATA)) {
|
||||||
this.springFormEncoder.encode(requestBody, bodyType, request);
|
springFormEncoder.encode(requestBody, bodyType, request);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else {
|
String message = "Content-Type \"" + MediaType.MULTIPART_FORM_DATA +
|
||||||
String message = "Content-Type \"" + MediaType.MULTIPART_FORM_DATA
|
"\" not set for request body of type " +
|
||||||
+ "\" not set for request body of type "
|
requestBody.getClass().getSimpleName();
|
||||||
+ requestBody.getClass().getSimpleName();
|
|
||||||
throw new EncodeException(message);
|
throw new EncodeException(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,8 +94,8 @@ public class SpringEncoder implements Encoder {
|
|||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
if (requestContentType != null) {
|
if (requestContentType != null) {
|
||||||
log.debug("Writing [" + requestBody + "] as \""
|
log.debug("Writing [" + requestBody + "] as \""
|
||||||
+ requestContentType + "\" using [" + messageConverter
|
+ requestContentType + "\" using ["
|
||||||
+ "]");
|
+ messageConverter + "]");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.debug("Writing [" + requestBody + "] using ["
|
log.debug("Writing [" + requestBody + "] using ["
|
||||||
@@ -124,17 +123,13 @@ public class SpringEncoder implements Encoder {
|
|||||||
Charset charset;
|
Charset charset;
|
||||||
if (messageConverter instanceof ByteArrayHttpMessageConverter) {
|
if (messageConverter instanceof ByteArrayHttpMessageConverter) {
|
||||||
charset = null;
|
charset = null;
|
||||||
}
|
} else if (messageConverter instanceof ProtobufHttpMessageConverter &&
|
||||||
else if (messageConverter instanceof ProtobufHttpMessageConverter
|
ProtobufHttpMessageConverter.PROTOBUF.isCompatibleWith(outputMessage.getHeaders().getContentType())) {
|
||||||
&& ProtobufHttpMessageConverter.PROTOBUF.isCompatibleWith(
|
|
||||||
outputMessage.getHeaders().getContentType())) {
|
|
||||||
charset = null;
|
charset = null;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
charset = StandardCharsets.UTF_8;
|
charset = StandardCharsets.UTF_8;
|
||||||
}
|
}
|
||||||
request.body(Request.Body.encoded(
|
request.body(outputMessage.getOutputStream().toByteArray(), charset);
|
||||||
outputMessage.getOutputStream().toByteArray(), charset));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,14 +142,14 @@ public class SpringEncoder implements Encoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class FeignOutputMessage implements HttpOutputMessage {
|
private class FeignOutputMessage implements HttpOutputMessage {
|
||||||
|
|
||||||
private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
|
||||||
private final HttpHeaders httpHeaders;
|
private final HttpHeaders httpHeaders;
|
||||||
|
|
||||||
private FeignOutputMessage(RequestTemplate request) {
|
private FeignOutputMessage(RequestTemplate request) {
|
||||||
this.httpHeaders = getHttpHeaders(request.headers());
|
httpHeaders = getHttpHeaders(request.headers());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+36
-123
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -18,7 +18,6 @@ package org.springframework.cloud.openfeign.support;
|
|||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Parameter;
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -29,26 +28,16 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import feign.Contract;
|
|
||||||
import feign.Feign;
|
|
||||||
import feign.MethodMetadata;
|
|
||||||
import feign.Param;
|
|
||||||
import feign.Request;
|
|
||||||
|
|
||||||
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
||||||
import org.springframework.cloud.openfeign.annotation.PathVariableParameterProcessor;
|
import org.springframework.cloud.openfeign.annotation.PathVariableParameterProcessor;
|
||||||
import org.springframework.cloud.openfeign.annotation.QueryMapParameterProcessor;
|
|
||||||
import org.springframework.cloud.openfeign.annotation.RequestHeaderParameterProcessor;
|
import org.springframework.cloud.openfeign.annotation.RequestHeaderParameterProcessor;
|
||||||
import org.springframework.cloud.openfeign.annotation.RequestParamParameterProcessor;
|
import org.springframework.cloud.openfeign.annotation.RequestParamParameterProcessor;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.ResourceLoaderAware;
|
import org.springframework.context.ResourceLoaderAware;
|
||||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||||
import org.springframework.core.MethodParameter;
|
|
||||||
import org.springframework.core.ParameterNameDiscoverer;
|
import org.springframework.core.ParameterNameDiscoverer;
|
||||||
import org.springframework.core.ResolvableType;
|
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
import org.springframework.core.convert.support.DefaultConversionService;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
@@ -59,15 +48,16 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||||||
|
|
||||||
import static feign.Util.checkState;
|
import static feign.Util.checkState;
|
||||||
import static feign.Util.emptyToNull;
|
import static feign.Util.emptyToNull;
|
||||||
import static org.springframework.cloud.openfeign.support.FeignUtils.addTemplateParameter;
|
|
||||||
import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;
|
import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;
|
||||||
|
|
||||||
|
import feign.Contract;
|
||||||
|
import feign.Feign;
|
||||||
|
import feign.MethodMetadata;
|
||||||
|
import feign.Param;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
* @author Abhijit Sarkar
|
* @author Abhijit Sarkar
|
||||||
* @author Halvdan Hoem Grelland
|
|
||||||
* @author Aram Peres
|
|
||||||
* @author Olga Maciaszek-Sharma
|
|
||||||
*/
|
*/
|
||||||
public class SpringMvcContract extends Contract.BaseContract
|
public class SpringMvcContract extends Contract.BaseContract
|
||||||
implements ResourceLoaderAware {
|
implements ResourceLoaderAware {
|
||||||
@@ -76,22 +66,13 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
|
|
||||||
private static final String CONTENT_TYPE = "Content-Type";
|
private static final String CONTENT_TYPE = "Content-Type";
|
||||||
|
|
||||||
private static final TypeDescriptor STRING_TYPE_DESCRIPTOR = TypeDescriptor
|
|
||||||
.valueOf(String.class);
|
|
||||||
|
|
||||||
private static final TypeDescriptor ITERABLE_TYPE_DESCRIPTOR = TypeDescriptor
|
|
||||||
.valueOf(Iterable.class);
|
|
||||||
|
|
||||||
private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
|
private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
|
||||||
|
|
||||||
private final Map<Class<? extends Annotation>, AnnotatedParameterProcessor> annotatedArgumentProcessors;
|
private final Map<Class<? extends Annotation>, AnnotatedParameterProcessor> annotatedArgumentProcessors;
|
||||||
|
|
||||||
private final Map<String, Method> processedMethods = new HashMap<>();
|
private final Map<String, Method> processedMethods = new HashMap<>();
|
||||||
|
|
||||||
private final ConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
private final Param.Expander expander;
|
||||||
private final ConvertingExpanderFactory convertingExpanderFactory;
|
|
||||||
|
|
||||||
private ResourceLoader resourceLoader = new DefaultResourceLoader();
|
private ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||||
|
|
||||||
public SpringMvcContract() {
|
public SpringMvcContract() {
|
||||||
@@ -119,43 +100,7 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
}
|
}
|
||||||
this.annotatedArgumentProcessors = toAnnotatedArgumentProcessorMap(processors);
|
this.annotatedArgumentProcessors = toAnnotatedArgumentProcessorMap(processors);
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
this.convertingExpanderFactory = new ConvertingExpanderFactory(conversionService);
|
this.expander = new ConvertingExpander(conversionService);
|
||||||
}
|
|
||||||
|
|
||||||
private static TypeDescriptor createTypeDescriptor(Method method, int paramIndex) {
|
|
||||||
Parameter parameter = method.getParameters()[paramIndex];
|
|
||||||
MethodParameter methodParameter = MethodParameter.forParameter(parameter);
|
|
||||||
TypeDescriptor typeDescriptor = new TypeDescriptor(methodParameter);
|
|
||||||
|
|
||||||
// Feign applies the Param.Expander to each element of an Iterable, so in those
|
|
||||||
// cases we need to provide a TypeDescriptor of the element.
|
|
||||||
if (typeDescriptor.isAssignableTo(ITERABLE_TYPE_DESCRIPTOR)) {
|
|
||||||
TypeDescriptor elementTypeDescriptor = getElementTypeDescriptor(
|
|
||||||
typeDescriptor);
|
|
||||||
|
|
||||||
checkState(elementTypeDescriptor != null,
|
|
||||||
"Could not resolve element type of Iterable type %s. Not declared?",
|
|
||||||
typeDescriptor);
|
|
||||||
|
|
||||||
typeDescriptor = elementTypeDescriptor;
|
|
||||||
}
|
|
||||||
return typeDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TypeDescriptor getElementTypeDescriptor(
|
|
||||||
TypeDescriptor typeDescriptor) {
|
|
||||||
TypeDescriptor elementTypeDescriptor = typeDescriptor.getElementTypeDescriptor();
|
|
||||||
// that means it's not a collection but it is iterable, gh-135
|
|
||||||
if (elementTypeDescriptor == null
|
|
||||||
&& Iterable.class.isAssignableFrom(typeDescriptor.getType())) {
|
|
||||||
ResolvableType type = typeDescriptor.getResolvableType().as(Iterable.class)
|
|
||||||
.getGeneric(0);
|
|
||||||
if (type.resolve() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new TypeDescriptor(type, null, typeDescriptor.getAnnotations());
|
|
||||||
}
|
|
||||||
return elementTypeDescriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -176,7 +121,7 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
if (!pathValue.startsWith("/")) {
|
if (!pathValue.startsWith("/")) {
|
||||||
pathValue = "/" + pathValue;
|
pathValue = "/" + pathValue;
|
||||||
}
|
}
|
||||||
data.template().uri(pathValue);
|
data.template().insert(0, pathValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,7 +167,7 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
methods = new RequestMethod[] { RequestMethod.GET };
|
methods = new RequestMethod[] { RequestMethod.GET };
|
||||||
}
|
}
|
||||||
checkOne(method, methods, "method");
|
checkOne(method, methods, "method");
|
||||||
data.template().method(Request.HttpMethod.valueOf(methods[0].name()));
|
data.template().method(methods[0].name());
|
||||||
|
|
||||||
// path
|
// path
|
||||||
checkAtMostOne(method, methodMapping.value(), "value");
|
checkAtMostOne(method, methodMapping.value(), "value");
|
||||||
@@ -231,10 +176,11 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
if (pathValue != null) {
|
if (pathValue != null) {
|
||||||
pathValue = resolve(pathValue);
|
pathValue = resolve(pathValue);
|
||||||
// Append path from @RequestMapping if value is present on method
|
// Append path from @RequestMapping if value is present on method
|
||||||
if (!pathValue.startsWith("/") && !data.template().path().endsWith("/")) {
|
if (!pathValue.startsWith("/")
|
||||||
|
&& !data.template().toString().endsWith("/")) {
|
||||||
pathValue = "/" + pathValue;
|
pathValue = "/" + pathValue;
|
||||||
}
|
}
|
||||||
data.template().uri(pathValue, true);
|
data.template().append(pathValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,17 +239,10 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
processParameterAnnotation, method);
|
processParameterAnnotation, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isHttpAnnotation && data.indexToExpander().get(paramIndex) == null
|
||||||
if (isHttpAnnotation && data.indexToExpander().get(paramIndex) == null) {
|
&& this.conversionService.canConvert(
|
||||||
TypeDescriptor typeDescriptor = createTypeDescriptor(method, paramIndex);
|
method.getParameterTypes()[paramIndex], String.class)) {
|
||||||
if (this.conversionService.canConvert(typeDescriptor,
|
data.indexToExpander().put(paramIndex, this.expander);
|
||||||
STRING_TYPE_DESCRIPTOR)) {
|
|
||||||
Param.Expander expander = this.convertingExpanderFactory
|
|
||||||
.getExpander(typeDescriptor);
|
|
||||||
if (expander != null) {
|
|
||||||
data.indexToExpander().put(paramIndex, expander);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return isHttpAnnotation;
|
return isHttpAnnotation;
|
||||||
}
|
}
|
||||||
@@ -336,7 +275,7 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
int index = header.indexOf('=');
|
int index = header.indexOf('=');
|
||||||
if (!header.contains("!=") && index >= 0) {
|
if (!header.contains("!=") && index >= 0) {
|
||||||
md.template().header(resolve(header.substring(0, index)),
|
md.template().header(resolve(header.substring(0, index)),
|
||||||
resolve(header.substring(index + 1).trim()));
|
resolve(header.substring(index + 1).trim()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -358,7 +297,6 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
annotatedArgumentResolvers.add(new PathVariableParameterProcessor());
|
annotatedArgumentResolvers.add(new PathVariableParameterProcessor());
|
||||||
annotatedArgumentResolvers.add(new RequestParamParameterProcessor());
|
annotatedArgumentResolvers.add(new RequestParamParameterProcessor());
|
||||||
annotatedArgumentResolvers.add(new RequestHeaderParameterProcessor());
|
annotatedArgumentResolvers.add(new RequestHeaderParameterProcessor());
|
||||||
annotatedArgumentResolvers.add(new QueryMapParameterProcessor());
|
|
||||||
|
|
||||||
return annotatedArgumentResolvers;
|
return annotatedArgumentResolvers;
|
||||||
}
|
}
|
||||||
@@ -381,51 +319,13 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
parameterAnnotation.annotationType(), null);
|
parameterAnnotation.annotationType(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldAddParameterName(int parameterIndex, Type[] parameterTypes,
|
private boolean shouldAddParameterName(int parameterIndex, Type[] parameterTypes, String[] parameterNames) {
|
||||||
String[] parameterNames) {
|
|
||||||
// has a parameter name
|
// has a parameter name
|
||||||
return parameterNames != null && parameterNames.length > parameterIndex
|
return parameterNames != null && parameterNames.length > parameterIndex
|
||||||
// has a type
|
// has a type
|
||||||
&& parameterTypes != null && parameterTypes.length > parameterIndex;
|
&& parameterTypes != null && parameterTypes.length > parameterIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Not used internally anymore. Will be removed in the future.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static class ConvertingExpander implements Param.Expander {
|
|
||||||
|
|
||||||
private final ConversionService conversionService;
|
|
||||||
|
|
||||||
public ConvertingExpander(ConversionService conversionService) {
|
|
||||||
this.conversionService = conversionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String expand(Object value) {
|
|
||||||
return this.conversionService.convert(value, String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ConvertingExpanderFactory {
|
|
||||||
|
|
||||||
private final ConversionService conversionService;
|
|
||||||
|
|
||||||
ConvertingExpanderFactory(ConversionService conversionService) {
|
|
||||||
this.conversionService = conversionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
Param.Expander getExpander(TypeDescriptor typeDescriptor) {
|
|
||||||
return value -> {
|
|
||||||
Object converted = this.conversionService.convert(value, typeDescriptor,
|
|
||||||
STRING_TYPE_DESCRIPTOR);
|
|
||||||
return (String) converted;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SimpleAnnotatedParameterContext
|
private class SimpleAnnotatedParameterContext
|
||||||
implements AnnotatedParameterProcessor.AnnotatedParameterContext {
|
implements AnnotatedParameterProcessor.AnnotatedParameterContext {
|
||||||
|
|
||||||
@@ -433,7 +333,7 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
|
|
||||||
private final int parameterIndex;
|
private final int parameterIndex;
|
||||||
|
|
||||||
SimpleAnnotatedParameterContext(MethodMetadata methodMetadata,
|
public SimpleAnnotatedParameterContext(MethodMetadata methodMetadata,
|
||||||
int parameterIndex) {
|
int parameterIndex) {
|
||||||
this.methodMetadata = methodMetadata;
|
this.methodMetadata = methodMetadata;
|
||||||
this.parameterIndex = parameterIndex;
|
this.parameterIndex = parameterIndex;
|
||||||
@@ -457,9 +357,22 @@ public class SpringMvcContract extends Contract.BaseContract
|
|||||||
@Override
|
@Override
|
||||||
public Collection<String> setTemplateParameter(String name,
|
public Collection<String> setTemplateParameter(String name,
|
||||||
Collection<String> rest) {
|
Collection<String> rest) {
|
||||||
return addTemplateParameter(rest, name);
|
return addTemplatedParam(rest, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConvertingExpander implements Param.Expander {
|
||||||
|
|
||||||
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
|
public ConvertingExpander(ConversionService conversionService) {
|
||||||
|
this.conversionService = conversionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String expand(Object value) {
|
||||||
|
return this.conversionService.convert(value, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-36
@@ -1,36 +1,33 @@
|
|||||||
{
|
{"groups": [
|
||||||
"groups": [
|
], "properties": [
|
||||||
],
|
{
|
||||||
"properties": [
|
"name": "feign.hystrix.enabled",
|
||||||
{
|
"type": "java.lang.Boolean",
|
||||||
"name": "feign.hystrix.enabled",
|
"description": "If true, an OpenFeign client will be wrapped with a Hystrix circuit breaker.",
|
||||||
"type": "java.lang.Boolean",
|
"defaultValue": "false"
|
||||||
"description": "If true, an OpenFeign client will be wrapped with a Hystrix circuit breaker.",
|
},
|
||||||
"defaultValue": "false"
|
{
|
||||||
},
|
"name": "feign.httpclient.enabled",
|
||||||
{
|
"type": "java.lang.Boolean",
|
||||||
"name": "feign.httpclient.enabled",
|
"description": "Enables the use of the Apache HTTP Client by Feign.",
|
||||||
"type": "java.lang.Boolean",
|
"defaultValue": "true"
|
||||||
"description": "Enables the use of the Apache HTTP Client by Feign.",
|
},
|
||||||
"defaultValue": "true"
|
{
|
||||||
},
|
"name": "feign.okhttp.enabled",
|
||||||
{
|
"type": "java.lang.Boolean",
|
||||||
"name": "feign.okhttp.enabled",
|
"description": "Enables the use of the OK HTTP Client by Feign.",
|
||||||
"type": "java.lang.Boolean",
|
"defaultValue": "false"
|
||||||
"description": "Enables the use of the OK HTTP Client by Feign.",
|
},
|
||||||
"defaultValue": "false"
|
{
|
||||||
},
|
"name": "feign.compression.response.enabled",
|
||||||
{
|
"type": "java.lang.Boolean",
|
||||||
"name": "feign.compression.response.enabled",
|
"description": "Enables the response from Feign to be compressed.",
|
||||||
"type": "java.lang.Boolean",
|
"defaultValue": "false"
|
||||||
"description": "Enables the response from Feign to be compressed.",
|
},
|
||||||
"defaultValue": "false"
|
{
|
||||||
},
|
"name": "feign.compression.request.enabled",
|
||||||
{
|
"type": "java.lang.Boolean",
|
||||||
"name": "feign.compression.request.enabled",
|
"description": "Enables the request sent by Feign to be compressed.",
|
||||||
"type": "java.lang.Boolean",
|
"defaultValue": "false"
|
||||||
"description": "Enables the request sent by Feign to be compressed.",
|
}
|
||||||
"defaultValue": "false"
|
]}
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|||||||
-58
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2015 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;
|
|
||||||
|
|
||||||
import feign.codec.Encoder;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
|
||||||
import org.springframework.cloud.openfeign.support.PageableSpringEncoder;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Spencer Gibb
|
|
||||||
*/
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
|
||||||
@SpringBootTest(classes = EnableFeignClientsSpringDataTests.PlainConfiguration.class)
|
|
||||||
@DirtiesContext
|
|
||||||
public class EnableFeignClientsSpringDataTests {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private FeignContext feignContext;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void encoderDefaultCorrect() {
|
|
||||||
|
|
||||||
PageableSpringEncoder.class
|
|
||||||
.cast(this.feignContext.getInstance("foo", Encoder.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@Import({ PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class,
|
|
||||||
FeignAutoConfiguration.class })
|
|
||||||
protected static class PlainConfiguration {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+30
-40
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2015 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,10 +12,24 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
||||||
|
import org.springframework.cloud.openfeign.support.SpringEncoder;
|
||||||
|
import org.springframework.cloud.openfeign.support.SpringMvcContract;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
import feign.Contract;
|
import feign.Contract;
|
||||||
import feign.Feign;
|
import feign.Feign;
|
||||||
import feign.Logger;
|
import feign.Logger;
|
||||||
@@ -23,74 +37,50 @@ import feign.codec.Decoder;
|
|||||||
import feign.codec.Encoder;
|
import feign.codec.Encoder;
|
||||||
import feign.optionals.OptionalDecoder;
|
import feign.optionals.OptionalDecoder;
|
||||||
import feign.slf4j.Slf4jLogger;
|
import feign.slf4j.Slf4jLogger;
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import org.springframework.boot.WebApplicationType;
|
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
|
||||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
|
||||||
import org.springframework.cloud.openfeign.support.SpringEncoder;
|
|
||||||
import org.springframework.cloud.openfeign.support.SpringMvcContract;
|
|
||||||
import org.springframework.cloud.test.ClassPathExclusions;
|
|
||||||
import org.springframework.cloud.test.ModifiedClassPathRunner;
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
*/
|
*/
|
||||||
@RunWith(ModifiedClassPathRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ClassPathExclusions({ "spring-data-commons-*.jar" })
|
@SpringBootTest(classes = EnableFeignClientsTests.PlainConfiguration.class)
|
||||||
|
@DirtiesContext
|
||||||
public class EnableFeignClientsTests {
|
public class EnableFeignClientsTests {
|
||||||
|
|
||||||
private ConfigurableApplicationContext context;
|
@Autowired
|
||||||
|
private FeignContext feignContext;
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
context = new SpringApplicationBuilder().web(WebApplicationType.NONE)
|
|
||||||
.properties("debug=true", "feign.httpclient.enabled=false")
|
|
||||||
.sources(EnableFeignClientsTests.PlainConfiguration.class).run();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() {
|
|
||||||
if (context != null) {
|
|
||||||
context.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void decoderDefaultCorrect() {
|
public void decoderDefaultCorrect() {
|
||||||
OptionalDecoder.class.cast(this.context.getBeansOfType(Decoder.class).get(0));
|
OptionalDecoder.class
|
||||||
|
.cast(this.feignContext.getInstance("foo", Decoder.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void encoderDefaultCorrect() {
|
public void encoderDefaultCorrect() {
|
||||||
SpringEncoder.class.cast(this.context.getBeansOfType(Encoder.class).get(0));
|
SpringEncoder.class.cast(this.feignContext.getInstance("foo", Encoder.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void loggerDefaultCorrect() {
|
public void loggerDefaultCorrect() {
|
||||||
Slf4jLogger.class.cast(this.context.getBeansOfType(Logger.class).get(0));
|
Slf4jLogger.class.cast(this.feignContext.getInstance("foo", Logger.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void contractDefaultCorrect() {
|
public void contractDefaultCorrect() {
|
||||||
SpringMvcContract.class.cast(this.context.getBeansOfType(Contract.class).get(0));
|
SpringMvcContract.class
|
||||||
|
.cast(this.feignContext.getInstance("foo", Contract.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void builderDefaultCorrect() {
|
public void builderDefaultCorrect() {
|
||||||
Feign.Builder.class.cast(this.context.getBeansOfType(Feign.Builder.class).get(0));
|
Feign.Builder.class
|
||||||
|
.cast(this.feignContext.getInstance("foo", Feign.Builder.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import({ ArchaiusAutoConfiguration.class, FeignAutoConfiguration.class })
|
@Import({ PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class,
|
||||||
|
FeignAutoConfiguration.class })
|
||||||
protected static class PlainConfiguration {
|
protected static class PlainConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-18
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -25,18 +25,16 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
import org.springframework.cloud.openfeign.testclients.TestClient;
|
import org.springframework.cloud.openfeign.testclients.TestClient;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sven Döring
|
* @author Sven Döring
|
||||||
*/
|
*/
|
||||||
@@ -67,14 +65,14 @@ public class FeignClientBuilderTests {
|
|||||||
fieldName);
|
fieldName);
|
||||||
ReflectionUtils.makeAccessible(field);
|
ReflectionUtils.makeAccessible(field);
|
||||||
final Object value = ReflectionUtils.getField(field, factoryBean);
|
final Object value = ReflectionUtils.getField(field, factoryBean);
|
||||||
assertThat(value).as("Expected value for the field '" + fieldName + "':")
|
Assert.assertEquals("Expected value for the field '" + fieldName + "':",
|
||||||
.isEqualTo(expectedValue);
|
expectedValue, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
this.applicationContext = Mockito.mock(ApplicationContext.class);
|
this.applicationContext = Mockito.mock(ApplicationContext.class);
|
||||||
this.feignClientBuilder = new FeignClientBuilder(this.applicationContext);
|
this.feignClientBuilder = new FeignClientBuilder(applicationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -93,21 +91,20 @@ public class FeignClientBuilderTests {
|
|||||||
// on this builder class.
|
// on this builder class.
|
||||||
// (2) Or a new field was added and the builder class has to be extended with this
|
// (2) Or a new field was added and the builder class has to be extended with this
|
||||||
// new field.
|
// new field.
|
||||||
assertThat(methodNames).containsExactly("contextId", "decode404", "fallback",
|
Assert.assertThat(methodNames, Matchers.contains("decode404", "fallback",
|
||||||
"fallbackFactory", "name", "path", "url");
|
"fallbackFactory", "name", "path", "url"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void forType_preinitializedBuilder() {
|
public void forType_preinitializedBuilder() {
|
||||||
// when:
|
// when:
|
||||||
final FeignClientBuilder.Builder builder = this.feignClientBuilder
|
final FeignClientBuilder.Builder builder = feignClientBuilder
|
||||||
.forType(FeignClientBuilderTests.class, "TestClient");
|
.forType(FeignClientBuilderTests.class, "TestClient");
|
||||||
|
|
||||||
// then:
|
// then:
|
||||||
assertFactoryBeanField(builder, "applicationContext", this.applicationContext);
|
assertFactoryBeanField(builder, "applicationContext", applicationContext);
|
||||||
assertFactoryBeanField(builder, "type", FeignClientBuilderTests.class);
|
assertFactoryBeanField(builder, "type", FeignClientBuilderTests.class);
|
||||||
assertFactoryBeanField(builder, "name", "TestClient");
|
assertFactoryBeanField(builder, "name", "TestClient");
|
||||||
assertFactoryBeanField(builder, "contextId", "TestClient");
|
|
||||||
|
|
||||||
// and:
|
// and:
|
||||||
assertFactoryBeanField(builder, "url",
|
assertFactoryBeanField(builder, "url",
|
||||||
@@ -125,13 +122,13 @@ public class FeignClientBuilderTests {
|
|||||||
@Test
|
@Test
|
||||||
public void forType_allFieldsSetOnBuilder() {
|
public void forType_allFieldsSetOnBuilder() {
|
||||||
// when:
|
// when:
|
||||||
final FeignClientBuilder.Builder builder = this.feignClientBuilder
|
final FeignClientBuilder.Builder builder = feignClientBuilder
|
||||||
.forType(FeignClientBuilderTests.class, "TestClient").decode404(true)
|
.forType(FeignClientBuilderTests.class, "TestClient").decode404(true)
|
||||||
.fallback(Object.class).fallbackFactory(Object.class).path("Path/")
|
.fallback(Object.class).fallbackFactory(Object.class).path("Path/")
|
||||||
.url("Url/");
|
.url("Url/");
|
||||||
|
|
||||||
// then:
|
// then:
|
||||||
assertFactoryBeanField(builder, "applicationContext", this.applicationContext);
|
assertFactoryBeanField(builder, "applicationContext", applicationContext);
|
||||||
assertFactoryBeanField(builder, "type", FeignClientBuilderTests.class);
|
assertFactoryBeanField(builder, "type", FeignClientBuilderTests.class);
|
||||||
assertFactoryBeanField(builder, "name", "TestClient");
|
assertFactoryBeanField(builder, "name", "TestClient");
|
||||||
|
|
||||||
@@ -146,17 +143,16 @@ public class FeignClientBuilderTests {
|
|||||||
@Test
|
@Test
|
||||||
public void forType_build() {
|
public void forType_build() {
|
||||||
// given:
|
// given:
|
||||||
Mockito.when(this.applicationContext.getBean(FeignContext.class))
|
Mockito.when(applicationContext.getBean(FeignContext.class))
|
||||||
.thenThrow(new ClosedFileSystemException()); // throw an unusual exception
|
.thenThrow(new ClosedFileSystemException()); // throw an unusual exception
|
||||||
// in the
|
// in the
|
||||||
// FeignClientFactoryBean
|
// FeignClientFactoryBean
|
||||||
final FeignClientBuilder.Builder builder = this.feignClientBuilder
|
final FeignClientBuilder.Builder builder = feignClientBuilder
|
||||||
.forType(TestClient.class, "TestClient");
|
.forType(TestClient.class, "TestClient");
|
||||||
|
|
||||||
// expect: 'the build will fail right after calling build() with the mocked
|
// expect: 'the build will fail right after calling build() with the mocked
|
||||||
// unusual exception'
|
// unusual exception'
|
||||||
this.thrown.expect(Matchers.isA(ClosedFileSystemException.class));
|
thrown.expect(Matchers.isA(ClosedFileSystemException.class));
|
||||||
builder.build();
|
builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-21
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,14 +16,16 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
@@ -40,43 +42,33 @@ public class FeignClientFactoryTests {
|
|||||||
getSpec("bar", BarConfig.class)));
|
getSpec("bar", BarConfig.class)));
|
||||||
|
|
||||||
Foo foo = context.getInstance("foo", Foo.class);
|
Foo foo = context.getInstance("foo", Foo.class);
|
||||||
assertThat(foo).as("foo was null").isNotNull();
|
assertThat("foo was null", foo, is(notNullValue()));
|
||||||
|
|
||||||
Bar bar = context.getInstance("bar", Bar.class);
|
Bar bar = context.getInstance("bar", Bar.class);
|
||||||
assertThat(bar).as("bar was null").isNotNull();
|
assertThat("bar was null", bar, is(notNullValue()));
|
||||||
|
|
||||||
Bar foobar = context.getInstance("foo", Bar.class);
|
Bar foobar = context.getInstance("foo", Bar.class);
|
||||||
assertThat(foobar).as("bar was not null").isNull();
|
assertThat("bar was not null", foobar, is(nullValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private FeignClientSpecification getSpec(String name, Class<?> configClass) {
|
private FeignClientSpecification getSpec(String name, Class<?> configClass) {
|
||||||
return new FeignClientSpecification(name, new Class[] { configClass });
|
return new FeignClientSpecification(name, new Class[]{configClass});
|
||||||
}
|
}
|
||||||
|
|
||||||
static class FooConfig {
|
static class FooConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
Foo foo() {
|
Foo foo() {
|
||||||
return new Foo();
|
return new Foo();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
static class Foo{}
|
||||||
static class Foo {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class BarConfig {
|
static class BarConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
Bar bar() {
|
Bar bar() {
|
||||||
return new Bar();
|
return new Bar();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
static class Bar{}
|
||||||
static class Bar {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+51
-59
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,10 +12,31 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
||||||
|
import org.springframework.cloud.openfeign.support.SpringEncoder;
|
||||||
|
import org.springframework.cloud.openfeign.support.SpringMvcContract;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
import feign.Contract;
|
import feign.Contract;
|
||||||
import feign.Feign;
|
import feign.Feign;
|
||||||
import feign.Logger;
|
import feign.Logger;
|
||||||
@@ -31,24 +52,6 @@ import feign.codec.ErrorDecoder;
|
|||||||
import feign.hystrix.HystrixFeign;
|
import feign.hystrix.HystrixFeign;
|
||||||
import feign.optionals.OptionalDecoder;
|
import feign.optionals.OptionalDecoder;
|
||||||
import feign.slf4j.Slf4jLogger;
|
import feign.slf4j.Slf4jLogger;
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
|
|
||||||
import org.springframework.cloud.openfeign.support.PageableSpringEncoder;
|
|
||||||
import org.springframework.cloud.openfeign.support.SpringMvcContract;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
@@ -69,8 +72,8 @@ public class FeignClientOverrideDefaultsTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clientsAvailable() {
|
public void clientsAvailable() {
|
||||||
assertThat(this.foo).isNotNull();
|
assertNotNull(this.foo);
|
||||||
assertThat(this.bar).isNotNull();
|
assertNotNull(this.bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -82,7 +85,7 @@ public class FeignClientOverrideDefaultsTests {
|
|||||||
@Test
|
@Test
|
||||||
public void overrideEncoder() {
|
public void overrideEncoder() {
|
||||||
Encoder.Default.class.cast(this.context.getInstance("foo", Encoder.class));
|
Encoder.Default.class.cast(this.context.getInstance("foo", Encoder.class));
|
||||||
PageableSpringEncoder.class.cast(this.context.getInstance("bar", Encoder.class));
|
SpringEncoder.class.cast(this.context.getInstance("bar", Encoder.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -99,62 +102,45 @@ public class FeignClientOverrideDefaultsTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void overrideLoggerLevel() {
|
public void overrideLoggerLevel() {
|
||||||
assertThat(this.context.getInstance("foo", Logger.Level.class)).isNull();
|
assertNull(this.context.getInstance("foo", Logger.Level.class));
|
||||||
assertThat(this.context.getInstance("bar", Logger.Level.class))
|
assertEquals(Logger.Level.HEADERS,
|
||||||
.isEqualTo(Logger.Level.HEADERS);
|
this.context.getInstance("bar", Logger.Level.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void overrideRetryer() {
|
public void overrideRetryer() {
|
||||||
assertThat(this.context.getInstance("foo", Retryer.class))
|
assertEquals(Retryer.NEVER_RETRY, this.context.getInstance("foo", Retryer.class));
|
||||||
.isEqualTo(Retryer.NEVER_RETRY);
|
|
||||||
Retryer.Default.class.cast(this.context.getInstance("bar", Retryer.class));
|
Retryer.Default.class.cast(this.context.getInstance("bar", Retryer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void overrideErrorDecoder() {
|
public void overrideErrorDecoder() {
|
||||||
assertThat(this.context.getInstance("foo", ErrorDecoder.class)).isNull();
|
assertNull(this.context.getInstance("foo", ErrorDecoder.class));
|
||||||
ErrorDecoder.Default.class
|
ErrorDecoder.Default.class
|
||||||
.cast(this.context.getInstance("bar", ErrorDecoder.class));
|
.cast(this.context.getInstance("bar", ErrorDecoder.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void overrideBuilder() {
|
public void overrideBuilder() {
|
||||||
HystrixFeign.Builder.class
|
HystrixFeign.Builder.class.cast(this.context.getInstance("foo", Feign.Builder.class));
|
||||||
.cast(this.context.getInstance("foo", Feign.Builder.class));
|
Feign.Builder.class
|
||||||
Feign.Builder.class.cast(this.context.getInstance("bar", Feign.Builder.class));
|
.cast(this.context.getInstance("bar", Feign.Builder.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void overrideRequestOptions() {
|
public void overrideRequestOptions() {
|
||||||
assertThat(this.context.getInstance("foo", Request.Options.class)).isNull();
|
assertNull(this.context.getInstance("foo", Request.Options.class));
|
||||||
Request.Options options = this.context.getInstance("bar", Request.Options.class);
|
Request.Options options = this.context.getInstance("bar", Request.Options.class);
|
||||||
assertThat(options.connectTimeoutMillis()).isEqualTo(1);
|
assertEquals(1, options.connectTimeoutMillis());
|
||||||
assertThat(options.readTimeoutMillis()).isEqualTo(1);
|
assertEquals(1, options.readTimeoutMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addRequestInterceptor() {
|
public void addRequestInterceptor() {
|
||||||
assertThat(this.context.getInstances("foo", RequestInterceptor.class).size())
|
assertEquals(1,
|
||||||
.isEqualTo(1);
|
this.context.getInstances("foo", RequestInterceptor.class).size());
|
||||||
assertThat(this.context.getInstances("bar", RequestInterceptor.class).size())
|
assertEquals(2,
|
||||||
.isEqualTo(2);
|
this.context.getInstances("bar", RequestInterceptor.class).size());
|
||||||
}
|
|
||||||
|
|
||||||
@FeignClient(name = "foo", url = "http://foo", configuration = FooConfiguration.class)
|
|
||||||
interface FooClient {
|
|
||||||
|
|
||||||
@RequestLine("GET /")
|
|
||||||
String get();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@FeignClient(name = "bar", url = "http://bar", configuration = BarConfiguration.class)
|
|
||||||
interface BarClient {
|
|
||||||
|
|
||||||
@RequestMapping(value = "/", method = RequestMethod.GET)
|
|
||||||
String get();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@@ -162,7 +148,6 @@ public class FeignClientOverrideDefaultsTests {
|
|||||||
@Import({ PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class,
|
@Import({ PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class,
|
||||||
FeignAutoConfiguration.class })
|
FeignAutoConfiguration.class })
|
||||||
protected static class TestConfiguration {
|
protected static class TestConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
RequestInterceptor defaultRequestInterceptor() {
|
RequestInterceptor defaultRequestInterceptor() {
|
||||||
return new RequestInterceptor() {
|
return new RequestInterceptor() {
|
||||||
@@ -171,11 +156,16 @@ public class FeignClientOverrideDefaultsTests {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FeignClient(name = "foo", url = "http://foo", configuration = FooConfiguration.class)
|
||||||
|
interface FooClient {
|
||||||
|
@RequestLine("GET /")
|
||||||
|
String get();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FooConfiguration {
|
public static class FooConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Decoder feignDecoder() {
|
public Decoder feignDecoder() {
|
||||||
return new Decoder.Default();
|
return new Decoder.Default();
|
||||||
@@ -200,11 +190,15 @@ public class FeignClientOverrideDefaultsTests {
|
|||||||
public Feign.Builder feignBuilder() {
|
public Feign.Builder feignBuilder() {
|
||||||
return HystrixFeign.builder();
|
return HystrixFeign.builder();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FeignClient(name = "bar", url = "http://bar", configuration = BarConfiguration.class)
|
||||||
|
interface BarClient {
|
||||||
|
@RequestMapping(value = "/", method = RequestMethod.GET)
|
||||||
|
String get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BarConfiguration {
|
public static class BarConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
Logger.Level feignLevel() {
|
Logger.Level feignLevel() {
|
||||||
return Logger.Level.HEADERS;
|
return Logger.Level.HEADERS;
|
||||||
@@ -229,7 +223,5 @@ public class FeignClientOverrideDefaultsTests {
|
|||||||
RequestInterceptor feignRequestInterceptor() {
|
RequestInterceptor feignRequestInterceptor() {
|
||||||
return new BasicAuthRequestInterceptor("user", "pass");
|
return new BasicAuthRequestInterceptor("user", "pass");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-57
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,13 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import feign.Request;
|
|
||||||
import feign.RequestInterceptor;
|
import feign.RequestInterceptor;
|
||||||
import feign.RequestTemplate;
|
import feign.RequestTemplate;
|
||||||
import feign.RetryableException;
|
import feign.RetryableException;
|
||||||
@@ -32,15 +25,13 @@ import feign.codec.Encoder;
|
|||||||
import feign.codec.ErrorDecoder;
|
import feign.codec.ErrorDecoder;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
@@ -50,16 +41,19 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import java.lang.reflect.Type;
|
||||||
import static org.assertj.core.api.Assertions.fail;
|
import java.util.Collections;
|
||||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Eko Kurniawan Khannedy
|
* @author Eko Kurniawan Khannedy
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@SpringBootTest(classes = FeignClientUsingPropertiesTests.Application.class, webEnvironment = RANDOM_PORT)
|
@SpringBootTest(classes = FeignClientUsingPropertiesTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||||
@TestPropertySource("classpath:feign-properties.properties")
|
@TestPropertySource("classpath:feign-properties.properties")
|
||||||
@DirtiesContext
|
@DirtiesContext
|
||||||
public class FeignClientUsingPropertiesTests {
|
public class FeignClientUsingPropertiesTests {
|
||||||
@@ -80,41 +74,38 @@ public class FeignClientUsingPropertiesTests {
|
|||||||
private FeignClientFactoryBean formFactoryBean;
|
private FeignClientFactoryBean formFactoryBean;
|
||||||
|
|
||||||
public FeignClientUsingPropertiesTests() {
|
public FeignClientUsingPropertiesTests() {
|
||||||
this.fooFactoryBean = new FeignClientFactoryBean();
|
fooFactoryBean = new FeignClientFactoryBean();
|
||||||
this.fooFactoryBean.setContextId("foo");
|
fooFactoryBean.setName("foo");
|
||||||
this.fooFactoryBean.setType(FeignClientFactoryBean.class);
|
fooFactoryBean.setType(FeignClientFactoryBean.class);
|
||||||
|
|
||||||
this.barFactoryBean = new FeignClientFactoryBean();
|
barFactoryBean = new FeignClientFactoryBean();
|
||||||
this.barFactoryBean.setContextId("bar");
|
barFactoryBean.setName("bar");
|
||||||
this.barFactoryBean.setType(FeignClientFactoryBean.class);
|
barFactoryBean.setType(FeignClientFactoryBean.class);
|
||||||
|
|
||||||
this.formFactoryBean = new FeignClientFactoryBean();
|
formFactoryBean = new FeignClientFactoryBean();
|
||||||
this.formFactoryBean.setContextId("form");
|
formFactoryBean.setName("form");
|
||||||
this.formFactoryBean.setType(FeignClientFactoryBean.class);
|
formFactoryBean.setType(FeignClientFactoryBean.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FooClient fooClient() {
|
public FooClient fooClient() {
|
||||||
this.fooFactoryBean.setApplicationContext(this.applicationContext);
|
fooFactoryBean.setApplicationContext(applicationContext);
|
||||||
return this.fooFactoryBean.feign(this.context).target(FooClient.class,
|
return fooFactoryBean.feign(context).target(FooClient.class, "http://localhost:" + this.port);
|
||||||
"http://localhost:" + this.port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BarClient barClient() {
|
public BarClient barClient() {
|
||||||
this.barFactoryBean.setApplicationContext(this.applicationContext);
|
barFactoryBean.setApplicationContext(applicationContext);
|
||||||
return this.barFactoryBean.feign(this.context).target(BarClient.class,
|
return barFactoryBean.feign(context).target(BarClient.class, "http://localhost:" + this.port);
|
||||||
"http://localhost:" + this.port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FormClient formClient() {
|
public FormClient formClient() {
|
||||||
this.formFactoryBean.setApplicationContext(this.applicationContext);
|
formFactoryBean.setApplicationContext(applicationContext);
|
||||||
return this.formFactoryBean.feign(this.context).target(FormClient.class,
|
return formFactoryBean.feign(context).target(FormClient.class, "http://localhost:" + this.port);
|
||||||
"http://localhost:" + this.port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFoo() {
|
public void testFoo() {
|
||||||
String response = fooClient().foo();
|
String response = fooClient().foo();
|
||||||
assertThat(response).isEqualTo("OK");
|
assertEquals("OK", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = RetryableException.class)
|
@Test(expected = RetryableException.class)
|
||||||
@@ -127,26 +118,25 @@ public class FeignClientUsingPropertiesTests {
|
|||||||
public void testForm() {
|
public void testForm() {
|
||||||
Map<String, String> request = Collections.singletonMap("form", "Data");
|
Map<String, String> request = Collections.singletonMap("form", "Data");
|
||||||
String response = formClient().form(request);
|
String response = formClient().form(request);
|
||||||
assertThat(response).isEqualTo("Data");
|
assertEquals("Data", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected interface FooClient {
|
protected interface FooClient {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/foo")
|
@RequestMapping(method = RequestMethod.GET, value = "/foo")
|
||||||
String foo();
|
String foo();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected interface BarClient {
|
protected interface BarClient {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/bar")
|
@RequestMapping(method = RequestMethod.GET, value = "/bar")
|
||||||
String bar();
|
String bar();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected interface FormClient {
|
protected interface FormClient {
|
||||||
|
|
||||||
@RequestMapping(value = "/form", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
@RequestMapping(value = "/form", method = RequestMethod.POST,
|
||||||
|
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
String form(Map<String, String> form);
|
String form(Map<String, String> form);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -154,16 +144,14 @@ public class FeignClientUsingPropertiesTests {
|
|||||||
@Configuration
|
@Configuration
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@RestController
|
@RestController
|
||||||
@Import(NoSecurityConfiguration.class)
|
|
||||||
protected static class Application {
|
protected static class Application {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/foo")
|
@RequestMapping(method = RequestMethod.GET, value = "/foo")
|
||||||
public String foo(HttpServletRequest request) throws IllegalAccessException {
|
public String foo(HttpServletRequest request) throws IllegalAccessException {
|
||||||
if ("Foo".equals(request.getHeader("Foo"))
|
if ("Foo".equals(request.getHeader("Foo")) &&
|
||||||
&& "Bar".equals(request.getHeader("Bar"))) {
|
"Bar".equals(request.getHeader("Bar"))) {
|
||||||
return "OK";
|
return "OK";
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
throw new IllegalAccessException("It should has Foo and Bar header");
|
throw new IllegalAccessException("It should has Foo and Bar header");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,7 +162,8 @@ public class FeignClientUsingPropertiesTests {
|
|||||||
return "OK";
|
return "OK";
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "/form", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
@RequestMapping(value = "/form", method = RequestMethod.POST,
|
||||||
|
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
public String form(HttpServletRequest request) {
|
public String form(HttpServletRequest request) {
|
||||||
return request.getParameter("form");
|
return request.getParameter("form");
|
||||||
}
|
}
|
||||||
@@ -182,21 +171,17 @@ public class FeignClientUsingPropertiesTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class FooRequestInterceptor implements RequestInterceptor {
|
public static class FooRequestInterceptor implements RequestInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(RequestTemplate template) {
|
public void apply(RequestTemplate template) {
|
||||||
template.header("Foo", "Foo");
|
template.header("Foo", "Foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BarRequestInterceptor implements RequestInterceptor {
|
public static class BarRequestInterceptor implements RequestInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(RequestTemplate template) {
|
public void apply(RequestTemplate template) {
|
||||||
template.header("Bar", "Bar");
|
template.header("Bar", "Bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NoRetryer implements Retryer {
|
public static class NoRetryer implements Retryer {
|
||||||
@@ -210,29 +195,24 @@ public class FeignClientUsingPropertiesTests {
|
|||||||
public Retryer clone() {
|
public Retryer clone() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DefaultErrorDecoder extends ErrorDecoder.Default {
|
public static class DefaultErrorDecoder extends ErrorDecoder.Default {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FormEncoder implements Encoder {
|
public static class FormEncoder implements Encoder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encode(Object o, Type type, RequestTemplate requestTemplate)
|
public void encode(Object o, Type type, RequestTemplate requestTemplate) throws EncodeException {
|
||||||
throws EncodeException {
|
|
||||||
Map<String, String> form = (Map<String, String>) o;
|
Map<String, String> form = (Map<String, String>) o;
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
form.forEach((key, value) -> {
|
form.forEach((key, value) -> {
|
||||||
builder.append(key + "=" + value + "&");
|
builder.append(key + "=" + value + "&");
|
||||||
});
|
});
|
||||||
|
|
||||||
requestTemplate.header(HttpHeaders.CONTENT_TYPE,
|
requestTemplate.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
||||||
MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
requestTemplate.body(builder.toString());
|
||||||
requestTemplate.body(Request.Body.bodyTemplate(builder.toString(), UTF_8));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-24
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
@@ -19,7 +20,6 @@ package org.springframework.cloud.openfeign;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -27,7 +27,8 @@ import org.springframework.mock.env.MockEnvironment;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
@@ -40,6 +41,7 @@ public class FeignClientsRegistrarTests {
|
|||||||
testGetName("http://bad_hostname");
|
testGetName("http://bad_hostname");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void badNameHttpsPrefix() {
|
public void badNameHttpsPrefix() {
|
||||||
testGetName("https://bad_hostname");
|
testGetName("https://bad_hostname");
|
||||||
@@ -58,19 +60,19 @@ public class FeignClientsRegistrarTests {
|
|||||||
@Test
|
@Test
|
||||||
public void goodName() {
|
public void goodName() {
|
||||||
String name = testGetName("good-name");
|
String name = testGetName("good-name");
|
||||||
assertThat(name).as("name was wrong").isEqualTo("good-name");
|
assertThat("name was wrong", name, is("good-name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void goodNameHttpPrefix() {
|
public void goodNameHttpPrefix() {
|
||||||
String name = testGetName("http://good-name");
|
String name = testGetName("http://good-name");
|
||||||
assertThat(name).as("name was wrong").isEqualTo("http://good-name");
|
assertThat("name was wrong", name, is("http://good-name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void goodNameHttpsPrefix() {
|
public void goodNameHttpsPrefix() {
|
||||||
String name = testGetName("https://goodname");
|
String name = testGetName("https://goodname");
|
||||||
assertThat(name).as("name was wrong").isEqualTo("https://goodname");
|
assertThat("name was wrong", name, is("https://goodname"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String testGetName(String name) {
|
private String testGetName(String name) {
|
||||||
@@ -79,6 +81,7 @@ public class FeignClientsRegistrarTests {
|
|||||||
return registrar.getName(Collections.<String, Object>singletonMap("name", name));
|
return registrar.getName(Collections.<String, Object>singletonMap("name", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testFallback() {
|
public void testFallback() {
|
||||||
new AnnotationConfigApplicationContext(FallbackTestConfig.class);
|
new AnnotationConfigApplicationContext(FallbackTestConfig.class);
|
||||||
@@ -89,35 +92,30 @@ public class FeignClientsRegistrarTests {
|
|||||||
new AnnotationConfigApplicationContext(FallbackFactoryTestConfig.class);
|
new AnnotationConfigApplicationContext(FallbackFactoryTestConfig.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@EnableFeignClients(clients = { FeignClientsRegistrarTests.FallbackClient.class})
|
||||||
|
protected static class FallbackTestConfig {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@FeignClient(name = "fallbackTestClient", url = "http://localhost:8080/", fallback = FallbackClient.class)
|
@FeignClient(name = "fallbackTestClient", url = "http://localhost:8080/", fallback = FallbackClient.class)
|
||||||
protected interface FallbackClient {
|
protected interface FallbackClient {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||||
String fallbackTest();
|
String fallbackTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@EnableFeignClients(clients = { FeignClientsRegistrarTests.FallbackFactoryClient.class})
|
||||||
|
protected static class FallbackFactoryTestConfig {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FeignClient(name = "fallbackFactoryTestClient", url = "http://localhost:8081/", fallbackFactory = FallbackFactoryClient.class)
|
@FeignClient(name = "fallbackFactoryTestClient", url = "http://localhost:8081/", fallbackFactory = FallbackFactoryClient.class)
|
||||||
protected interface FallbackFactoryClient {
|
protected interface FallbackFactoryClient {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||||
String fallbackFactoryTest();
|
String fallbackFactoryTest();
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableAutoConfiguration
|
|
||||||
@EnableFeignClients(clients = { FeignClientsRegistrarTests.FallbackClient.class })
|
|
||||||
protected static class FallbackTestConfig {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableAutoConfiguration
|
|
||||||
@EnableFeignClients(clients = {
|
|
||||||
FeignClientsRegistrarTests.FallbackFactoryClient.class })
|
|
||||||
protected static class FallbackFactoryTestConfig {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-9
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,18 +12,15 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import feign.Client;
|
|
||||||
import feign.RequestInterceptor;
|
|
||||||
import feign.httpclient.ApacheHttpClient;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
@@ -38,6 +35,10 @@ import org.springframework.cloud.test.ModifiedClassPathRunner;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import feign.Client;
|
||||||
|
import feign.RequestInterceptor;
|
||||||
|
import feign.httpclient.ApacheHttpClient;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,9 +90,7 @@ public class FeignCompressionTests {
|
|||||||
* a bean here of type ApacheHttpClient so that the configuration will be
|
* a bean here of type ApacheHttpClient so that the configuration will be
|
||||||
* loaded correctly.
|
* loaded correctly.
|
||||||
*/
|
*/
|
||||||
return (ApacheHttpClient) this.client;
|
return (ApacheHttpClient) client;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
+20
-35
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,16 +12,14 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContextSpi;
|
import javax.net.ssl.SSLContextSpi;
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
import org.apache.http.config.Lookup;
|
import org.apache.http.config.Lookup;
|
||||||
import org.apache.http.conn.HttpClientConnectionManager;
|
import org.apache.http.conn.HttpClientConnectionManager;
|
||||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||||
@@ -30,8 +28,6 @@ import org.junit.After;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.boot.WebApplicationType;
|
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
||||||
import org.springframework.cloud.test.ClassPathExclusions;
|
import org.springframework.cloud.test.ClassPathExclusions;
|
||||||
@@ -39,7 +35,8 @@ import org.springframework.cloud.test.ModifiedClassPathRunner;
|
|||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ryan Baxter
|
* @author Ryan Baxter
|
||||||
@@ -52,47 +49,35 @@ public class FeignHttpClientConfigurationTests {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
this.context = new SpringApplicationBuilder()
|
context = new SpringApplicationBuilder().properties("debug=true","feign.httpclient.disableSslValidation=true").web(false)
|
||||||
.properties("debug=true", "feign.httpclient.disableSslValidation=true")
|
.sources(HttpClientConfiguration.class, FeignAutoConfiguration.class).run();
|
||||||
.web(WebApplicationType.NONE)
|
|
||||||
.sources(HttpClientConfiguration.class, FeignAutoConfiguration.class)
|
|
||||||
.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
if (this.context != null) {
|
if(context != null) {
|
||||||
this.context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void disableSslTest() throws Exception {
|
public void disableSslTest() throws Exception {
|
||||||
HttpClientConnectionManager connectionManager = this.context
|
HttpClientConnectionManager connectionManager = context.getBean(HttpClientConnectionManager.class);
|
||||||
.getBean(HttpClientConnectionManager.class);
|
Lookup<ConnectionSocketFactory> socketFactoryRegistry = getConnectionSocketFactoryLookup(connectionManager);
|
||||||
Lookup<ConnectionSocketFactory> socketFactoryRegistry = getConnectionSocketFactoryLookup(
|
assertNotNull(socketFactoryRegistry.lookup("https"));
|
||||||
connectionManager);
|
assertNull(this.getX509TrustManager(socketFactoryRegistry).getAcceptedIssuers());
|
||||||
assertThat(socketFactoryRegistry.lookup("https")).isNotNull();
|
|
||||||
assertThat(this.getX509TrustManager(socketFactoryRegistry).getAcceptedIssuers())
|
|
||||||
.isNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Lookup<ConnectionSocketFactory> getConnectionSocketFactoryLookup(
|
private Lookup<ConnectionSocketFactory> getConnectionSocketFactoryLookup(HttpClientConnectionManager connectionManager) {
|
||||||
HttpClientConnectionManager connectionManager) {
|
DefaultHttpClientConnectionOperator connectionOperator = (DefaultHttpClientConnectionOperator)this.getField(connectionManager, "connectionOperator");
|
||||||
DefaultHttpClientConnectionOperator connectionOperator = (DefaultHttpClientConnectionOperator) this
|
return (Lookup)this.getField(connectionOperator, "socketFactoryRegistry");
|
||||||
.getField(connectionManager, "connectionOperator");
|
|
||||||
return (Lookup) this.getField(connectionOperator, "socketFactoryRegistry");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private X509TrustManager getX509TrustManager(
|
private X509TrustManager getX509TrustManager(Lookup<ConnectionSocketFactory> socketFactoryRegistry) {
|
||||||
Lookup<ConnectionSocketFactory> socketFactoryRegistry) {
|
ConnectionSocketFactory connectionSocketFactory = (ConnectionSocketFactory)socketFactoryRegistry.lookup("https");
|
||||||
ConnectionSocketFactory connectionSocketFactory = (ConnectionSocketFactory) socketFactoryRegistry
|
SSLSocketFactory sslSocketFactory = (SSLSocketFactory)this.getField(connectionSocketFactory, "socketfactory");
|
||||||
.lookup("https");
|
SSLContextSpi sslContext = (SSLContextSpi)this.getField(sslSocketFactory, "context");
|
||||||
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) this
|
return (X509TrustManager)this.getField(sslContext, "trustManager");
|
||||||
.getField(connectionSocketFactory, "socketfactory");
|
|
||||||
SSLContextSpi sslContext = (SSLContextSpi) this.getField(sslSocketFactory,
|
|
||||||
"context");
|
|
||||||
return (X509TrustManager) this.getField(sslContext, "trustManager");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> Object getField(Object target, String name) {
|
protected <T> Object getField(Object target, String name) {
|
||||||
|
|||||||
+51
-67
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,29 +12,30 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import feign.Client;
|
|
||||||
import feign.Feign;
|
|
||||||
import feign.Target;
|
|
||||||
import feign.httpclient.ApacheHttpClient;
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
@@ -43,14 +44,16 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import feign.Client;
|
||||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
|
import feign.Feign;
|
||||||
|
import feign.Target;
|
||||||
|
import feign.httpclient.ApacheHttpClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@SpringBootTest(classes = FeignHttpClientUrlTests.TestConfig.class, webEnvironment = DEFINED_PORT, value = {
|
@SpringBootTest(classes = FeignHttpClientUrlTests.TestConfig.class, webEnvironment = WebEnvironment.DEFINED_PORT, value = {
|
||||||
"spring.application.name=feignclienturltest", "feign.hystrix.enabled=false",
|
"spring.application.name=feignclienturltest", "feign.hystrix.enabled=false",
|
||||||
"feign.okhttp.enabled=false" })
|
"feign.okhttp.enabled=false" })
|
||||||
@DirtiesContext
|
@DirtiesContext
|
||||||
@@ -58,15 +61,6 @@ public class FeignHttpClientUrlTests {
|
|||||||
|
|
||||||
static int port;
|
static int port;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
BeanUrlClientNoProtocol beanClientNoProtocol;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UrlClient urlClient;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private BeanUrlClient beanClient;
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeClass() {
|
public static void beforeClass() {
|
||||||
port = SocketUtils.findAvailableTcpPort();
|
port = SocketUtils.findAvailableTcpPort();
|
||||||
@@ -78,62 +72,37 @@ public class FeignHttpClientUrlTests {
|
|||||||
System.clearProperty("server.port");
|
System.clearProperty("server.port");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Autowired
|
||||||
public void testUrlHttpClient() {
|
private UrlClient urlClient;
|
||||||
assertThat(this.urlClient).as("UrlClient was null").isNotNull();
|
|
||||||
Hello hello = this.urlClient.getHello();
|
|
||||||
assertThat(hello).as("hello was null").isNotNull();
|
|
||||||
assertThat(hello).as("first hello didn't match")
|
|
||||||
.isEqualTo(new Hello("hello world 1"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Autowired
|
||||||
public void testBeanUrl() {
|
private BeanUrlClient beanClient;
|
||||||
Hello hello = this.beanClient.getHello();
|
|
||||||
assertThat(hello).as("hello was null").isNotNull();
|
|
||||||
assertThat(hello).as("first hello didn't match")
|
|
||||||
.isEqualTo(new Hello("hello world 1"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Autowired BeanUrlClientNoProtocol beanClientNoProtocol;
|
||||||
public void testBeanUrlNoProtocol() {
|
|
||||||
Hello hello = this.beanClientNoProtocol.getHello();
|
|
||||||
assertThat(hello).as("hello was null").isNotNull();
|
|
||||||
assertThat(hello).as("first hello didn't match")
|
|
||||||
.isEqualTo(new Hello("hello world 1"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// this tests that
|
// this tests that
|
||||||
@FeignClient(name = "localappurl", url = "http://localhost:${server.port}/")
|
@FeignClient(name = "localappurl", url = "http://localhost:${server.port}/")
|
||||||
protected interface UrlClient {
|
protected interface UrlClient {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||||
Hello getHello();
|
Hello getHello();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FeignClient(name = "beanappurl", url = "#{SERVER_URL}path")
|
@FeignClient(name = "beanappurl", url = "#{SERVER_URL}path")
|
||||||
protected interface BeanUrlClient {
|
protected interface BeanUrlClient {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||||
Hello getHello();
|
Hello getHello();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FeignClient(name = "beanappurlnoprotocol", url = "#{SERVER_URL_NO_PROTOCOL}path")
|
@FeignClient(name = "beanappurlnoprotocol", url = "#{SERVER_URL_NO_PROTOCOL}path")
|
||||||
protected interface BeanUrlClientNoProtocol {
|
protected interface BeanUrlClientNoProtocol {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||||
Hello getHello();
|
Hello getHello();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@RestController
|
@RestController
|
||||||
@EnableFeignClients(clients = { UrlClient.class, BeanUrlClient.class,
|
@EnableFeignClients(clients = { UrlClient.class, BeanUrlClient.class, BeanUrlClientNoProtocol.class })
|
||||||
BeanUrlClientNoProtocol.class })
|
|
||||||
@Import(NoSecurityConfiguration.class)
|
|
||||||
protected static class TestConfig {
|
protected static class TestConfig {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||||
@@ -146,12 +115,12 @@ public class FeignHttpClientUrlTests {
|
|||||||
return getHello();
|
return getHello();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "SERVER_URL")
|
@Bean(name="SERVER_URL")
|
||||||
public String serverUrl() {
|
public String serverUrl() {
|
||||||
return "http://localhost:" + port + "/";
|
return "http://localhost:" + port + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "SERVER_URL_NO_PROTOCOL")
|
@Bean(name="SERVER_URL_NO_PROTOCOL")
|
||||||
public String serverUrlNoProtocol() {
|
public String serverUrlNoProtocol() {
|
||||||
return "localhost:" + port + "/";
|
return "localhost:" + port + "/";
|
||||||
}
|
}
|
||||||
@@ -167,8 +136,8 @@ public class FeignHttpClientUrlTests {
|
|||||||
ReflectionUtils.makeAccessible(field);
|
ReflectionUtils.makeAccessible(field);
|
||||||
Client client = (Client) ReflectionUtils.getField(field, feign);
|
Client client = (Client) ReflectionUtils.getField(field, feign);
|
||||||
if (target.name().equals("localappurl")) {
|
if (target.name().equals("localappurl")) {
|
||||||
assertThat(client).isInstanceOf(ApacheHttpClient.class)
|
assertThat("client was wrong type", client,
|
||||||
.as("client was wrong type");
|
is(instanceOf(ApacheHttpClient.class)));
|
||||||
}
|
}
|
||||||
return feign.target(target);
|
return feign.target(target);
|
||||||
}
|
}
|
||||||
@@ -177,8 +146,29 @@ public class FeignHttpClientUrlTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Hello {
|
@Test
|
||||||
|
public void testUrlHttpClient() {
|
||||||
|
assertNotNull("UrlClient was null", this.urlClient);
|
||||||
|
Hello hello = this.urlClient.getHello();
|
||||||
|
assertNotNull("hello was null", hello);
|
||||||
|
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBeanUrl() {
|
||||||
|
Hello hello = this.beanClient.getHello();
|
||||||
|
assertNotNull("hello was null", hello);
|
||||||
|
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBeanUrlNoProtocol() {
|
||||||
|
Hello hello = this.beanClientNoProtocol.getHello();
|
||||||
|
assertNotNull("hello was null", hello);
|
||||||
|
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Hello {
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
public Hello() {
|
public Hello() {
|
||||||
@@ -189,7 +179,7 @@ public class FeignHttpClientUrlTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return this.message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMessage(String message) {
|
public void setMessage(String message) {
|
||||||
@@ -198,21 +188,15 @@ public class FeignHttpClientUrlTests {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) return true;
|
||||||
return true;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Hello that = (Hello) o;
|
Hello that = (Hello) o;
|
||||||
return Objects.equals(this.message, that.message);
|
return Objects.equals(message, that.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(this.message);
|
return Objects.hash(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-34
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2019 the original author or authors.
|
* Copyright 2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
import feign.Logger;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import feign.slf4j.Slf4jLogger;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
@@ -25,7 +26,8 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import feign.Logger;
|
||||||
|
import feign.slf4j.Slf4jLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Venil Noronha
|
* @author Venil Noronha
|
||||||
@@ -34,38 +36,12 @@ public class FeignLoggerFactoryTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDefaultLogger() {
|
public void testDefaultLogger() {
|
||||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleConfiguration1.class);
|
||||||
SampleConfiguration1.class);
|
|
||||||
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
|
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
|
||||||
assertThat(loggerFactory).isNotNull();
|
assertNotNull(loggerFactory);
|
||||||
Logger logger = loggerFactory.create(Object.class);
|
Logger logger = loggerFactory.create(Object.class);
|
||||||
assertThat(logger).isNotNull();
|
assertNotNull(logger);
|
||||||
assertThat(logger instanceof Slf4jLogger).isTrue();
|
assertTrue(logger instanceof Slf4jLogger);
|
||||||
context.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCustomLogger() {
|
|
||||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
|
||||||
SampleConfiguration2.class);
|
|
||||||
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
|
|
||||||
assertThat(loggerFactory).isNotNull();
|
|
||||||
Logger logger = loggerFactory.create(Object.class);
|
|
||||||
assertThat(logger).isNotNull();
|
|
||||||
assertThat(logger instanceof LoggerImpl1).isTrue();
|
|
||||||
context.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCustomLoggerFactory() {
|
|
||||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
|
||||||
SampleConfiguration3.class);
|
|
||||||
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
|
|
||||||
assertThat(loggerFactory).isNotNull();
|
|
||||||
assertThat(loggerFactory instanceof LoggerFactoryImpl).isTrue();
|
|
||||||
Logger logger = loggerFactory.create(Object.class);
|
|
||||||
assertThat(logger).isNotNull();
|
|
||||||
assertThat(logger instanceof LoggerImpl2).isTrue();
|
|
||||||
context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +51,17 @@ public class FeignLoggerFactoryTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCustomLogger() {
|
||||||
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleConfiguration2.class);
|
||||||
|
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
|
||||||
|
assertNotNull(loggerFactory);
|
||||||
|
Logger logger = loggerFactory.create(Object.class);
|
||||||
|
assertNotNull(logger);
|
||||||
|
assertTrue(logger instanceof LoggerImpl1);
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import(FeignClientsConfiguration.class)
|
@Import(FeignClientsConfiguration.class)
|
||||||
protected static class SampleConfiguration2 {
|
protected static class SampleConfiguration2 {
|
||||||
@@ -95,6 +82,18 @@ public class FeignLoggerFactoryTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCustomLoggerFactory() {
|
||||||
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleConfiguration3.class);
|
||||||
|
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
|
||||||
|
assertNotNull(loggerFactory);
|
||||||
|
assertTrue(loggerFactory instanceof LoggerFactoryImpl);
|
||||||
|
Logger logger = loggerFactory.create(Object.class);
|
||||||
|
assertNotNull(logger);
|
||||||
|
assertTrue(logger instanceof LoggerImpl2);
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import(FeignClientsConfiguration.class)
|
@Import(FeignClientsConfiguration.class)
|
||||||
protected static class SampleConfiguration3 {
|
protected static class SampleConfiguration3 {
|
||||||
|
|||||||
+14
-25
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -12,21 +12,19 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
|
||||||
|
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.boot.WebApplicationType;
|
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
||||||
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
|
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
|
||||||
@@ -35,8 +33,6 @@ import org.springframework.cloud.test.ModifiedClassPathRunner;
|
|||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ryan Baxter
|
* @author Ryan Baxter
|
||||||
*/
|
*/
|
||||||
@@ -48,29 +44,23 @@ public class FeignOkHttpConfigurationTests {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
this.context = new SpringApplicationBuilder()
|
context = new SpringApplicationBuilder().properties("debug=true","feign.httpclient.disableSslValidation=true",
|
||||||
.properties("debug=true", "feign.httpclient.disableSslValidation=true",
|
"feign.okhttp.enabled=true", "feign.httpclient.enabled=false").web(false)
|
||||||
"feign.okhttp.enabled=true", "feign.httpclient.enabled=false")
|
.sources(HttpClientConfiguration.class, FeignAutoConfiguration.class).run();
|
||||||
.web(WebApplicationType.NONE)
|
|
||||||
.sources(HttpClientConfiguration.class, FeignAutoConfiguration.class)
|
|
||||||
.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
if (this.context != null) {
|
if(context != null) {
|
||||||
this.context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void disableSslTest() throws Exception {
|
public void disableSslTest() throws Exception {
|
||||||
OkHttpClient httpClient = this.context.getBean(OkHttpClient.class);
|
OkHttpClient httpClient = context.getBean(OkHttpClient.class);
|
||||||
HostnameVerifier hostnameVerifier = (HostnameVerifier) this.getField(httpClient,
|
HostnameVerifier hostnameVerifier = (HostnameVerifier)this.getField(httpClient, "hostnameVerifier");
|
||||||
"hostnameVerifier");
|
Assert.assertTrue(OkHttpClientFactory.TrustAllHostnames.class.isInstance(hostnameVerifier));
|
||||||
assertThat(
|
|
||||||
OkHttpClientFactory.TrustAllHostnames.class.isInstance(hostnameVerifier))
|
|
||||||
.isTrue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> Object getField(Object target, String name) {
|
protected <T> Object getField(Object target, String name) {
|
||||||
@@ -79,5 +69,4 @@ public class FeignOkHttpConfigurationTests {
|
|||||||
Object value = ReflectionUtils.getField(field, target);
|
Object value = ReflectionUtils.getField(field, target);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+64
-81
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -23,15 +23,12 @@ import java.util.Objects;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
@@ -41,7 +38,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
@@ -60,7 +60,6 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
|
|||||||
|
|
||||||
public SpringDecoderTests() {
|
public SpringDecoderTests() {
|
||||||
setName("test");
|
setName("test");
|
||||||
setContextId("test");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestClient testClient() {
|
public TestClient testClient() {
|
||||||
@@ -70,73 +69,66 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
|
|||||||
public TestClient testClient(boolean decode404) {
|
public TestClient testClient(boolean decode404) {
|
||||||
setType(this.getClass());
|
setType(this.getClass());
|
||||||
setDecode404(decode404);
|
setDecode404(decode404);
|
||||||
return feign(this.context).target(TestClient.class,
|
return feign(context).target(TestClient.class, "http://localhost:" + this.port);
|
||||||
"http://localhost:" + this.port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResponseEntity() {
|
public void testResponseEntity() {
|
||||||
ResponseEntity<Hello> response = testClient().getHelloResponse();
|
ResponseEntity<Hello> response = testClient().getHelloResponse();
|
||||||
assertThat(response).as("response was null").isNotNull();
|
assertNotNull("response was null", response);
|
||||||
assertThat(response.getStatusCode()).as("wrong status code")
|
assertEquals("wrong status code", HttpStatus.OK, response.getStatusCode());
|
||||||
.isEqualTo(HttpStatus.OK);
|
|
||||||
Hello hello = response.getBody();
|
Hello hello = response.getBody();
|
||||||
assertThat(hello).as("hello was null").isNotNull();
|
assertNotNull("hello was null", hello);
|
||||||
assertThat(hello).as("first hello didn't match")
|
assertEquals("first hello didn't match", new Hello("hello world via response"),
|
||||||
.isEqualTo(new Hello("hello world via response"));
|
hello);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleType() {
|
public void testSimpleType() {
|
||||||
Hello hello = testClient().getHello();
|
Hello hello = testClient().getHello();
|
||||||
assertThat(hello).as("hello was null").isNotNull();
|
assertNotNull("hello was null", hello);
|
||||||
assertThat(hello).as("first hello didn't match")
|
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
|
||||||
.isEqualTo(new Hello("hello world 1"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUserParameterizedTypeDecode() {
|
public void testUserParameterizedTypeDecode() {
|
||||||
List<Hello> hellos = testClient().getHellos();
|
List<Hello> hellos = testClient().getHellos();
|
||||||
assertThat(hellos).as("hellos was null").isNotNull();
|
assertNotNull("hellos was null", hellos);
|
||||||
assertThat(hellos.size()).as("hellos was not the right size").isEqualTo(2);
|
assertEquals("hellos was not the right size", 2, hellos.size());
|
||||||
assertThat(hellos.get(0)).as("first hello didn't match")
|
assertEquals("first hello didn't match", new Hello("hello world 1"),
|
||||||
.isEqualTo(new Hello("hello world 1"));
|
hellos.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleParameterizedTypeDecode() {
|
public void testSimpleParameterizedTypeDecode() {
|
||||||
List<String> hellos = testClient().getHelloStrings();
|
List<String> hellos = testClient().getHelloStrings();
|
||||||
assertThat(hellos).as("hellos was null").isNotNull();
|
assertNotNull("hellos was null", hellos);
|
||||||
assertThat(hellos.size()).as("hellos was not the right size").isEqualTo(2);
|
assertEquals("hellos was not the right size", 2, hellos.size());
|
||||||
assertThat(hellos.get(0)).as("first hello didn't match")
|
assertEquals("first hello didn't match", "hello world 1", hellos.get(0));
|
||||||
.isEqualTo("hello world 1");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void testWildcardTypeDecode() {
|
public void testWildcardTypeDecode() {
|
||||||
ResponseEntity<?> wildcard = testClient().getWildcard();
|
ResponseEntity<?> wildcard = testClient().getWildcard();
|
||||||
assertThat(wildcard).as("wildcard was null").isNotNull();
|
assertNotNull("wildcard was null", wildcard);
|
||||||
assertThat(wildcard.getStatusCode()).as("wrong status code")
|
assertEquals("wrong status code", HttpStatus.OK, wildcard.getStatusCode());
|
||||||
.isEqualTo(HttpStatus.OK);
|
|
||||||
Object wildcardBody = wildcard.getBody();
|
Object wildcardBody = wildcard.getBody();
|
||||||
assertThat(wildcardBody).as("wildcardBody was null").isNotNull();
|
assertNotNull("wildcardBody was null", wildcardBody);
|
||||||
assertThat(wildcardBody instanceof Map).as("wildcard not an instance of Map")
|
assertTrue("wildcard not an instance of Map", wildcardBody instanceof Map);
|
||||||
.isTrue();
|
|
||||||
Map<String, String> hello = (Map<String, String>) wildcardBody;
|
Map<String, String> hello = (Map<String, String>) wildcardBody;
|
||||||
assertThat(hello.get("message")).as("first hello didn't match")
|
assertEquals("first hello didn't match", "wildcard", hello.get("message"));
|
||||||
.isEqualTo("wildcard");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResponseEntityVoid() {
|
public void testResponseEntityVoid() {
|
||||||
ResponseEntity<Void> response = testClient().getHelloVoid();
|
ResponseEntity<Void> response = testClient().getHelloVoid();
|
||||||
assertThat(response).as("response was null").isNotNull();
|
assertNotNull("response was null", response);
|
||||||
List<String> headerVals = response.getHeaders().get("X-test-header");
|
List<String> headerVals = response.getHeaders().get("X-test-header");
|
||||||
assertThat(headerVals).as("headerVals was null").isNotNull();
|
assertNotNull("headerVals was null", headerVals);
|
||||||
assertThat(headerVals.size()).as("headerVals size was wrong").isEqualTo(1);
|
assertEquals("headerVals size was wrong", 1, headerVals.size());
|
||||||
String header = headerVals.get(0);
|
String header = headerVals.get(0);
|
||||||
assertThat(header).as("header was wrong").isEqualTo("myval");
|
assertEquals("header was wrong", "myval", header);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = RuntimeException.class)
|
@Test(expected = RuntimeException.class)
|
||||||
@@ -147,12 +139,43 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
|
|||||||
@Test
|
@Test
|
||||||
public void testDecodes404() {
|
public void testDecodes404() {
|
||||||
final ResponseEntity<String> response = testClient(true).getNotFound();
|
final ResponseEntity<String> response = testClient(true).getNotFound();
|
||||||
assertThat(response).as("response was null").isNotNull();
|
assertNotNull("response was null", response);
|
||||||
assertThat(response.getBody()).as("response body was not null").isNull();
|
assertNull("response body was not null", response.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Hello {
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public Hello() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Hello(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Hello that = (Hello) o;
|
||||||
|
return Objects.equals(message, that.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected interface TestClient {
|
protected interface TestClient {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/helloresponse")
|
@RequestMapping(method = RequestMethod.GET, value = "/helloresponse")
|
||||||
ResponseEntity<Hello> getHelloResponse();
|
ResponseEntity<Hello> getHelloResponse();
|
||||||
|
|
||||||
@@ -173,51 +196,11 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
|
|||||||
|
|
||||||
@GetMapping("/helloWildcard")
|
@GetMapping("/helloWildcard")
|
||||||
ResponseEntity<?> getWildcard();
|
ResponseEntity<?> getWildcard();
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Hello {
|
|
||||||
|
|
||||||
private String message;
|
|
||||||
|
|
||||||
public Hello() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Hello(String message) {
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return this.message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMessage(String message) {
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Hello that = (Hello) o;
|
|
||||||
return Objects.equals(this.message, that.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(this.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@RestController
|
@RestController
|
||||||
@Import(NoSecurityConfiguration.class)
|
|
||||||
protected static class Application implements TestClient {
|
protected static class Application implements TestClient {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -260,7 +243,7 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
|
|||||||
public ResponseEntity<?> getWildcard() {
|
public ResponseEntity<?> getWildcard() {
|
||||||
return ResponseEntity.ok(new Hello("wildcard"));
|
return ResponseEntity.ok(new Hello("wildcard"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-23
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -14,64 +14,61 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.boot.WebApplicationType;
|
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
|
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
|
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
|
|
||||||
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
|
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
|
||||||
import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
|
import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
|
||||||
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
|
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
|
||||||
import org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer;
|
import org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
|
||||||
import org.springframework.cloud.test.ClassPathExclusions;
|
import org.springframework.cloud.test.ClassPathExclusions;
|
||||||
import org.springframework.cloud.test.ModifiedClassPathRunner;
|
import org.springframework.cloud.test.ModifiedClassPathRunner;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ryan Baxter
|
* @author Ryan Baxter
|
||||||
*/
|
*/
|
||||||
@RunWith(ModifiedClassPathRunner.class)
|
@RunWith(ModifiedClassPathRunner.class)
|
||||||
@ClassPathExclusions({ "spring-retry-*.jar", "spring-boot-starter-aop-*.jar" })
|
@ClassPathExclusions({"spring-retry-*.jar", "spring-boot-starter-aop-*.jar"})
|
||||||
public class SpringRetryDisabledTests {
|
public class SpringRetryDisabledTests {
|
||||||
|
|
||||||
private ConfigurableApplicationContext context;
|
private ConfigurableApplicationContext context;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
this.context = new SpringApplicationBuilder().web(WebApplicationType.NONE)
|
context = new SpringApplicationBuilder().web(false)
|
||||||
.sources(RibbonAutoConfiguration.class,
|
.sources(RibbonAutoConfiguration.class, LoadBalancerAutoConfiguration.class, RibbonClientConfiguration.class,
|
||||||
LoadBalancerAutoConfiguration.class,
|
FeignRibbonClientAutoConfiguration.class).run();
|
||||||
RibbonClientConfiguration.class,
|
|
||||||
FeignRibbonClientAutoConfiguration.class)
|
|
||||||
.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
if (this.context != null) {
|
if(context != null) {
|
||||||
this.context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadBalancedRetryFactoryBean() throws Exception {
|
public void testLoadBalancedRetryFactoryBean() throws Exception {
|
||||||
Map<String, CachingSpringLoadBalancerFactory> lbFactorys = this.context
|
Map<String, CachingSpringLoadBalancerFactory> lbFactorys = context.getBeansOfType(CachingSpringLoadBalancerFactory.class);
|
||||||
.getBeansOfType(CachingSpringLoadBalancerFactory.class);
|
assertThat(lbFactorys.values(), hasSize(1));
|
||||||
assertThat(lbFactorys.values()).hasSize(1);
|
FeignLoadBalancer lb =lbFactorys.values().iterator().next().create("foo");
|
||||||
FeignLoadBalancer lb = lbFactorys.values().iterator().next().create("foo");
|
assertThat(lb, instanceOf(FeignLoadBalancer.class));
|
||||||
assertThat(lb).isInstanceOf(FeignLoadBalancer.class);
|
assertThat(lb, is(not(instanceOf(RetryableFeignLoadBalancer.class))));
|
||||||
assertThat(lb).isNotInstanceOf(RetryableFeignLoadBalancer.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-16
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,49 +17,46 @@
|
|||||||
package org.springframework.cloud.openfeign;
|
package org.springframework.cloud.openfeign;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
|
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
|
||||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
|
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
|
|
||||||
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
|
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
|
||||||
import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
|
import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
|
||||||
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
|
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
|
||||||
import org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer;
|
import org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ryan Baxter
|
* @author Ryan Baxter
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration(classes = { RibbonAutoConfiguration.class,
|
@ContextConfiguration(classes = {RibbonAutoConfiguration.class, RibbonClientConfiguration.class, LoadBalancerAutoConfiguration.class,
|
||||||
RibbonClientConfiguration.class, LoadBalancerAutoConfiguration.class,
|
FeignRibbonClientAutoConfiguration.class, HttpClientConfiguration.class})
|
||||||
FeignRibbonClientAutoConfiguration.class, HttpClientConfiguration.class })
|
|
||||||
public class SpringRetryEnabledTests implements ApplicationContextAware {
|
public class SpringRetryEnabledTests implements ApplicationContextAware {
|
||||||
|
|
||||||
private ApplicationContext context;
|
private ApplicationContext context;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadBalancedRetryFactoryBean() throws Exception {
|
public void testLoadBalancedRetryFactoryBean() throws Exception {
|
||||||
Map<String, CachingSpringLoadBalancerFactory> lbFactorys = this.context
|
Map<String, CachingSpringLoadBalancerFactory> lbFactorys = context.getBeansOfType(CachingSpringLoadBalancerFactory.class);
|
||||||
.getBeansOfType(CachingSpringLoadBalancerFactory.class);
|
assertThat(lbFactorys.values(), Matchers.hasSize(1));
|
||||||
assertThat(lbFactorys.values()).hasSize(1);
|
FeignLoadBalancer lb =lbFactorys.values().iterator().next().create("foo");
|
||||||
FeignLoadBalancer lb = lbFactorys.values().iterator().next().create("foo");
|
assertThat(lb, instanceOf(RetryableFeignLoadBalancer.class));
|
||||||
assertThat(lb).isInstanceOf(RetryableFeignLoadBalancer.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
+46
-55
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -23,7 +23,6 @@ import java.util.Objects;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -43,7 +42,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
@@ -73,44 +73,6 @@ public class FeignClientTests {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private TestClient buildByBuilder;
|
private TestClient buildByBuilder;
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAnnotations() {
|
|
||||||
Map<String, Object> beans = this.context
|
|
||||||
.getBeansWithAnnotation(FeignClient.class);
|
|
||||||
assertThat(beans.containsKey(TestClient.class.getName()))
|
|
||||||
.as("Wrong clients: " + beans).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testClient() {
|
|
||||||
assertThat(this.testClient).as("testClient was null").isNotNull();
|
|
||||||
assertThat(this.extraClient).as("extraClient was null").isNotNull();
|
|
||||||
assertThat(Proxy.isProxyClass(this.testClient.getClass()))
|
|
||||||
.as("testClient is not a java Proxy").isTrue();
|
|
||||||
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.testClient);
|
|
||||||
assertThat(invocationHandler).as("invocationHandler was null").isNotNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void extraClient() {
|
|
||||||
assertThat(this.extraClient).as("extraClient was null").isNotNull();
|
|
||||||
assertThat(Proxy.isProxyClass(this.extraClient.getClass()))
|
|
||||||
.as("extraClient is not a java Proxy").isTrue();
|
|
||||||
InvocationHandler invocationHandler = Proxy
|
|
||||||
.getInvocationHandler(this.extraClient);
|
|
||||||
assertThat(invocationHandler).as("invocationHandler was null").isNotNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void buildByBuilder() {
|
|
||||||
assertThat(this.buildByBuilder).as("buildByBuilder was null").isNotNull();
|
|
||||||
assertThat(Proxy.isProxyClass(this.buildByBuilder.getClass()))
|
|
||||||
.as("buildByBuilder is not a java Proxy").isTrue();
|
|
||||||
InvocationHandler invocationHandler = Proxy
|
|
||||||
.getInvocationHandler(this.buildByBuilder);
|
|
||||||
assertThat(invocationHandler).as("invocationHandler was null").isNotNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@RestController
|
@RestController
|
||||||
@@ -120,18 +82,18 @@ public class FeignClientTests {
|
|||||||
|
|
||||||
@Bean("build-by-builder")
|
@Bean("build-by-builder")
|
||||||
public TestClient buildByBuilder(final FeignClientBuilder feignClientBuilder) {
|
public TestClient buildByBuilder(final FeignClientBuilder feignClientBuilder) {
|
||||||
return feignClientBuilder.forType(TestClient.class, "builderapp").build();
|
return feignClientBuilder
|
||||||
|
.forType(TestClient.class, "builderapp")
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||||
public Hello getHello() {
|
public Hello getHello() {
|
||||||
return new Hello("hello world 1");
|
return new Hello("hello world 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Hello {
|
public static class Hello {
|
||||||
|
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
public Hello() {
|
public Hello() {
|
||||||
@@ -142,7 +104,7 @@ public class FeignClientTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return this.message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMessage(String message) {
|
public void setMessage(String message) {
|
||||||
@@ -151,27 +113,56 @@ public class FeignClientTests {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) return true;
|
||||||
return true;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Hello that = (Hello) o;
|
Hello that = (Hello) o;
|
||||||
|
|
||||||
return Objects.equals(this.message, that.message);
|
return Objects.equals(message, that.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return this.message != null ? this.message.hashCode() : 0;
|
return message != null ? message.hashCode() : 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAnnotations() {
|
||||||
|
Map<String, Object> beans = this.context
|
||||||
|
.getBeansWithAnnotation(FeignClient.class);
|
||||||
|
assertTrue("Wrong clients: " + beans,
|
||||||
|
beans.containsKey(TestClient.class.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClient() {
|
||||||
|
assertNotNull("testClient was null", this.testClient);
|
||||||
|
assertNotNull("extraClient was null", this.extraClient);
|
||||||
|
assertTrue("testClient is not a java Proxy",
|
||||||
|
Proxy.isProxyClass(this.testClient.getClass()));
|
||||||
|
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.testClient);
|
||||||
|
assertNotNull("invocationHandler was null", invocationHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void extraClient() {
|
||||||
|
assertNotNull("extraClient was null", this.extraClient);
|
||||||
|
assertTrue("extraClient is not a java Proxy",
|
||||||
|
Proxy.isProxyClass(this.extraClient.getClass()));
|
||||||
|
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.extraClient);
|
||||||
|
assertNotNull("invocationHandler was null", invocationHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildByBuilder() {
|
||||||
|
assertNotNull("buildByBuilder was null", this.buildByBuilder);
|
||||||
|
assertTrue("buildByBuilder is not a java Proxy",
|
||||||
|
Proxy.isProxyClass(this.buildByBuilder.getClass()));
|
||||||
|
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.buildByBuilder);
|
||||||
|
assertNotNull("invocationHandler was null", invocationHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public static class TestDefaultFeignConfig {
|
public static class TestDefaultFeignConfig {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -23,10 +23,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
@Primary
|
@Primary
|
||||||
@FeignClient("localapp")
|
@FeignClient(value = "localapp")
|
||||||
public interface TestClient {
|
public interface TestClient {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||||
Hello getHello();
|
Hello getHello();
|
||||||
|
}
|
||||||
}
|
|
||||||
+1
-3
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -23,8 +23,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||||||
|
|
||||||
@FeignClient(value = "otherapp", qualifier = "uniquequalifier")
|
@FeignClient(value = "otherapp", qualifier = "uniquequalifier")
|
||||||
public interface TestClient {
|
public interface TestClient {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||||
Hello getHello();
|
Hello getHello();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-16
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -22,6 +22,7 @@ import java.util.List;
|
|||||||
import com.netflix.loadbalancer.BaseLoadBalancer;
|
import com.netflix.loadbalancer.BaseLoadBalancer;
|
||||||
import com.netflix.loadbalancer.ILoadBalancer;
|
import com.netflix.loadbalancer.ILoadBalancer;
|
||||||
import com.netflix.loadbalancer.Server;
|
import com.netflix.loadbalancer.Server;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@@ -29,28 +30,27 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonClient;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
import org.springframework.cloud.openfeign.encoding.app.client.InvoiceClient;
|
import org.springframework.cloud.openfeign.encoding.app.client.InvoiceClient;
|
||||||
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
||||||
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
|
import org.springframework.cloud.netflix.ribbon.RibbonClient;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the response compression.
|
* Tests the response compression.
|
||||||
*
|
*
|
||||||
* @author Jakub Narloch
|
* @author Jakub Narloch
|
||||||
*/
|
*/
|
||||||
@SpringBootTest(classes = FeignAcceptEncodingTests.Application.class, webEnvironment = RANDOM_PORT, value = {
|
@SpringBootTest(classes = FeignAcceptEncodingTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = {
|
||||||
"feign.compression.response.enabled=true" })
|
"feign.compression.response.enabled=true" })
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@DirtiesContext
|
@DirtiesContext
|
||||||
@@ -66,19 +66,17 @@ public class FeignAcceptEncodingTests {
|
|||||||
final ResponseEntity<List<Invoice>> invoices = this.invoiceClient.getInvoices();
|
final ResponseEntity<List<Invoice>> invoices = this.invoiceClient.getInvoices();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(invoices).isNotNull();
|
assertNotNull(invoices);
|
||||||
assertThat(invoices.getStatusCode()).isEqualTo(HttpStatus.OK);
|
assertEquals(HttpStatus.OK, invoices.getStatusCode());
|
||||||
assertThat(invoices.getBody()).isNotNull();
|
assertNotNull(invoices.getBody());
|
||||||
assertThat(invoices.getBody().size()).isEqualTo(100);
|
assertEquals(100, invoices.getBody().size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableFeignClients(clients = InvoiceClient.class)
|
@EnableFeignClients(clients = InvoiceClient.class)
|
||||||
@RibbonClient(name = "local", configuration = LocalRibbonClientConfiguration.class)
|
@RibbonClient(name = "local", configuration = LocalRibbonClientConfiguration.class)
|
||||||
@SpringBootApplication(scanBasePackages = "org.springframework.cloud.openfeign.encoding.app")
|
@SpringBootApplication(scanBasePackages = "org.springframework.cloud.openfeign.encoding.app")
|
||||||
@Import(NoSecurityConfiguration.class)
|
|
||||||
public static class Application {
|
public static class Application {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@@ -94,7 +92,5 @@ public class FeignAcceptEncodingTests {
|
|||||||
Collections.singletonList(new Server("localhost", this.port)));
|
Collections.singletonList(new Server("localhost", this.port)));
|
||||||
return balancer;
|
return balancer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
+15
-20
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,40 +16,39 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign.encoding;
|
package org.springframework.cloud.openfeign.encoding;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.netflix.loadbalancer.BaseLoadBalancer;
|
|
||||||
import com.netflix.loadbalancer.ILoadBalancer;
|
|
||||||
import com.netflix.loadbalancer.Server;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonClient;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
import org.springframework.cloud.openfeign.encoding.app.client.InvoiceClient;
|
import org.springframework.cloud.openfeign.encoding.app.client.InvoiceClient;
|
||||||
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
||||||
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
|
import org.springframework.cloud.netflix.ribbon.RibbonClient;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import com.netflix.loadbalancer.BaseLoadBalancer;
|
||||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
import com.netflix.loadbalancer.ILoadBalancer;
|
||||||
|
import com.netflix.loadbalancer.Server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the response compression.
|
* Tests the response compression.
|
||||||
*
|
*
|
||||||
* @author Jakub Narloch
|
* @author Jakub Narloch
|
||||||
*/
|
*/
|
||||||
@SpringBootTest(classes = FeignContentEncodingTests.Application.class, webEnvironment = RANDOM_PORT, value = {
|
@SpringBootTest(classes = FeignContentEncodingTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = {
|
||||||
"feign.compression.request.enabled=true",
|
"feign.compression.request.enabled=true",
|
||||||
"hystrix.command.default.execution.isolation.strategy=SEMAPHORE",
|
"hystrix.command.default.execution.isolation.strategy=SEMAPHORE",
|
||||||
"ribbon.OkToRetryOnAllOperations=false" })
|
"ribbon.OkToRetryOnAllOperations=false" })
|
||||||
@@ -70,19 +69,17 @@ public class FeignContentEncodingTests {
|
|||||||
.saveInvoices(invoices);
|
.saveInvoices(invoices);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(response).isNotNull();
|
assertNotNull(response);
|
||||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
assertThat(response.getBody()).isNotNull();
|
assertNotNull(response.getBody());
|
||||||
assertThat(response.getBody().size()).isEqualTo(invoices.size());
|
assertEquals(invoices.size(), response.getBody().size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableFeignClients(clients = InvoiceClient.class)
|
@EnableFeignClients(clients = InvoiceClient.class)
|
||||||
@RibbonClient(name = "local", configuration = LocalRibbonClientConfiguration.class)
|
@RibbonClient(name = "local", configuration = LocalRibbonClientConfiguration.class)
|
||||||
@SpringBootApplication(scanBasePackages = "org.springframework.cloud.openfeign.encoding.app")
|
@SpringBootApplication(scanBasePackages = "org.springframework.cloud.openfeign.encoding.app")
|
||||||
@Import(NoSecurityConfiguration.class)
|
|
||||||
public static class Application {
|
public static class Application {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@@ -98,7 +95,5 @@ public class FeignContentEncodingTests {
|
|||||||
Collections.singletonList(new Server("localhost", this.port)));
|
Collections.singletonList(new Server("localhost", this.port)));
|
||||||
return balancer;
|
return balancer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
-110
@@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2015 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.Collections;
|
|
||||||
|
|
||||||
import com.netflix.loadbalancer.BaseLoadBalancer;
|
|
||||||
import com.netflix.loadbalancer.ILoadBalancer;
|
|
||||||
import com.netflix.loadbalancer.Server;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonClient;
|
|
||||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
|
||||||
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
|
|
||||||
import org.springframework.cloud.openfeign.encoding.app.client.InvoiceClient;
|
|
||||||
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
|
||||||
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.PageRequest;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.domain.Sort;
|
|
||||||
import org.springframework.data.web.config.EnableSpringDataWebSupport;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the pagination encoding.
|
|
||||||
*
|
|
||||||
* @author Charlie Mordant.
|
|
||||||
*/
|
|
||||||
@SpringBootTest(classes = FeignPageableEncodingTests.Application.class, webEnvironment = RANDOM_PORT, value = {
|
|
||||||
"feign.compression.request.enabled=true",
|
|
||||||
"hystrix.command.default.execution.isolation.strategy=SEMAPHORE",
|
|
||||||
"ribbon.OkToRetryOnAllOperations=false" })
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
|
||||||
public class FeignPageableEncodingTests {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private InvoiceClient invoiceClient;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPageable() {
|
|
||||||
|
|
||||||
// given
|
|
||||||
Pageable pageable = PageRequest.of(0, 10, Sort.Direction.ASC, "sortProperty");
|
|
||||||
|
|
||||||
// when
|
|
||||||
final ResponseEntity<Page<Invoice>> response = this.invoiceClient
|
|
||||||
.getInvoicesPaged(pageable);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assertThat(response).isNotNull();
|
|
||||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
|
||||||
assertThat(response.getBody()).isNotNull();
|
|
||||||
assertThat(pageable.getPageSize()).isEqualTo(response.getBody().getSize());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@EnableFeignClients(clients = InvoiceClient.class)
|
|
||||||
@RibbonClient(name = "local", configuration = LocalRibbonClientConfiguration.class)
|
|
||||||
@SpringBootApplication(scanBasePackages = "org.springframework.cloud.openfeign.encoding.app")
|
|
||||||
@EnableSpringDataWebSupport
|
|
||||||
@Import({ NoSecurityConfiguration.class, FeignClientsConfiguration.class })
|
|
||||||
public static class Application {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
static class LocalRibbonClientConfiguration {
|
|
||||||
|
|
||||||
@Value("${local.server.port}")
|
|
||||||
private int port = 0;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ILoadBalancer ribbonLoadBalancer() {
|
|
||||||
BaseLoadBalancer balancer = new BaseLoadBalancer();
|
|
||||||
balancer.setServersList(
|
|
||||||
Collections.singletonList(new Server("localhost", this.port)));
|
|
||||||
return balancer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+4
-6
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign.encoding;
|
package org.springframework.cloud.openfeign.encoding;
|
||||||
|
|
||||||
|
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class used for testing.
|
* Utility class used for testing.
|
||||||
*
|
*
|
||||||
@@ -35,11 +35,9 @@ final class Invoices {
|
|||||||
for (int ind = 0; ind < count; ind++) {
|
for (int ind = 0; ind < count; ind++) {
|
||||||
final Invoice invoice = new Invoice();
|
final Invoice invoice = new Invoice();
|
||||||
invoice.setTitle("Invoice " + (ind + 1));
|
invoice.setTitle("Invoice " + (ind + 1));
|
||||||
invoice.setAmount(new BigDecimal(
|
invoice.setAmount(new BigDecimal(String.format(Locale.US, "%.2f", Math.random() * 1000)));
|
||||||
String.format(Locale.US, "%.2f", Math.random() * 1000)));
|
|
||||||
invoices.add(invoice);
|
invoices.add(invoice);
|
||||||
}
|
}
|
||||||
return invoices;
|
return invoices;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-7
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,7 +20,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -34,14 +33,9 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||||||
@FeignClient("local")
|
@FeignClient("local")
|
||||||
public interface InvoiceClient {
|
public interface InvoiceClient {
|
||||||
|
|
||||||
@RequestMapping(value = "invoicesPaged", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
|
|
||||||
ResponseEntity<Page<Invoice>> getInvoicesPaged(
|
|
||||||
org.springframework.data.domain.Pageable pageable);
|
|
||||||
|
|
||||||
@RequestMapping(value = "invoices", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(value = "invoices", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
ResponseEntity<List<Invoice>> getInvoices();
|
ResponseEntity<List<Invoice>> getInvoices();
|
||||||
|
|
||||||
@RequestMapping(value = "invoices", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(value = "invoices", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
ResponseEntity<List<Invoice>> saveInvoices(List<Invoice> invoices);
|
ResponseEntity<List<Invoice>> saveInvoices(List<Invoice> invoices);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-4
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -30,7 +30,7 @@ public class Invoice {
|
|||||||
private BigDecimal amount;
|
private BigDecimal amount;
|
||||||
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return this.title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTitle(String title) {
|
public void setTitle(String title) {
|
||||||
@@ -38,11 +38,10 @@ public class Invoice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getAmount() {
|
public BigDecimal getAmount() {
|
||||||
return this.amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAmount(BigDecimal amount) {
|
public void setAmount(BigDecimal amount) {
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-20
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,14 +16,7 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign.encoding.app.resource;
|
package org.springframework.cloud.openfeign.encoding.app.resource;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.PageImpl;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
@@ -31,6 +24,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An sample REST controller, that potentially returns large response - used for testing.
|
* An sample REST controller, that potentially returns large response - used for testing.
|
||||||
*
|
*
|
||||||
@@ -45,30 +43,21 @@ public class InvoiceResource {
|
|||||||
return ResponseEntity.ok(createInvoiceList(100));
|
return ResponseEntity.ok(createInvoiceList(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "invoices", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(value = "invoices", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE,
|
||||||
|
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
ResponseEntity<List<Invoice>> saveInvoices(@RequestBody List<Invoice> invoices) {
|
ResponseEntity<List<Invoice>> saveInvoices(@RequestBody List<Invoice> invoices) {
|
||||||
|
|
||||||
return ResponseEntity.ok(invoices);
|
return ResponseEntity.ok(invoices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "invoicesPaged", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
|
|
||||||
public ResponseEntity<Page<Invoice>> getInvoicesPaged(
|
|
||||||
org.springframework.data.domain.Pageable pageable) {
|
|
||||||
Page<Invoice> page = new PageImpl<>(createInvoiceList(pageable.getPageSize()),
|
|
||||||
pageable, 100);
|
|
||||||
return ResponseEntity.ok(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Invoice> createInvoiceList(int count) {
|
private List<Invoice> createInvoiceList(int count) {
|
||||||
final List<Invoice> invoices = new ArrayList<>();
|
final List<Invoice> invoices = new ArrayList<>();
|
||||||
for (int ind = 0; ind < count; ind++) {
|
for (int ind = 0; ind < count; ind++) {
|
||||||
final Invoice invoice = new Invoice();
|
final Invoice invoice = new Invoice();
|
||||||
invoice.setTitle("Invoice " + (ind + 1));
|
invoice.setTitle("Invoice " + (ind + 1));
|
||||||
invoice.setAmount(new BigDecimal(
|
invoice.setAmount(new BigDecimal(String.format(Locale.US, "%.2f", Math.random() * 1000)));
|
||||||
String.format(Locale.US, "%.2f", Math.random() * 1000)));
|
|
||||||
invoices.add(invoice);
|
invoices.add(invoice);
|
||||||
}
|
}
|
||||||
return invoices;
|
return invoices;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-16
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2012-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,7 +19,6 @@ package org.springframework.cloud.openfeign.encoding.proto;
|
|||||||
import feign.RequestTemplate;
|
import feign.RequestTemplate;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.ObjectFactory;
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||||
@@ -28,8 +27,6 @@ import org.springframework.cloud.test.ClassPathExclusions;
|
|||||||
import org.springframework.cloud.test.ModifiedClassPathRunner;
|
import org.springframework.cloud.test.ModifiedClassPathRunner;
|
||||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||||
|
|
||||||
import static feign.Request.HttpMethod.POST;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test {@link SpringEncoder} when protobuf is not in classpath
|
* Test {@link SpringEncoder} when protobuf is not in classpath
|
||||||
*
|
*
|
||||||
@@ -39,17 +36,17 @@ import static feign.Request.HttpMethod.POST;
|
|||||||
@ClassPathExclusions("protobuf-*.jar")
|
@ClassPathExclusions("protobuf-*.jar")
|
||||||
public class ProtobufNotInClasspathTest {
|
public class ProtobufNotInClasspathTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeWhenProtobufNotInClasspath() {
|
public void testEncodeWhenProtobufNotInClasspath() {
|
||||||
ObjectFactory<HttpMessageConverters> converters = new ObjectFactory<HttpMessageConverters>() {
|
ObjectFactory<HttpMessageConverters> converters = new ObjectFactory<HttpMessageConverters>() {
|
||||||
@Override
|
@Override
|
||||||
public HttpMessageConverters getObject() throws BeansException {
|
public HttpMessageConverters getObject() throws BeansException {
|
||||||
return new HttpMessageConverters(new StringHttpMessageConverter());
|
return new HttpMessageConverters(new StringHttpMessageConverter());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
RequestTemplate requestTemplate = new RequestTemplate();
|
RequestTemplate requestTemplate = new RequestTemplate();
|
||||||
requestTemplate.method(POST);
|
requestTemplate.method("POST");
|
||||||
new SpringEncoder(converters).encode("a=b", String.class, requestTemplate);
|
new SpringEncoder(converters).encode("a=b", String.class, requestTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+79
-94
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2012-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,14 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign.encoding.proto;
|
package org.springframework.cloud.openfeign.encoding.proto;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import feign.RequestTemplate;
|
import feign.RequestTemplate;
|
||||||
import feign.httpclient.ApacheHttpClient;
|
import feign.httpclient.ApacheHttpClient;
|
||||||
@@ -35,25 +27,27 @@ import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
|||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.message.BasicHttpResponse;
|
import org.apache.http.message.BasicHttpResponse;
|
||||||
import org.apache.http.message.BasicStatusLine;
|
import org.apache.http.message.BasicStatusLine;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.ArgumentMatchers;
|
|
||||||
import org.mockito.BDDMockito;
|
import org.mockito.BDDMockito;
|
||||||
|
import org.mockito.Matchers;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.ObjectFactory;
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||||
import org.springframework.cloud.openfeign.support.SpringEncoder;
|
import org.springframework.cloud.openfeign.support.SpringEncoder;
|
||||||
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
|
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
|
||||||
|
|
||||||
import static feign.Request.Body.encoded;
|
import java.io.IOException;
|
||||||
import static feign.Request.HttpMethod.POST;
|
import java.io.InputStream;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import java.net.URISyntaxException;
|
||||||
import static org.assertj.core.api.Assertions.fail;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test {@link SpringEncoder} with {@link ProtobufHttpMessageConverter}
|
* Test {@link SpringEncoder} with {@link ProtobufHttpMessageConverter}
|
||||||
@@ -63,92 +57,83 @@ import static org.assertj.core.api.Assertions.fail;
|
|||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class ProtobufSpringEncoderTest {
|
public class ProtobufSpringEncoderTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
|
|
||||||
// a protobuf object with some content
|
// a protobuf object with some content
|
||||||
private org.springframework.cloud.openfeign.encoding.proto.Request request = org.springframework.cloud.openfeign.encoding.proto.Request
|
private org.springframework.cloud.openfeign.encoding.proto.Request request = org.springframework.cloud.openfeign.encoding.proto.Request.newBuilder()
|
||||||
.newBuilder().setId(1000000).setMsg("Erlang/OTP 最初是爱立信为开发电信设备系统设计的编程语言平台,"
|
.setId(1000000)
|
||||||
+ "电信设备(路由器、接入网关、…)典型设计是通过背板连接主控板卡与多块业务板卡的分布式系统。")
|
.setMsg("Erlang/OTP 最初是爱立信为开发电信设备系统设计的编程语言平台," +
|
||||||
.build();
|
"电信设备(路由器、接入网关、…)典型设计是通过背板连接主控板卡与多块业务板卡的分布式系统。")
|
||||||
|
.build();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProtobuf() throws IOException, URISyntaxException {
|
public void testProtobuf() throws IOException, URISyntaxException {
|
||||||
// protobuf convert to request by feign and ProtobufHttpMessageConverter
|
// protobuf convert to request by feign and ProtobufHttpMessageConverter
|
||||||
RequestTemplate requestTemplate = newRequestTemplate();
|
RequestTemplate requestTemplate = newRequestTemplate();
|
||||||
newEncoder().encode(this.request, Request.class, requestTemplate);
|
newEncoder().encode(request, Request.class, requestTemplate);
|
||||||
HttpEntity entity = toApacheHttpEntity(requestTemplate);
|
HttpEntity entity = toApacheHttpEntity(requestTemplate);
|
||||||
byte[] bytes = read(entity.getContent(), (int) entity.getContentLength());
|
byte[] bytes = read(entity.getContent(), (int) entity.getContentLength());
|
||||||
|
|
||||||
assertThat(this.request.toByteArray()).isEqualTo(bytes);
|
Assert.assertArrayEquals(bytes, request.toByteArray());
|
||||||
org.springframework.cloud.openfeign.encoding.proto.Request copy = org.springframework.cloud.openfeign.encoding.proto.Request
|
org.springframework.cloud.openfeign.encoding.proto.Request copy = org.springframework.cloud.openfeign.encoding.proto.Request.parseFrom(bytes);
|
||||||
.parseFrom(bytes);
|
Assert.assertEquals(request, copy);
|
||||||
assertThat(copy).isEqualTo(this.request);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProtobufWithCharsetWillFail() throws IOException, URISyntaxException {
|
public void testProtobufWithCharsetWillFail() throws IOException, URISyntaxException {
|
||||||
// protobuf convert to request by feign and ProtobufHttpMessageConverter
|
// protobuf convert to request by feign and ProtobufHttpMessageConverter
|
||||||
RequestTemplate requestTemplate = newRequestTemplate();
|
RequestTemplate requestTemplate = newRequestTemplate();
|
||||||
newEncoder().encode(this.request, Request.class, requestTemplate);
|
newEncoder().encode(request, Request.class, requestTemplate);
|
||||||
// set a charset
|
// set a charset
|
||||||
requestTemplate.body(
|
requestTemplate.body(requestTemplate.body(), StandardCharsets.UTF_8);
|
||||||
encoded(requestTemplate.requestBody().asBytes(), StandardCharsets.UTF_8));
|
HttpEntity entity = toApacheHttpEntity(requestTemplate);
|
||||||
HttpEntity entity = toApacheHttpEntity(requestTemplate);
|
byte[] bytes = read(entity.getContent(), (int) entity.getContentLength());
|
||||||
byte[] bytes = read(entity.getContent(), (int) entity.getContentLength());
|
|
||||||
|
|
||||||
// http request-body is different with original protobuf body
|
// http request-body is different with original protobuf body
|
||||||
assertThat(this.request.toByteArray().length).isNotEqualTo(bytes.length);
|
Assert.assertNotEquals(bytes.length, request.toByteArray().length);
|
||||||
try {
|
try {
|
||||||
org.springframework.cloud.openfeign.encoding.proto.Request copy = org.springframework.cloud.openfeign.encoding.proto.Request
|
org.springframework.cloud.openfeign.encoding.proto.Request copy = org.springframework.cloud.openfeign.encoding.proto.Request.parseFrom(bytes);
|
||||||
.parseFrom(bytes);
|
Assert.fail("Expected an InvalidProtocolBufferException to be thrown");
|
||||||
fail("Expected an InvalidProtocolBufferException to be thrown");
|
} catch (InvalidProtocolBufferException e) {
|
||||||
}
|
// success
|
||||||
catch (InvalidProtocolBufferException e) {
|
}
|
||||||
// success
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SpringEncoder newEncoder() {
|
private SpringEncoder newEncoder() {
|
||||||
ObjectFactory<HttpMessageConverters> converters = new ObjectFactory<HttpMessageConverters>() {
|
ObjectFactory<HttpMessageConverters> converters = new ObjectFactory<HttpMessageConverters>() {
|
||||||
@Override
|
@Override
|
||||||
public HttpMessageConverters getObject() throws BeansException {
|
public HttpMessageConverters getObject() throws BeansException {
|
||||||
return new HttpMessageConverters(new ProtobufHttpMessageConverter());
|
return new HttpMessageConverters(new ProtobufHttpMessageConverter());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return new SpringEncoder(converters);
|
return new SpringEncoder(converters);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RequestTemplate newRequestTemplate() {
|
private RequestTemplate newRequestTemplate() {
|
||||||
RequestTemplate requestTemplate = new RequestTemplate();
|
RequestTemplate requestTemplate = new RequestTemplate();
|
||||||
requestTemplate.method(POST);
|
requestTemplate.method("POST");
|
||||||
return requestTemplate;
|
return requestTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpEntity toApacheHttpEntity(RequestTemplate requestTemplate)
|
private HttpEntity toApacheHttpEntity(RequestTemplate requestTemplate) throws IOException, URISyntaxException {
|
||||||
throws IOException, URISyntaxException {
|
final List<HttpUriRequest> request = new ArrayList<>(1);
|
||||||
final List<HttpUriRequest> request = new ArrayList<>(1);
|
BDDMockito.given(httpClient.execute(Matchers.<HttpUriRequest>any())).will(new Answer<HttpResponse>() {
|
||||||
BDDMockito.given(this.httpClient.execute(ArgumentMatchers.<HttpUriRequest>any()))
|
@Override
|
||||||
.will(new Answer<HttpResponse>() {
|
public HttpResponse answer(InvocationOnMock invocationOnMock) throws Throwable {
|
||||||
@Override
|
request.add((HttpUriRequest) invocationOnMock.getArguments()[0]);
|
||||||
public HttpResponse answer(InvocationOnMock invocationOnMock)
|
return new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion("http", 1, 1), 200, null));
|
||||||
throws Throwable {
|
}
|
||||||
request.add((HttpUriRequest) invocationOnMock.getArguments()[0]);
|
});
|
||||||
return new BasicHttpResponse(new BasicStatusLine(
|
new ApacheHttpClient(httpClient).execute(requestTemplate.request(), new feign.Request.Options());
|
||||||
new ProtocolVersion("http", 1, 1), 200, null));
|
HttpUriRequest httpUriRequest = request.get(0);
|
||||||
}
|
return ((HttpEntityEnclosingRequestBase)httpUriRequest).getEntity();
|
||||||
});
|
}
|
||||||
new ApacheHttpClient(this.httpClient).execute(
|
|
||||||
requestTemplate.resolve(new HashMap<>()).request(),
|
|
||||||
new feign.Request.Options());
|
|
||||||
HttpUriRequest httpUriRequest = request.get(0);
|
|
||||||
return ((HttpEntityEnclosingRequestBase) httpUriRequest).getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] read(InputStream in, int length) throws IOException {
|
private byte[] read(InputStream in, int length) throws IOException {
|
||||||
byte[] bytes = new byte[length];
|
byte[] bytes = new byte[length];
|
||||||
in.read(bytes);
|
in.read(bytes);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-42
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2012-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,48 +20,53 @@
|
|||||||
package org.springframework.cloud.openfeign.encoding.proto;
|
package org.springframework.cloud.openfeign.encoding.proto;
|
||||||
|
|
||||||
public final class ProtobufTest {
|
public final class ProtobufTest {
|
||||||
|
private ProtobufTest() {}
|
||||||
|
public static void registerAllExtensions(
|
||||||
|
com.google.protobuf.ExtensionRegistryLite registry) {
|
||||||
|
}
|
||||||
|
|
||||||
static final com.google.protobuf.Descriptors.Descriptor internal_static_Request_descriptor;
|
public static void registerAllExtensions(
|
||||||
static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_Request_fieldAccessorTable;
|
com.google.protobuf.ExtensionRegistry registry) {
|
||||||
|
registerAllExtensions(
|
||||||
|
(com.google.protobuf.ExtensionRegistryLite) registry);
|
||||||
|
}
|
||||||
|
static final com.google.protobuf.Descriptors.Descriptor
|
||||||
|
internal_static_Request_descriptor;
|
||||||
|
static final
|
||||||
|
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
|
||||||
|
internal_static_Request_fieldAccessorTable;
|
||||||
|
|
||||||
private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
|
public static com.google.protobuf.Descriptors.FileDescriptor
|
||||||
|
getDescriptor() {
|
||||||
static {
|
return descriptor;
|
||||||
String[] descriptorData = {
|
}
|
||||||
"\n\023protobuf_test.proto\"\"\n\007Request\022\n\n\002id\030\001"
|
private static com.google.protobuf.Descriptors.FileDescriptor
|
||||||
+ " \001(\005\022\013\n\003msg\030\002 \001(\tB\024\n\020feign.httpclientP\001b"
|
descriptor;
|
||||||
+ "\006proto3" };
|
static {
|
||||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
String[] descriptorData = {
|
||||||
public com.google.protobuf.ExtensionRegistry assignDescriptors(
|
"\n\023protobuf_test.proto\"\"\n\007Request\022\n\n\002id\030\001" +
|
||||||
com.google.protobuf.Descriptors.FileDescriptor root) {
|
" \001(\005\022\013\n\003msg\030\002 \001(\tB\024\n\020feign.httpclientP\001b" +
|
||||||
descriptor = root;
|
"\006proto3"
|
||||||
return null;
|
};
|
||||||
}
|
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||||
};
|
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
|
||||||
com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(
|
public com.google.protobuf.ExtensionRegistry assignDescriptors(
|
||||||
descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {},
|
com.google.protobuf.Descriptors.FileDescriptor root) {
|
||||||
assigner);
|
descriptor = root;
|
||||||
internal_static_Request_descriptor = getDescriptor().getMessageTypes().get(0);
|
return null;
|
||||||
internal_static_Request_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
|
}
|
||||||
internal_static_Request_descriptor, new String[] { "Id", "Msg", });
|
};
|
||||||
}
|
com.google.protobuf.Descriptors.FileDescriptor
|
||||||
|
.internalBuildGeneratedFileFrom(descriptorData,
|
||||||
private ProtobufTest() {
|
new com.google.protobuf.Descriptors.FileDescriptor[] {
|
||||||
}
|
}, assigner);
|
||||||
|
internal_static_Request_descriptor =
|
||||||
public static void registerAllExtensions(
|
getDescriptor().getMessageTypes().get(0);
|
||||||
com.google.protobuf.ExtensionRegistryLite registry) {
|
internal_static_Request_fieldAccessorTable = new
|
||||||
}
|
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
|
||||||
|
internal_static_Request_descriptor,
|
||||||
public static void registerAllExtensions(
|
new String[] { "Id", "Msg", });
|
||||||
com.google.protobuf.ExtensionRegistry registry) {
|
}
|
||||||
registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
|
|
||||||
return descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @@protoc_insertion_point(outer_class_scope)
|
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(outer_class_scope)
|
||||||
}
|
}
|
||||||
|
|||||||
+562
-579
File diff suppressed because it is too large
Load Diff
+16
-17
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2012-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,22 +20,21 @@
|
|||||||
package org.springframework.cloud.openfeign.encoding.proto;
|
package org.springframework.cloud.openfeign.encoding.proto;
|
||||||
|
|
||||||
public interface RequestOrBuilder extends
|
public interface RequestOrBuilder extends
|
||||||
// @@protoc_insertion_point(interface_extends:Request)
|
// @@protoc_insertion_point(interface_extends:Request)
|
||||||
com.google.protobuf.MessageOrBuilder {
|
com.google.protobuf.MessageOrBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>int32 id = 1;</code>
|
* <code>int32 id = 1;</code>
|
||||||
*/
|
*/
|
||||||
int getId();
|
int getId();
|
||||||
|
|
||||||
/**
|
|
||||||
* <code>string msg = 2;</code>
|
|
||||||
*/
|
|
||||||
String getMsg();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <code>string msg = 2;</code>
|
|
||||||
*/
|
|
||||||
com.google.protobuf.ByteString getMsgBytes();
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>string msg = 2;</code>
|
||||||
|
*/
|
||||||
|
String getMsg();
|
||||||
|
/**
|
||||||
|
* <code>string msg = 2;</code>
|
||||||
|
*/
|
||||||
|
com.google.protobuf.ByteString
|
||||||
|
getMsgBytes();
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-31
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,45 +16,17 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.openfeign.hystrix.security;
|
package org.springframework.cloud.openfeign.hystrix.security;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
import org.springframework.cloud.openfeign.hystrix.security.app.CustomConcurrenyStrategy;
|
|
||||||
import org.springframework.cloud.openfeign.hystrix.security.app.ProxyUsernameController;
|
|
||||||
import org.springframework.cloud.openfeign.hystrix.security.app.TestInterceptor;
|
|
||||||
import org.springframework.cloud.openfeign.hystrix.security.app.UsernameClient;
|
import org.springframework.cloud.openfeign.hystrix.security.app.UsernameClient;
|
||||||
import org.springframework.cloud.openfeign.hystrix.security.app.UsernameController;
|
|
||||||
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Daniel Lavoie
|
* @author Daniel Lavoie
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableAutoConfiguration
|
@SpringBootApplication
|
||||||
@EnableFeignClients(clients = UsernameClient.class)
|
@EnableFeignClients(clients = UsernameClient.class)
|
||||||
@Import(NoSecurityConfiguration.class)
|
|
||||||
public class HystrixSecurityApplication {
|
public class HystrixSecurityApplication {
|
||||||
|
|
||||||
@Bean
|
|
||||||
public CustomConcurrenyStrategy customConcurrenyStrategy() {
|
|
||||||
return new CustomConcurrenyStrategy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public TestInterceptor testInterceptor() {
|
|
||||||
return new TestInterceptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ProxyUsernameController proxyUsernameController() {
|
|
||||||
return new ProxyUsernameController();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public UsernameController usernameController() {
|
|
||||||
return new UsernameController();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-65
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,61 +17,73 @@
|
|||||||
package org.springframework.cloud.openfeign.hystrix.security;
|
package org.springframework.cloud.openfeign.hystrix.security;
|
||||||
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
import org.junit.Assert;
|
||||||
import com.netflix.hystrix.strategy.HystrixPlugins;
|
|
||||||
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
|
|
||||||
import com.netflix.loadbalancer.Server;
|
|
||||||
import com.netflix.loadbalancer.ServerList;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.SpringBootConfiguration;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.boot.web.server.LocalServerPort;
|
import org.springframework.boot.web.server.LocalServerPort;
|
||||||
import org.springframework.cloud.netflix.hystrix.security.SecurityContextConcurrencyStrategy;
|
import org.springframework.cloud.netflix.hystrix.security.SecurityContextConcurrencyStrategy;
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonClient;
|
|
||||||
import org.springframework.cloud.netflix.ribbon.StaticServerList;
|
|
||||||
import org.springframework.cloud.openfeign.hystrix.security.app.CustomConcurrenyStrategy;
|
import org.springframework.cloud.openfeign.hystrix.security.app.CustomConcurrenyStrategy;
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
import com.netflix.hystrix.strategy.HystrixPlugins;
|
||||||
|
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that a secured web service returning values using a feign client properly access
|
* Tests that a secured web service returning values using a feign client properly access
|
||||||
* the security context from a hystrix command.
|
* the security context from a hystrix command.
|
||||||
*
|
|
||||||
* @author Daniel Lavoie
|
* @author Daniel Lavoie
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@DirtiesContext
|
@DirtiesContext
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
|
@SpringBootTest(classes = HystrixSecurityApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT,
|
||||||
"feign.hystrix.enabled=true" })
|
properties = { "username.ribbon.listOfServers=localhost:${local.server.port}",
|
||||||
|
"feign.hystrix.enabled=true"})
|
||||||
@ActiveProfiles("proxysecurity")
|
@ActiveProfiles("proxysecurity")
|
||||||
public class HystrixSecurityTests {
|
public class HystrixSecurityTests {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private CustomConcurrenyStrategy customConcurrenyStrategy;
|
private CustomConcurrenyStrategy customConcurrenyStrategy;
|
||||||
|
|
||||||
@LocalServerPort
|
@LocalServerPort
|
||||||
private String serverPort;
|
private String serverPort;
|
||||||
|
|
||||||
// TODO: move to constants in TestAutoConfiguration
|
//TODOO: move to constants in TestAutoConfiguration
|
||||||
private String username = "user";
|
private String username = "user";
|
||||||
|
|
||||||
private String password = "password";
|
private String password = "password";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSecurityConcurrencyStrategyInstalled() {
|
||||||
|
HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
|
||||||
|
assertThat(concurrencyStrategy).isInstanceOf(SecurityContextConcurrencyStrategy.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFeignHystrixSecurity() {
|
||||||
|
HttpHeaders headers = HystrixSecurityTests.createBasicAuthHeader(username,
|
||||||
|
password);
|
||||||
|
|
||||||
|
String usernameResult = new RestTemplate()
|
||||||
|
.exchange("http://localhost:" + serverPort + "/proxy-username",
|
||||||
|
HttpMethod.GET, new HttpEntity<Void>(headers), String.class)
|
||||||
|
.getBody();
|
||||||
|
|
||||||
|
Assert.assertTrue("Username should have been intercepted by feign interceptor.",
|
||||||
|
username.equals(usernameResult));
|
||||||
|
|
||||||
|
Assert.assertTrue("Custom hook should have been called.",
|
||||||
|
customConcurrenyStrategy.isHookCalled());
|
||||||
|
}
|
||||||
|
|
||||||
public static HttpHeaders createBasicAuthHeader(final String username,
|
public static HttpHeaders createBasicAuthHeader(final String username,
|
||||||
final String password) {
|
final String password) {
|
||||||
return new HttpHeaders() {
|
return new HttpHeaders() {
|
||||||
@@ -85,50 +97,4 @@ public class HystrixSecurityTests {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSecurityConcurrencyStrategyInstalled() {
|
|
||||||
HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance()
|
|
||||||
.getConcurrencyStrategy();
|
|
||||||
assertThat(concurrencyStrategy)
|
|
||||||
.isInstanceOf(SecurityContextConcurrencyStrategy.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFeignHystrixSecurity() {
|
|
||||||
HttpHeaders headers = createBasicAuthHeader(this.username, this.password);
|
|
||||||
|
|
||||||
ResponseEntity<String> entity = new RestTemplate().exchange(
|
|
||||||
"http://localhost:" + this.serverPort + "/proxy-username", HttpMethod.GET,
|
|
||||||
new HttpEntity<Void>(headers), String.class);
|
|
||||||
|
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
|
||||||
|
|
||||||
assertThat(entity.getBody())
|
|
||||||
.as("Username should have been intercepted by feign interceptor.")
|
|
||||||
.isEqualTo(this.username);
|
|
||||||
|
|
||||||
assertThat(this.customConcurrenyStrategy.isHookCalled())
|
|
||||||
.as("Custom hook should have been called.").isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SpringBootConfiguration
|
|
||||||
@Import(HystrixSecurityApplication.class)
|
|
||||||
@RibbonClient(name = "username", configuration = LocalRibbonClientConfiguration.class)
|
|
||||||
protected static class TestConfig {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class LocalRibbonClientConfiguration {
|
|
||||||
|
|
||||||
@LocalServerPort
|
|
||||||
private int port = 0;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ServerList<Server> ribbonServerList() {
|
|
||||||
return new StaticServerList<>(new Server("localhost", this.port));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-20
@@ -1,27 +1,11 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2019 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.hystrix.security.app;
|
package org.springframework.cloud.openfeign.hystrix.security.app;
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
|
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
|
||||||
|
|
||||||
|
@Component
|
||||||
public class CustomConcurrenyStrategy extends HystrixConcurrencyStrategy {
|
public class CustomConcurrenyStrategy extends HystrixConcurrencyStrategy {
|
||||||
|
|
||||||
private boolean hookCalled;
|
private boolean hookCalled;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -32,7 +16,6 @@ public class CustomConcurrenyStrategy extends HystrixConcurrencyStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHookCalled() {
|
public boolean isHookCalled() {
|
||||||
return this.hookCalled;
|
return hookCalled;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,13 +26,11 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/proxy-username")
|
@RequestMapping("/proxy-username")
|
||||||
public class ProxyUsernameController {
|
public class ProxyUsernameController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UsernameClient usernameClient;
|
private UsernameClient usernameClient;
|
||||||
|
|
||||||
@RequestMapping
|
@RequestMapping
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return this.usernameClient.getUsername();
|
return usernameClient.getUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,21 +20,21 @@ import feign.RequestInterceptor;
|
|||||||
import feign.RequestTemplate;
|
import feign.RequestTemplate;
|
||||||
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interceptor should be called from an Hyxtrix command execution thread. It is
|
* This interceptor should be called from an Hyxtrix command execution thread. It is
|
||||||
* access the SecurityContext and settings an http header from the authentication details.
|
* access the SecurityContext and settings an http header from the authentication details.
|
||||||
*
|
*
|
||||||
* @author Daniel Lavoie
|
* @author Daniel Lavoie
|
||||||
*/
|
*/
|
||||||
|
@Component
|
||||||
public class TestInterceptor implements RequestInterceptor {
|
public class TestInterceptor implements RequestInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(RequestTemplate template) {
|
public void apply(RequestTemplate template) {
|
||||||
if (SecurityContextHolder.getContext().getAuthentication() != null) {
|
if (SecurityContextHolder.getContext().getAuthentication() != null)
|
||||||
template.header("username",
|
template.header("username",
|
||||||
SecurityContextHolder.getContext().getAuthentication().getName());
|
SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,6 +26,5 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
public interface UsernameClient {
|
public interface UsernameClient {
|
||||||
|
|
||||||
@RequestMapping("/username")
|
@RequestMapping("/username")
|
||||||
String getUsername();
|
public String getUsername();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,10 +26,8 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/username")
|
@RequestMapping("/username")
|
||||||
public class UsernameController {
|
public class UsernameController {
|
||||||
|
|
||||||
@RequestMapping
|
@RequestMapping
|
||||||
public String getUsername(@RequestHeader String username) {
|
public String getUsername(@RequestHeader String username){
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+79
-154
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,17 +19,13 @@ package org.springframework.cloud.openfeign.invalid;
|
|||||||
import feign.Feign;
|
import feign.Feign;
|
||||||
import feign.hystrix.FallbackFactory;
|
import feign.hystrix.FallbackFactory;
|
||||||
import feign.hystrix.HystrixFeign;
|
import feign.hystrix.HystrixFeign;
|
||||||
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
|
|
||||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
|
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
|
|
||||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
|
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
|
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -37,7 +33,7 @@ import org.springframework.context.annotation.Import;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
@@ -53,81 +49,6 @@ public class FeignClientValidationTests {
|
|||||||
new AnnotationConfigApplicationContext(NameAndValueConfiguration.class);
|
new AnnotationConfigApplicationContext(NameAndValueConfiguration.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testServiceIdAndValue() {
|
|
||||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
|
||||||
LoadBalancerAutoConfiguration.class, RibbonAutoConfiguration.class,
|
|
||||||
FeignRibbonClientAutoConfiguration.class,
|
|
||||||
NameAndServiceIdConfiguration.class);
|
|
||||||
assertThat(context.getBean(NameAndServiceIdConfiguration.Client.class))
|
|
||||||
.isNotNull();
|
|
||||||
context.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDuplicatedClientNames() {
|
|
||||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
|
||||||
context.setAllowBeanDefinitionOverriding(false);
|
|
||||||
context.register(LoadBalancerAutoConfiguration.class,
|
|
||||||
RibbonAutoConfiguration.class, FeignRibbonClientAutoConfiguration.class,
|
|
||||||
DuplicatedFeignClientNamesConfiguration.class);
|
|
||||||
context.refresh();
|
|
||||||
assertThat(
|
|
||||||
context.getBean(DuplicatedFeignClientNamesConfiguration.FooClient.class))
|
|
||||||
.isNotNull();
|
|
||||||
assertThat(
|
|
||||||
context.getBean(DuplicatedFeignClientNamesConfiguration.BarClient.class))
|
|
||||||
.isNotNull();
|
|
||||||
context.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNotLegalHostname() {
|
|
||||||
this.expected.expectMessage("not legal hostname (foo_bar)");
|
|
||||||
new AnnotationConfigApplicationContext(BadHostnameConfiguration.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMissingFallback() {
|
|
||||||
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
|
||||||
MissingFallbackConfiguration.class)) {
|
|
||||||
this.expected.expectMessage("No fallback instance of type");
|
|
||||||
assertThat(context.getBean(MissingFallbackConfiguration.Client.class))
|
|
||||||
.isNotNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testWrongFallbackType() {
|
|
||||||
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
|
||||||
WrongFallbackTypeConfiguration.class)) {
|
|
||||||
this.expected.expectMessage("Incompatible fallback instance");
|
|
||||||
assertThat(context.getBean(WrongFallbackTypeConfiguration.Client.class))
|
|
||||||
.isNotNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMissingFallbackFactory() {
|
|
||||||
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
|
||||||
MissingFallbackFactoryConfiguration.class)) {
|
|
||||||
this.expected.expectMessage("No fallbackFactory instance of type");
|
|
||||||
assertThat(context.getBean(MissingFallbackFactoryConfiguration.Client.class))
|
|
||||||
.isNotNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testWrongFallbackFactoryType() {
|
|
||||||
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
|
||||||
WrongFallbackFactoryTypeConfiguration.class)) {
|
|
||||||
this.expected.expectMessage("Incompatible fallbackFactory instance");
|
|
||||||
assertThat(
|
|
||||||
context.getBean(WrongFallbackFactoryTypeConfiguration.Client.class))
|
|
||||||
.isNotNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import(FeignAutoConfiguration.class)
|
@Import(FeignAutoConfiguration.class)
|
||||||
@EnableFeignClients(clients = NameAndValueConfiguration.Client.class)
|
@EnableFeignClients(clients = NameAndValueConfiguration.Client.class)
|
||||||
@@ -135,53 +56,38 @@ public class FeignClientValidationTests {
|
|||||||
|
|
||||||
@FeignClient(value = "foo", name = "bar")
|
@FeignClient(value = "foo", name = "bar")
|
||||||
interface Client {
|
interface Client {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/")
|
@RequestMapping(method = RequestMethod.GET, value = "/")
|
||||||
String get();
|
String get();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testServiceIdAndValue() {
|
||||||
|
this.expected.expectMessage("only one is permitted");
|
||||||
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||||
|
NameAndValueConfiguration.class);
|
||||||
|
assertNotNull(context.getBean(NameAndServiceIdConfiguration.Client.class));
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import({ FeignAutoConfiguration.class, HttpClientConfiguration.class })
|
@Import(FeignAutoConfiguration.class)
|
||||||
@EnableFeignClients(clients = NameAndServiceIdConfiguration.Client.class)
|
@EnableFeignClients(clients = NameAndServiceIdConfiguration.Client.class)
|
||||||
protected static class NameAndServiceIdConfiguration {
|
protected static class NameAndServiceIdConfiguration {
|
||||||
|
|
||||||
@FeignClient(name = "bar", serviceId = "foo")
|
@FeignClient(serviceId = "foo", name = "bar")
|
||||||
interface Client {
|
interface Client {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/")
|
@RequestMapping(method = RequestMethod.GET, value = "/")
|
||||||
String get();
|
String get();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Test
|
||||||
|
public void testNotLegalHostname() {
|
||||||
@Import({ FeignAutoConfiguration.class, HttpClientConfiguration.class })
|
this.expected.expectMessage("not legal hostname (foo_bar)");
|
||||||
@EnableFeignClients(clients = {
|
new AnnotationConfigApplicationContext(BadHostnameConfiguration.class);
|
||||||
DuplicatedFeignClientNamesConfiguration.FooClient.class,
|
|
||||||
DuplicatedFeignClientNamesConfiguration.BarClient.class })
|
|
||||||
protected static class DuplicatedFeignClientNamesConfiguration {
|
|
||||||
|
|
||||||
@FeignClient(contextId = "foo", name = "bar")
|
|
||||||
interface FooClient {
|
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/")
|
|
||||||
String get();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@FeignClient(name = "bar")
|
|
||||||
interface BarClient {
|
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/")
|
|
||||||
String get();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@@ -191,41 +97,53 @@ public class FeignClientValidationTests {
|
|||||||
|
|
||||||
@FeignClient("foo_bar")
|
@FeignClient("foo_bar")
|
||||||
interface Client {
|
interface Client {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/")
|
@RequestMapping(method = RequestMethod.GET, value = "/")
|
||||||
String get();
|
String get();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMissingFallback() {
|
||||||
|
try (
|
||||||
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||||
|
MissingFallbackConfiguration.class)) {
|
||||||
|
this.expected.expectMessage("No fallback instance of type");
|
||||||
|
assertNotNull(context.getBean(MissingFallbackConfiguration.Client.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import(FeignAutoConfiguration.class)
|
@Import(FeignAutoConfiguration.class)
|
||||||
@EnableFeignClients(clients = MissingFallbackConfiguration.Client.class)
|
@EnableFeignClients(clients = MissingFallbackConfiguration.Client.class)
|
||||||
protected static class MissingFallbackConfiguration {
|
protected static class MissingFallbackConfiguration {
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Feign.Builder feignBuilder() {
|
|
||||||
return HystrixFeign.builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
@FeignClient(name = "foobar", url = "http://localhost", fallback = ClientFallback.class)
|
@FeignClient(name = "foobar", url = "http://localhost", fallback = ClientFallback.class)
|
||||||
interface Client {
|
interface Client {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/")
|
@RequestMapping(method = RequestMethod.GET, value = "/")
|
||||||
String get();
|
String get();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClientFallback implements Client {
|
class ClientFallback implements Client {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String get() {
|
public String get() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Feign.Builder feignBuilder() {
|
||||||
|
return HystrixFeign.builder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWrongFallbackType() {
|
||||||
|
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||||
|
WrongFallbackTypeConfiguration.class)) {
|
||||||
|
this.expected.expectMessage("Incompatible fallback instance");
|
||||||
|
assertNotNull(context.getBean(WrongFallbackTypeConfiguration.Client.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@@ -233,28 +151,34 @@ public class FeignClientValidationTests {
|
|||||||
@EnableFeignClients(clients = WrongFallbackTypeConfiguration.Client.class)
|
@EnableFeignClients(clients = WrongFallbackTypeConfiguration.Client.class)
|
||||||
protected static class WrongFallbackTypeConfiguration {
|
protected static class WrongFallbackTypeConfiguration {
|
||||||
|
|
||||||
|
@FeignClient(name = "foobar", url = "http://localhost", fallback = Dummy.class)
|
||||||
|
interface Client {
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = "/")
|
||||||
|
String get();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
Dummy dummy() {
|
Dummy dummy() {
|
||||||
return new Dummy();
|
return new Dummy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Dummy {
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Feign.Builder feignBuilder() {
|
public Feign.Builder feignBuilder() {
|
||||||
return HystrixFeign.builder();
|
return HystrixFeign.builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@FeignClient(name = "foobar", url = "http://localhost", fallback = Dummy.class)
|
}
|
||||||
interface Client {
|
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/")
|
|
||||||
String get();
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMissingFallbackFactory() {
|
||||||
|
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||||
|
MissingFallbackFactoryConfiguration.class)) {
|
||||||
|
this.expected.expectMessage("No fallbackFactory instance of type");
|
||||||
|
assertNotNull(context.getBean(MissingFallbackFactoryConfiguration.Client.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
class Dummy {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@@ -262,17 +186,10 @@ public class FeignClientValidationTests {
|
|||||||
@EnableFeignClients(clients = MissingFallbackFactoryConfiguration.Client.class)
|
@EnableFeignClients(clients = MissingFallbackFactoryConfiguration.Client.class)
|
||||||
protected static class MissingFallbackFactoryConfiguration {
|
protected static class MissingFallbackFactoryConfiguration {
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Feign.Builder feignBuilder() {
|
|
||||||
return HystrixFeign.builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
@FeignClient(name = "foobar", url = "http://localhost", fallbackFactory = ClientFallback.class)
|
@FeignClient(name = "foobar", url = "http://localhost", fallbackFactory = ClientFallback.class)
|
||||||
interface Client {
|
interface Client {
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/")
|
@RequestMapping(method = RequestMethod.GET, value = "/")
|
||||||
String get();
|
String get();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClientFallback implements FallbackFactory<Client> {
|
class ClientFallback implements FallbackFactory<Client> {
|
||||||
@@ -281,9 +198,21 @@ public class FeignClientValidationTests {
|
|||||||
public Client create(Throwable cause) {
|
public Client create(Throwable cause) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Feign.Builder feignBuilder() {
|
||||||
|
return HystrixFeign.builder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWrongFallbackFactoryType() {
|
||||||
|
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||||
|
WrongFallbackFactoryTypeConfiguration.class)) {
|
||||||
|
this.expected.expectMessage("Incompatible fallbackFactory instance");
|
||||||
|
assertNotNull(context.getBean(WrongFallbackFactoryTypeConfiguration.Client.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@@ -291,28 +220,24 @@ public class FeignClientValidationTests {
|
|||||||
@EnableFeignClients(clients = WrongFallbackFactoryTypeConfiguration.Client.class)
|
@EnableFeignClients(clients = WrongFallbackFactoryTypeConfiguration.Client.class)
|
||||||
protected static class WrongFallbackFactoryTypeConfiguration {
|
protected static class WrongFallbackFactoryTypeConfiguration {
|
||||||
|
|
||||||
|
@FeignClient(name = "foobar", url = "http://localhost", fallbackFactory = Dummy.class)
|
||||||
|
interface Client {
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = "/")
|
||||||
|
String get();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
Dummy dummy() {
|
Dummy dummy() {
|
||||||
return new Dummy();
|
return new Dummy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Dummy {
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Feign.Builder feignBuilder() {
|
public Feign.Builder feignBuilder() {
|
||||||
return HystrixFeign.builder();
|
return HystrixFeign.builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@FeignClient(name = "foobar", url = "http://localhost", fallbackFactory = Dummy.class)
|
|
||||||
interface Client {
|
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/")
|
|
||||||
String get();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class Dummy {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-14
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2019 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -23,11 +23,10 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryFactory;
|
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryFactory;
|
||||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -57,13 +56,13 @@ public class CachingSpringLoadBalancerFactoryTests {
|
|||||||
when(this.delegate.getClientConfig("client2")).thenReturn(config);
|
when(this.delegate.getClientConfig("client2")).thenReturn(config);
|
||||||
|
|
||||||
this.factory = new CachingSpringLoadBalancerFactory(this.delegate,
|
this.factory = new CachingSpringLoadBalancerFactory(this.delegate,
|
||||||
this.loadBalancedRetryFactory);
|
loadBalancedRetryFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void delegateCreatesWhenMissing() {
|
public void delegateCreatesWhenMissing() {
|
||||||
FeignLoadBalancer client = this.factory.create("client1");
|
FeignLoadBalancer client = this.factory.create("client1");
|
||||||
assertThat(client).as("client was null").isNotNull();
|
assertNotNull("client was null", client);
|
||||||
|
|
||||||
verify(this.delegate, times(1)).getClientConfig("client1");
|
verify(this.delegate, times(1)).getClientConfig("client1");
|
||||||
}
|
}
|
||||||
@@ -71,10 +70,10 @@ public class CachingSpringLoadBalancerFactoryTests {
|
|||||||
@Test
|
@Test
|
||||||
public void cacheWorks() {
|
public void cacheWorks() {
|
||||||
FeignLoadBalancer client = this.factory.create("client2");
|
FeignLoadBalancer client = this.factory.create("client2");
|
||||||
assertThat(client).as("client was null").isNotNull();
|
assertNotNull("client was null", client);
|
||||||
|
|
||||||
client = this.factory.create("client2");
|
client = this.factory.create("client2");
|
||||||
assertThat(client).as("client was null").isNotNull();
|
assertNotNull("client was null", client);
|
||||||
|
|
||||||
verify(this.delegate, times(1)).getClientConfig("client2");
|
verify(this.delegate, times(1)).getClientConfig("client2");
|
||||||
}
|
}
|
||||||
@@ -85,10 +84,9 @@ public class CachingSpringLoadBalancerFactoryTests {
|
|||||||
config.set(CommonClientConfigKey.ConnectTimeout, 1000);
|
config.set(CommonClientConfigKey.ConnectTimeout, 1000);
|
||||||
config.set(CommonClientConfigKey.ReadTimeout, 500);
|
config.set(CommonClientConfigKey.ReadTimeout, 500);
|
||||||
when(this.delegate.getClientConfig("retry")).thenReturn(config);
|
when(this.delegate.getClientConfig("retry")).thenReturn(config);
|
||||||
CachingSpringLoadBalancerFactory factory = new CachingSpringLoadBalancerFactory(
|
CachingSpringLoadBalancerFactory factory = new CachingSpringLoadBalancerFactory(this.delegate);
|
||||||
this.delegate);
|
|
||||||
FeignLoadBalancer client = this.factory.create("retry");
|
FeignLoadBalancer client = this.factory.create("retry");
|
||||||
assertThat(client).as("client was null").isNotNull();
|
assertNotNull("client was null", client);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -97,10 +95,8 @@ public class CachingSpringLoadBalancerFactoryTests {
|
|||||||
config.set(CommonClientConfigKey.ConnectTimeout, 1000);
|
config.set(CommonClientConfigKey.ConnectTimeout, 1000);
|
||||||
config.set(CommonClientConfigKey.ReadTimeout, 500);
|
config.set(CommonClientConfigKey.ReadTimeout, 500);
|
||||||
when(this.delegate.getClientConfig("retry")).thenReturn(config);
|
when(this.delegate.getClientConfig("retry")).thenReturn(config);
|
||||||
CachingSpringLoadBalancerFactory factory = new CachingSpringLoadBalancerFactory(
|
CachingSpringLoadBalancerFactory factory = new CachingSpringLoadBalancerFactory(this.delegate, loadBalancedRetryFactory);
|
||||||
this.delegate, this.loadBalancedRetryFactory);
|
|
||||||
FeignLoadBalancer client = this.factory.create("retry");
|
FeignLoadBalancer client = this.factory.create("retry");
|
||||||
assertThat(client).as("client was null").isNotNull();
|
assertNotNull("client was null", client);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user