Merge pull request #5640 from eclipse/jetty-9.4.x-5633-httpclient_configure_authority

Fixes #5633 - Allow to configure HttpClient request authority.
This commit is contained in:
Simone Bordet 2020-11-16 15:41:42 +01:00 committed by GitHub
commit 3cbd117ec9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 13 deletions

View File

@ -562,7 +562,13 @@ public class HttpClient extends ContainerLifeCycle
return new Origin(scheme, host, port, tag); return new Origin(scheme, host, port, tag);
} }
protected HttpDestination resolveDestination(Origin origin) /**
* <p>Returns, creating it if absent, the destination with the given origin.</p>
*
* @param origin the origin that identifies the destination
* @return the destination for the given origin
*/
public HttpDestination resolveDestination(Origin origin)
{ {
return destinations.computeIfAbsent(origin, o -> return destinations.computeIfAbsent(origin, o ->
{ {

View File

@ -120,8 +120,14 @@ public abstract class HttpConnection implements Connection, Attachable
if (version.getVersion() <= 11) if (version.getVersion() <= 11)
{ {
if (!headers.containsKey(HttpHeader.HOST.asString())) if (!headers.containsKey(HttpHeader.HOST.asString()))
{
URI uri = request.getURI();
if (uri != null)
headers.put(HttpHeader.HOST, uri.getAuthority());
else
headers.put(getHttpDestination().getHostField()); headers.put(getHttpDestination().getHostField());
} }
}
// Add content headers // Add content headers
if (content != null) if (content != null)

View File

@ -253,15 +253,13 @@ public abstract class HttpDestination extends ContainerLifeCycle implements Dest
abort(x); abort(x);
} }
public void send(Request request, Response.CompleteListener listener)
{
((HttpRequest)request).sendAsync(this, listener);
}
protected void send(HttpRequest request, List<Response.ResponseListener> listeners) protected void send(HttpRequest request, List<Response.ResponseListener> listeners)
{ {
if (!getScheme().equalsIgnoreCase(request.getScheme()))
throw new IllegalArgumentException("Invalid request scheme " + request.getScheme() + " for destination " + this);
if (!getHost().equalsIgnoreCase(request.getHost()))
throw new IllegalArgumentException("Invalid request host " + request.getHost() + " for destination " + this);
int port = request.getPort();
if (port >= 0 && getPort() != port)
throw new IllegalArgumentException("Invalid request port " + port + " for destination " + this);
send(new HttpExchange(this, request, listeners)); send(new HttpExchange(this, request, listeners));
} }

View File

@ -40,6 +40,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.LongConsumer; import java.util.function.LongConsumer;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -722,7 +723,7 @@ public class HttpRequest implements Request
public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException
{ {
FutureResponseListener listener = new FutureResponseListener(this); FutureResponseListener listener = new FutureResponseListener(this);
send(this, listener); send(listener);
try try
{ {
@ -761,15 +762,20 @@ public class HttpRequest implements Request
@Override @Override
public void send(Response.CompleteListener listener) public void send(Response.CompleteListener listener)
{ {
send(this, listener); sendAsync(client::send, listener);
} }
private void send(HttpRequest request, Response.CompleteListener listener) void sendAsync(HttpDestination destination, Response.CompleteListener listener)
{
sendAsync(destination::send, listener);
}
private void sendAsync(BiConsumer<HttpRequest, List<Response.ResponseListener>> sender, Response.CompleteListener listener)
{ {
if (listener != null) if (listener != null)
responseListeners.add(listener); responseListeners.add(listener);
sent(); sent();
client.send(request, responseListeners); sender.accept(this, responseListeners);
} }
void sent() void sent()

View File

@ -36,6 +36,8 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.HttpDestination;
import org.eclipse.jetty.client.Origin;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Destination; import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
@ -44,7 +46,9 @@ import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.client.util.InputStreamResponseListener; import org.eclipse.jetty.client.util.InputStreamResponseListener;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http2.FlowControlStrategy; import org.eclipse.jetty.http2.FlowControlStrategy;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
@ -733,6 +737,46 @@ public class HttpClientTest extends AbstractTest<TransportScenario>
assertEquals(1, scenario.client.getDestinations().size()); assertEquals(1, scenario.client.getDestinations().size());
} }
@ParameterizedTest
@ArgumentsSource(TransportProvider.class)
public void testRequestWithDifferentDestination(Transport transport) throws Exception
{
init(transport);
String requestScheme = HttpScheme.HTTPS.is(scenario.getScheme()) ? "http" : "https";
String requestHost = "otherHost.com";
int requestPort = 8888;
scenario.start(new EmptyServerHandler()
{
@Override
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response)
{
HttpURI uri = jettyRequest.getHttpURI();
assertEquals(requestHost, uri.getHost());
assertEquals(requestPort, uri.getPort());
if (scenario.transport == Transport.H2C || scenario.transport == Transport.H2)
assertEquals(requestScheme, request.getScheme());
}
});
Origin origin = new Origin(scenario.getScheme(), "localhost", scenario.getNetworkConnectorLocalPortInt().get());
HttpDestination destination = scenario.client.resolveDestination(origin);
org.eclipse.jetty.client.api.Request request = scenario.client.newRequest(requestHost, requestPort)
.scheme(requestScheme)
.path("/path");
CountDownLatch resultLatch = new CountDownLatch(1);
destination.send(request, result ->
{
assertTrue(result.isSucceeded());
assertEquals(HttpStatus.OK_200, result.getResponse().getStatus());
resultLatch.countDown();
});
assertTrue(resultLatch.await(5, TimeUnit.SECONDS));
}
private void sleep(long time) throws IOException private void sleep(long time) throws IOException
{ {
try try