I've noticed myself repeating instructions around the change log. This places guidance in the CONTRIBUTING section, as that's slightly more relevant than HACKING as it already includes policy such as license and code style.
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!