* Avoid `Decoder.decode` on 404 when void response type
Avoid calling `decode` when receiving a 404 error and `decode404` is set and the response type is `void`.
* Update CHANGELOG
The cause of the fallback is now logged by default to FINE level. You can programmatically inspect
the cause by making your own `FallbackFactory`. In many cases, the cause will be a `FeignException`,
which includes the http status.
Here's an example of using `FallbackFactory`:
```java
// This instance will be invoked if there are errors of any kind.
FallbackFactory<GitHub> fallbackFactory = cause -> (owner, repo) -> {
if (cause instanceof FeignException && ((FeignException) cause).status() == 403) {
return Collections.emptyList();
} else {
return Arrays.asList("yogi");
}
};
GitHub github = HystrixFeign.builder()
...
.target(GitHub.class, "https://api.github.com", fallbackFactory);
```
This exposes means to customize group and command keys, for example to
use non-default conventions from configuration or custom annotation
processing.
Ex.
```java
SetterFactory commandKeyIsRequestLine = (target, method) -> {
String groupKey = target.name();
String commandKey = method.getAnnotation(RequestLine.class).value();
return HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey));
};
api = HystrixFeign.builder()
.setterFactory(commandKeyIsRequestLine)
...
```
This also makes the default's more unique to avoid clashing in Hystrix's
cache.
Before, `LoadBalancingTarget` stripped out the path and only used
`URI.getScheme()` and `URI.getHost()` to generate the `Request`.
Now, it will add `URI.getPath()` to the `Request` as well; this is
useful if you want to interact with endpoints with a context-path.
Update README.md Travis CI to point to correct git repository
OkHttp client should not bail out when response body is >2gb
Instead, we return null length and the response can be processed
similarly to a chunked body.
Also, shares common client tests in AbstractClientTest
Add @HeaderMap parameter annotation that allows
methods to have an annotated Map parameter whose
contents is used to set the header values on the
request. Provides a way for APIs to allow for
per-request header customization for both fields
and values without customizing the Feign client.
This supports runtime injection of Param.Expander. Implementing
contracts will assign `MethodMetadata.indexToExpander` using configured
values. When `MethodMetadata.indexToExpander` is unset, Feign has the
existing behavior, which is to newInstance each `indexToExpanderClass`.
Fallbacks are known values, which you return when there's an error invoking an http method.
For example, you can return a cached result as opposed to raising an error to the caller. To use
this feature, pass a safe implementation of your target interface as the last parameter to `HystrixFeign.Builder.target`.
Here's an example:
```java
// When dealing with fallbacks, it is less tedious to keep interfaces small.
interface GitHub {
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<String> contributors(@Param("owner") String owner, @Param("repo") String repo);
}
// This instance will be invoked if there are errors of any kind.
GitHub fallback = (owner, repo) -> {
if (owner.equals("Netflix") && repo.equals("feign")) {
return Arrays.asList("stuarthendren"); // inspired this approach!
} else {
return Collections.emptyList();
}
};
GitHub github = HystrixFeign.builder()
...
.target(GitHub.class, "https://api.github.com", fallback);
```
Credit to the idea goes to @stuarthendren!
This adds the `Feign.Builder.decode404()` flag which indicates decoders
should process responses with 404 status. It also changes all
first-party decoders (like gson) to return well-known empty values by
default. Further customization is possible by wrapping or creating a
custom decoder.
Prior to this change, we used custom invocation handlers as the way to
add fallback values based on exception or return status. `feign-hystrix`
uses this to return `HystrixCommand<X>`, but the general pattern applies
to anything that has a type representing both success and failure, such
as `Try<X>` or `Observable<X>`.
As we define it here, 404 status is not a retry or fallback policy, it
is just empty semantics. By limiting Feign's special processing to 404,
we gain a lot with very little supporting code.
If instead we opened all codes, Feign could easily turn bad request,
redirect, or server errors silently to null. This sort of configuration
issue is hard to troubleshoot. 404 -> empty is a very safe policy vs
all codes.
Moreover, we don't create a cliff, where folks seeking fallback policy
eventually realize they can't if only given a response code. Fallback
systems like Hystrix address exceptions that occur before or in lieu of
a response. By special-casing 404, we avoid a slippery slope of half-
implementing Hystrix.
Finally, 404 handling has been commonly requested: it has a clear use-
case, and through that value. This design supports that without breaking
compatibility, or impacting existing integrations such as Hystrix or
Ribbon.
See #238#287
In unsuccessful scenarios, such as redirects, error handling converts a
`Response` into an exception. When a user defines a return type as
`Response`, we can assume they will want access to things like headers
even in an error scenario.
See #249
Before this change, apis that follow patterns across a service could
only be modeled by copy/paste/find/replace. Especially with a large
count, this is monotonous and error prone.
This change introduces support for base apis via single-inheritance
interfaces. Users ensure their target interface bind any type variables
and as a result have little effort to create boilerplate apis.
Ex.
```java
@Headers("Accept: application/json")
interface BaseApi<V> {
@RequestLine("GET /api/{key}")
V get(@Param("key") String);
@RequestLine("GET /api")
List<V> list();
@Headers("Content-Type: application/json")
@RequestLine("PUT /api/{key}")
void put(@Param("key") String, V value);
}
interface FooApi extends BaseApi<Foo> { }
interface BarApi extends BaseApi<Bar> { }
```
closes#133
Previously, the Retryer instance provided to the Builder was simply reused, but the instance keeps per-request state, causing repeatable requests to stop being retried. Fixes#236