I mistakenly advised `@Headers` to follow the encoding rules of `@Body`.
This was a a mistake as in both cases, url encoding is a bad choice, if
the only goal is to prevent accidental variable expansion. For example,
url encoding interferes a lot with content, including messing with '+'
characters, such as exist in "Accept: application/vnd.github.v3+json"
This changes `@Headers` to only address the problem, which where a '{'
literal is desired in a header value. The solution offered here is to
simply repeat "{{" when you desire a '{' literal. For example, if your
header value needs to be literally "{{variable}}", you'd encode it as
"{{{{variable}}".
The impact of this change is limited to those who have already started
using v8.15, and a fast release will occur after merge to limit that.
See #326Fixes#345Closes#346
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`.
Uses covariant overrides so that those collecting Feign configuration
via `Feign.Builder` can cast into `HystrixFeign.builder` to target an
api.
Closes#313
Before this change, if someone accidentally left out the HTTP method in
a `@RequestLine` annotation, they'd get an undecipherable error like:
"Body parameters cannot be used with form parameters." from Contract.java.
This makes the omission easier to find by changing the message to:
"RequestLine annotation didn't start with an HTTP verb..."
Fixes#310
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!
Removing exception wrapping adds flexibility to the interplay of Decoder and ErrorDecoder:
A Decoder can now delegate to an ErrorDecoder and the original ErrorDecoder exception gets
thrown rather than a Feign-specific DecodeException. An example use-case is a Jackson/Gson
implementation of special 404-handling of Optional<Foo> methods: when the Feign client has
decode404() enabled, then the Decoder is in charge of dispatching 404 to Optional#absent
where applicable, or to a delegate ErrorDecoder otherwise; consistent exception handling
requires that the exception produced by the ErrorDecoder does not wrapped.