From 76367fe03e1a60c5640ffef4db92e14d10a56c84 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sun, 1 Feb 2015 12:35:50 -0800 Subject: [PATCH] Adds EmptyTarget for interfaces who exclusively declare URI methods Supports cases when the base url isn't known until runtime. Closes #98 --- CHANGELOG.md | 3 + core/src/main/java/feign/Target.java | 60 +++++++++++++++++++ core/src/test/java/feign/EmptyTargetTest.java | 54 +++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 core/src/test/java/feign/EmptyTargetTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 61f3ae94..2a6c1344 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ * Removes support for parameters annotated with `javax.inject.@Named`. Use `feign.@Param` instead. * Makes body parameter type explicit. +### Version 7.2 +* Adds EmptyTarget for interfaces who exclusively declare URI methods + ### Version 7.1 * Introduces feign.@Param to annotate template parameters. Users must migrate from `javax.inject.@Named` to `feign.@Param` before updating to Feign 8.0. * Supports custom expansion via `@Param(value = "name", expander = CustomExpander.class)` diff --git a/core/src/main/java/feign/Target.java b/core/src/main/java/feign/Target.java index 474ed297..c161017b 100644 --- a/core/src/main/java/feign/Target.java +++ b/core/src/main/java/feign/Target.java @@ -118,4 +118,64 @@ public interface Target { return "HardCodedTarget(type=" + type.getSimpleName() + ", name=" + name + ", url=" + url + ")"; } } + + public static final class EmptyTarget implements Target { + private final Class type; + private final String name; + + EmptyTarget(Class type, String name) { + this.type = checkNotNull(type, "type"); + this.name = checkNotNull(emptyToNull(name), "name"); + } + + public static EmptyTarget create(Class type) { + return new EmptyTarget(type, "empty:" + type.getSimpleName()); + } + + public static EmptyTarget create(Class type, String name) { + return new EmptyTarget(type, name); + } + + @Override public Class type() { + return type; + } + + @Override public String name() { + return name; + } + + @Override public String url() { + throw new UnsupportedOperationException("Empty targets don't have URLs"); + } + + @Override public Request apply(RequestTemplate input) { + if (input.url().indexOf("http") != 0) { + throw new UnsupportedOperationException("Request with non-absolute URL not supported with empty target"); + } + return input.request(); + } + + @Override public boolean equals(Object obj) { + if (obj instanceof EmptyTarget) { + EmptyTarget other = (EmptyTarget) obj; + return type.equals(other.type) + && name.equals(other.name); + } + return false; + } + + @Override public int hashCode() { + int result = 17; + result = 31 * result + type.hashCode(); + result = 31 * result + name.hashCode(); + return result; + } + + @Override public String toString() { + if (name.equals("empty:" + type.getSimpleName())) { + return "EmptyTarget(type=" + type.getSimpleName() + ")"; + } + return "EmptyTarget(type=" + type.getSimpleName() + ", name=" + name + ")"; + } + } } diff --git a/core/src/test/java/feign/EmptyTargetTest.java b/core/src/test/java/feign/EmptyTargetTest.java new file mode 100644 index 00000000..b90a71ba --- /dev/null +++ b/core/src/test/java/feign/EmptyTargetTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015 Netflix, Inc. + * + * 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 + * + * http://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 feign; + +import feign.Target.EmptyTarget; +import java.net.URI; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static feign.assertj.FeignAssertions.assertThat; + +public class EmptyTargetTest { + @Rule public final ExpectedException thrown = ExpectedException.none(); + + interface UriInterface { + @RequestLine("GET /") Response get(URI endpoint); + } + + @Test public void whenNameNotSupplied() { + assertThat(EmptyTarget.create(UriInterface.class)) + .isEqualTo(EmptyTarget.create(UriInterface.class, "empty:UriInterface")); + } + + @Test public void toString_withoutName() { + assertThat(EmptyTarget.create(UriInterface.class).toString()) + .isEqualTo("EmptyTarget(type=UriInterface)"); + } + + @Test public void toString_withName() { + assertThat(EmptyTarget.create(UriInterface.class, "manager-access").toString()) + .isEqualTo("EmptyTarget(type=UriInterface, name=manager-access)"); + } + + @Test public void mustApplyToAbsoluteUrl() { + thrown.expect(UnsupportedOperationException.class); + thrown.expectMessage("Request with non-absolute URL not supported with empty target"); + + EmptyTarget.create(UriInterface.class).apply(new RequestTemplate().method("GET").append("/relative")); + } +}