KeyedCircuitBreakerMapping implements CircuitBreakerMapping { @Override public CircuitBreaker get(ClientRequestContext ctx, Request req) throws Exception { final String key; final String host; final String method; switch (mappingKey) { case HOST: key = host = host(ctx); method = null; break; case METHOD: host = null; key = method = method(ctx); break; case HOST_AND_METHOD: host = host(ctx); method = method(ctx); key = host + '#' + method; break; default: throw new Error(); } final CircuitBreaker circuitBreaker = mapping.get(key); if (circuitBreaker != null) { return circuitBreaker; } return mapping.computeIfAbsent(key, mapKey -> factory.apply(host, method)); } KeyedCircuitBreakerMapping(MappingKey mappingKey,
                               BiFunction<String, String, ? extends CircuitBreaker> factory); @Override CircuitBreaker get(ClientRequestContext ctx, Request req);  }
@Test void hostSelector() throws Exception { final CircuitBreaker a = mock(CircuitBreaker.class); final CircuitBreaker b = mock(CircuitBreaker.class); final CircuitBreaker c = mock(CircuitBreaker.class); final CircuitBreaker d = mock(CircuitBreaker.class); final CircuitBreaker e = mock(CircuitBreaker.class); final Function<String, ? extends CircuitBreaker> factory = host -> { if ("foo".equals(host)) { return a; } if ("foo:8080".equals(host)) { return b; } if ("foo/1.2.3.4".equals(host)) { return c; } if ("1.2.3.4:80".equals(host)) { return d; } if ("[::1]:80".equals(host)) { return e; } return null; }; final CircuitBreakerMapping breakerMapping = CircuitBreakerMapping.perHost(factory); assertThat(breakerMapping.get(context(Endpoint.of("foo")), req)).isSameAs(a); assertThat(breakerMapping.get(context(Endpoint.of("foo", 8080)), req)).isSameAs(b); assertThat(breakerMapping.get(context(Endpoint.of("foo").withIpAddr("1.2.3.4")), req)).isSameAs(c); assertThat(breakerMapping.get(context(Endpoint.of("1.2.3.4", 80)), req)).isSameAs(d); assertThat(breakerMapping.get(context(Endpoint.of("::1", 80)), req)).isSameAs(e); assertThat(breakerMapping.get(context(Endpoint.of("bar")), req)).isNull(); }