Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #4421 - HttpClient support for PROXY protocol. #4424

Merged
merged 3 commits into from
Dec 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -530,16 +530,29 @@ public Destination getDestination(String scheme, String host, int port)
}

protected HttpDestination destinationFor(String scheme, String host, int port)
{
return resolveDestination(scheme, host, port, null);
}

protected HttpDestination resolveDestination(String scheme, String host, int port, Object tag)
{
Origin origin = createOrigin(scheme, host, port, tag);
return resolveDestination(origin);
}

protected Origin createOrigin(String scheme, String host, int port, Object tag)
{
if (!HttpScheme.HTTP.is(scheme) && !HttpScheme.HTTPS.is(scheme) &&
!HttpScheme.WS.is(scheme) && !HttpScheme.WSS.is(scheme))
throw new IllegalArgumentException("Invalid protocol " + scheme);

scheme = scheme.toLowerCase(Locale.ENGLISH);
host = host.toLowerCase(Locale.ENGLISH);
port = normalizePort(scheme, port);
return new Origin(scheme, host, port, tag);
}

Origin origin = new Origin(scheme, host, port);
protected HttpDestination resolveDestination(Origin origin)
{
return destinations.computeIfAbsent(origin, o ->
{
HttpDestination newDestination = getTransport().newHttpDestination(o);
Expand All @@ -566,7 +579,7 @@ public List<Destination> getDestinations()

protected void send(final HttpRequest request, List<Response.ResponseListener> listeners)
{
HttpDestination destination = destinationFor(request.getScheme(), request.getHost(), request.getPort());
HttpDestination destination = resolveDestination(request.getScheme(), request.getHost(), request.getPort(), request.getTag());
destination.send(request, listeners);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ public HttpDestination(HttpClient client, Origin origin)
if (isSecure())
connectionFactory = newSslClientConnectionFactory(null, connectionFactory);
}
Object tag = origin.getTag();
if (tag instanceof ClientConnectionFactory.Decorator)
connectionFactory = ((ClientConnectionFactory.Decorator)tag).apply(connectionFactory);
this.connectionFactory = connectionFactory;

String host = HostPort.normalizeHost(getHost());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public URI getURI()
return URI.create(new Origin(scheme, getAddress()).asString());
}

private class HttpProxyClientConnectionFactory implements ClientConnectionFactory
private static class HttpProxyClientConnectionFactory implements ClientConnectionFactory
{
private final ClientConnectionFactory connectionFactory;

Expand Down Expand Up @@ -127,7 +127,7 @@ public org.eclipse.jetty.io.Connection newConnection(EndPoint endPoint, Map<Stri
* tunnel after the TCP connection is succeeded, and needs to notify
* the nested promise when the tunnel is established (or failed).</p>
*/
private class CreateTunnelPromise implements Promise<Connection>
private static class CreateTunnelPromise implements Promise<Connection>
{
private final ClientConnectionFactory connectionFactory;
private final EndPoint endPoint;
Expand Down Expand Up @@ -233,7 +233,7 @@ private void tunnelFailed(EndPoint endPoint, Throwable failure)
}
}

private class ProxyConnection implements Connection
private static class ProxyConnection implements Connection
{
private final Destination destination;
private final Connection connection;
Expand Down Expand Up @@ -272,7 +272,7 @@ public boolean isClosed()
}
}

private class TunnelPromise implements Promise<Connection>
private static class TunnelPromise implements Promise<Connection>
{
private final Request request;
private final Response.CompleteListener listener;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public class HttpRequest implements Request
private List<RequestListener> requestListeners;
private BiFunction<Request, Request, Response.CompleteListener> pushListener;
private Supplier<HttpFields> trailers;
private Object tag;

protected HttpRequest(HttpClient client, HttpConversation conversation, URI uri)
{
Expand Down Expand Up @@ -313,6 +314,19 @@ public Request cookie(HttpCookie cookie)
return this;
}

@Override
public Request tag(Object tag)
{
this.tag = tag;
return this;
}

@Override
public Object getTag()
{
return tag;
}

@Override
public Request attribute(String name, Object value)
{
Expand Down
34 changes: 30 additions & 4 deletions jetty-client/src/main/java/org/eclipse/jetty/client/Origin.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,28 @@ public class Origin
{
private final String scheme;
private final Address address;
private final Object tag;

public Origin(String scheme, String host, int port)
{
this(scheme, new Address(host, port));
this(scheme, host, port, null);
}

public Origin(String scheme, String host, int port, Object tag)
{
this(scheme, new Address(host, port), tag);
}

public Origin(String scheme, Address address)
{
this(scheme, address, null);
}

public Origin(String scheme, Address address, Object tag)
{
this.scheme = Objects.requireNonNull(scheme);
this.address = address;
this.tag = tag;
}

public String getScheme()
Expand All @@ -48,6 +60,11 @@ public Address getAddress()
return address;
}

public Object getTag()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is javadoc needed here to indicate that this is the same tag from the associated request?

{
return tag;
}

public String asString()
{
StringBuilder result = new StringBuilder();
Expand All @@ -63,14 +80,23 @@ public boolean equals(Object obj)
if (obj == null || getClass() != obj.getClass())
return false;
Origin that = (Origin)obj;
return scheme.equals(that.scheme) && address.equals(that.address);
return scheme.equals(that.scheme) &&
address.equals(that.address) &&
Objects.equals(tag, that.tag);
}

@Override
public int hashCode()
{
int result = scheme.hashCode();
result = 31 * result + address.hashCode();
return Objects.hash(scheme, address, tag);
gregw marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
public String toString()
{
String result = asString();
if (tag != null)
result += "[tag=" + tag + "]";
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public Proxy match(Origin origin)

public abstract static class Proxy
{
// TO use IPAddress Map
// TODO use InetAddressSet? Or IncludeExcludeSet?
private final Set<String> included = new HashSet<>();
private final Set<String> excluded = new HashSet<>();
private final Origin.Address address;
Expand Down
Loading