Skip to content
This repository has been archived by the owner on Dec 8, 2021. It is now read-only.

Commit

Permalink
fix(endpoint): Do not resolve an endpoint if reference is unknown or …
Browse files Browse the repository at this point in the history
…invalid

Closes gravitee-io/issues#1515
  • Loading branch information
brasseld authored and NicolasGeraud committed Oct 16, 2018
1 parent 24287eb commit 6ff67bd
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 7 deletions.
Expand Up @@ -23,6 +23,8 @@
*/
public interface Reference {

String UNKNOWN_REFERENCE = "ref:unknown";

String key();

String name();
Expand Down
Expand Up @@ -23,6 +23,9 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -72,6 +75,141 @@ public void provide(TemplateContext context) {
entry -> entry.getValue().name(),
entry -> entry.getKey() + ':'));

context.setVariable(TEMPLATE_VARIABLE_KEY, refs);
context.setVariable(TEMPLATE_VARIABLE_KEY, new EndpointReferenceMap(refs));
}

private static class EndpointReferenceMap implements Map<String, String> {

private final Map<String, String> wrapped;

EndpointReferenceMap(Map<String, String> wrapped) {
this.wrapped = wrapped;
}

@Override
public int size() {
return wrapped.size();
}

@Override
public boolean isEmpty() {
return wrapped.isEmpty();
}

@Override
public boolean containsKey(Object key) {
return wrapped.containsKey(key);
}

@Override
public boolean containsValue(Object value) {
return wrapped.containsValue(value);
}

@Override
public String get(Object key) {
String reference = wrapped.get(key);
return (reference != null) ? reference : Reference.UNKNOWN_REFERENCE;
}

@Override
public String put(String key, String value) {
return wrapped.put(key, value);
}

@Override
public String remove(Object key) {
return wrapped.remove(key);
}

@Override
public void putAll(Map<? extends String, ? extends String> m) {
wrapped.putAll(m);
}

@Override
public void clear() {
wrapped.clear();
}

@Override
public Set<String> keySet() {
return wrapped.keySet();
}

@Override
public Collection<String> values() {
return wrapped.values();
}

@Override
public Set<Entry<String, String>> entrySet() {
return wrapped.entrySet();
}

@Override
public boolean equals(Object o) {
return wrapped.equals(o);
}

@Override
public int hashCode() {
return wrapped.hashCode();
}

@Override
public String getOrDefault(Object key, String defaultValue) {
return wrapped.getOrDefault(key, defaultValue);
}

@Override
public void forEach(BiConsumer<? super String, ? super String> action) {
wrapped.forEach(action);
}

@Override
public void replaceAll(BiFunction<? super String, ? super String, ? extends String> function) {
wrapped.replaceAll(function);
}

@Override
public String putIfAbsent(String key, String value) {
return wrapped.putIfAbsent(key, value);
}

@Override
public boolean remove(Object key, Object value) {
return wrapped.remove(key, value);
}

@Override
public boolean replace(String key, String oldValue, String newValue) {
return wrapped.replace(key, oldValue, newValue);
}

@Override
public String replace(String key, String value) {
return wrapped.replace(key, value);
}

@Override
public String computeIfAbsent(String key, Function<? super String, ? extends String> mappingFunction) {
return wrapped.computeIfAbsent(key, mappingFunction);
}

@Override
public String computeIfPresent(String key, BiFunction<? super String, ? super String, ? extends String> remappingFunction) {
return wrapped.computeIfPresent(key, remappingFunction);
}

@Override
public String compute(String key, BiFunction<? super String, ? super String, ? extends String> remappingFunction) {
return wrapped.compute(key, remappingFunction);
}

@Override
public String merge(String key, String value, BiFunction<? super String, ? super String, ? extends String> remappingFunction) {
return wrapped.merge(key, value, remappingFunction);
}
}
}
Expand Up @@ -119,16 +119,19 @@ private ResolvedEndpoint selectUserDefinedEndpoint(Request serverRequest, String
Endpoint endpoint = reference.endpoint();

return createEndpoint(endpoint, encodedTarget.replaceFirst(sRef + ':', endpoint.target()));
} else if (encodedTarget.startsWith(Reference.UNKNOWN_REFERENCE)) {
return null;
} else {
// Try to match an endpoint according to the target URL
// When the user selected endpoint which is not defined (according to the given target), the gateway
// is always returning the first endpoints reference and took into account its configuration.
Collection<Reference> endpoints = referenceRegister.referencesByType(EndpointReference.class);
Reference reference = endpoints
.stream()
.filter(endpointEntry -> encodedTarget.startsWith(endpointEntry.endpoint().target()))
.findFirst()
.orElse(endpoints.iterator().next());

return createEndpoint(reference.endpoint(), encodedTarget);
return (reference != null) ? createEndpoint(reference.endpoint(), encodedTarget) : null;
}
}
}
Expand Down
Expand Up @@ -58,6 +58,7 @@ public class EndpointInvoker implements Invoker {
public Request invoke(ExecutionContext executionContext, Request serverRequest, ReadStream<Buffer> stream, Handler<ProxyConnection> connectionHandler) {
EndpointResolver.ResolvedEndpoint endpoint = endpointResolver.resolve(serverRequest, executionContext);

// Endpoint can be null if none endpoint can be selected or if the selected endpoint is unavailable
if (endpoint == null) {
DirectProxyConnection statusOnlyConnection = new DirectProxyConnection(HttpStatusCode.SERVICE_UNAVAILABLE_503);
connectionHandler.handle(statusOnlyConnection);
Expand Down
Expand Up @@ -78,7 +78,6 @@ public void shouldResolveUserDefinedEndpoint_selectFirstEndpoint() {
.thenAnswer(invocation -> Collections.singleton(new EndpointReference(endpoint)));

EndpointResolver.ResolvedEndpoint resolvedEndpoint = resolver.resolve(serverRequest, executionContext);

Assert.assertEquals(targetUri, resolvedEndpoint.getUri());
}

Expand Down
Expand Up @@ -210,8 +210,6 @@ private HttpMethod convert(io.gravitee.common.http.HttpMethod httpMethod) {

@Override
protected void doStart() throws Exception {
// TODO: Prepare HttpClientOptions according to the endpoint to improve performance when creating a new
// instance of the Vertx client
httpClientOptions = new HttpClientOptions();

httpClientOptions.setPipelining(endpoint.getHttpClientOptions().isPipelining());
Expand Down
Expand Up @@ -7,7 +7,7 @@
"endpoints": [
{
"name": "default",
"target": "http://bad_url_but_overriden:8080/team"
"target": "http://localhost:8080/team"
}
],
"strip_context_path": false,
Expand Down

0 comments on commit 6ff67bd

Please sign in to comment.