Performance improvements to HTTP client after profiling session.
The profiling suggested to reduce the number of unneeded allocations and this required a couple of API changes.
This commit is contained in:
parent
c9f4513a89
commit
b6e4f98cf7
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.client;
|
package org.eclipse.jetty.client;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -98,7 +99,7 @@ public class AuthenticationProtocolHandler implements ProtocolHandler
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String uri = request.getURI();
|
final URI uri = request.getURI();
|
||||||
Authentication authentication = null;
|
Authentication authentication = null;
|
||||||
WWWAuthenticate wwwAuthenticate = null;
|
WWWAuthenticate wwwAuthenticate = null;
|
||||||
for (WWWAuthenticate wwwAuthn : wwwAuthenticates)
|
for (WWWAuthenticate wwwAuthn : wwwAuthenticates)
|
||||||
|
@ -125,7 +126,7 @@ public class AuthenticationProtocolHandler implements ProtocolHandler
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Request newRequest = client.copyRequest(request, request.getURI());
|
Request newRequest = client.copyRequest(request, uri);
|
||||||
authnResult.apply(newRequest);
|
authnResult.apply(newRequest);
|
||||||
newRequest.onResponseSuccess(new Response.SuccessListener()
|
newRequest.onResponseSuccess(new Response.SuccessListener()
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.client;
|
package org.eclipse.jetty.client;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
@ -29,7 +30,7 @@ import org.eclipse.jetty.client.api.AuthenticationStore;
|
||||||
public class HttpAuthenticationStore implements AuthenticationStore
|
public class HttpAuthenticationStore implements AuthenticationStore
|
||||||
{
|
{
|
||||||
private final List<Authentication> authentications = new CopyOnWriteArrayList<>();
|
private final List<Authentication> authentications = new CopyOnWriteArrayList<>();
|
||||||
private final Map<String, Authentication.Result> results = new ConcurrentHashMap<>();
|
private final Map<URI, Authentication.Result> results = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addAuthentication(Authentication authentication)
|
public void addAuthentication(Authentication authentication)
|
||||||
|
@ -50,7 +51,7 @@ public class HttpAuthenticationStore implements AuthenticationStore
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication findAuthentication(String type, String uri, String realm)
|
public Authentication findAuthentication(String type, URI uri, String realm)
|
||||||
{
|
{
|
||||||
for (Authentication authentication : authentications)
|
for (Authentication authentication : authentications)
|
||||||
{
|
{
|
||||||
|
@ -79,12 +80,12 @@ public class HttpAuthenticationStore implements AuthenticationStore
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication.Result findAuthenticationResult(String uri)
|
public Authentication.Result findAuthenticationResult(URI uri)
|
||||||
{
|
{
|
||||||
// TODO: I should match the longest URI
|
// TODO: I should match the longest URI
|
||||||
for (Map.Entry<String, Authentication.Result> entry : results.entrySet())
|
for (Map.Entry<URI, Authentication.Result> entry : results.entrySet())
|
||||||
{
|
{
|
||||||
if (uri.startsWith(entry.getKey()))
|
if (uri.toString().startsWith(entry.getKey().toString()))
|
||||||
return entry.getValue();
|
return entry.getValue();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -30,14 +30,15 @@ import java.nio.channels.SelectionKey;
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
@ -111,10 +112,10 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
|
|
||||||
private final ConcurrentMap<String, HttpDestination> destinations = new ConcurrentHashMap<>();
|
private final ConcurrentMap<String, HttpDestination> destinations = new ConcurrentHashMap<>();
|
||||||
private final ConcurrentMap<Long, HttpConversation> conversations = new ConcurrentHashMap<>();
|
private final ConcurrentMap<Long, HttpConversation> conversations = new ConcurrentHashMap<>();
|
||||||
private final List<ProtocolHandler> handlers = new CopyOnWriteArrayList<>();
|
private final List<ProtocolHandler> handlers = new ArrayList<>();
|
||||||
private final List<Request.Listener> requestListeners = new CopyOnWriteArrayList<>();
|
private final List<Request.Listener> requestListeners = new ArrayList<>();
|
||||||
private final AuthenticationStore authenticationStore = new HttpAuthenticationStore();
|
private final AuthenticationStore authenticationStore = new HttpAuthenticationStore();
|
||||||
private final Set<ContentDecoder.Factory> decoderFactories = Collections.newSetFromMap(new ConcurrentHashMap<ContentDecoder.Factory, Boolean>());
|
private final Set<ContentDecoder.Factory> decoderFactories = new ContentDecoderFactorySet();
|
||||||
private final SslContextFactory sslContextFactory;
|
private final SslContextFactory sslContextFactory;
|
||||||
private volatile CookieManager cookieManager;
|
private volatile CookieManager cookieManager;
|
||||||
private volatile CookieStore cookieStore;
|
private volatile CookieStore cookieStore;
|
||||||
|
@ -122,7 +123,7 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
private volatile ByteBufferPool byteBufferPool;
|
private volatile ByteBufferPool byteBufferPool;
|
||||||
private volatile Scheduler scheduler;
|
private volatile Scheduler scheduler;
|
||||||
private volatile SelectorManager selectorManager;
|
private volatile SelectorManager selectorManager;
|
||||||
private volatile String agent = "Jetty/" + Jetty.VERSION;
|
private volatile HttpField agentField = new HttpField(HttpHeader.USER_AGENT, "Jetty/" + Jetty.VERSION);
|
||||||
private volatile boolean followRedirects = true;
|
private volatile boolean followRedirects = true;
|
||||||
private volatile int maxConnectionsPerDestination = 64;
|
private volatile int maxConnectionsPerDestination = 64;
|
||||||
private volatile int maxRequestsQueuedPerDestination = 1024;
|
private volatile int maxRequestsQueuedPerDestination = 1024;
|
||||||
|
@ -135,6 +136,7 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
private volatile boolean tcpNoDelay = true;
|
private volatile boolean tcpNoDelay = true;
|
||||||
private volatile boolean dispatchIO = true;
|
private volatile boolean dispatchIO = true;
|
||||||
private volatile ProxyConfiguration proxyConfig;
|
private volatile ProxyConfiguration proxyConfig;
|
||||||
|
private volatile HttpField encodingField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link HttpClient} instance that can perform requests to non-TLS destinations only
|
* Creates a {@link HttpClient} instance that can perform requests to non-TLS destinations only
|
||||||
|
@ -249,6 +251,9 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns a <em>non</em> thread-safe list of {@link Request.Listener}s that can be modified before
|
||||||
|
* performing requests.
|
||||||
|
*
|
||||||
* @return a list of {@link Request.Listener} that can be used to add and remove listeners
|
* @return a list of {@link Request.Listener} that can be used to add and remove listeners
|
||||||
*/
|
*/
|
||||||
public List<Request.Listener> getRequestListeners()
|
public List<Request.Listener> getRequestListeners()
|
||||||
|
@ -293,6 +298,9 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns a <em>non</em> thread-safe set of {@link ContentDecoder.Factory}s that can be modified before
|
||||||
|
* performing requests.
|
||||||
|
*
|
||||||
* @return a set of {@link ContentDecoder.Factory} that can be used to add and remove content decoder factories
|
* @return a set of {@link ContentDecoder.Factory} that can be used to add and remove content decoder factories
|
||||||
*/
|
*/
|
||||||
public Set<ContentDecoder.Factory> getContentDecoderFactories()
|
public Set<ContentDecoder.Factory> getContentDecoderFactories()
|
||||||
|
@ -381,9 +389,9 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
return new HttpRequest(this, uri);
|
return new HttpRequest(this, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Request copyRequest(Request oldRequest, String newURI)
|
protected Request copyRequest(Request oldRequest, URI newURI)
|
||||||
{
|
{
|
||||||
Request newRequest = new HttpRequest(this, oldRequest.getConversationID(), URI.create(newURI));
|
Request newRequest = new HttpRequest(this, oldRequest.getConversationID(), newURI);
|
||||||
newRequest.method(oldRequest.getMethod())
|
newRequest.method(oldRequest.getMethod())
|
||||||
.version(oldRequest.getVersion())
|
.version(oldRequest.getVersion())
|
||||||
.content(oldRequest.getContent());
|
.content(oldRequest.getContent());
|
||||||
|
@ -537,8 +545,11 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
|
|
||||||
protected ProtocolHandler findProtocolHandler(Request request, Response response)
|
protected ProtocolHandler findProtocolHandler(Request request, Response response)
|
||||||
{
|
{
|
||||||
for (ProtocolHandler handler : getProtocolHandlers())
|
// Optimized to avoid allocations of iterator instances
|
||||||
|
List<ProtocolHandler> protocolHandlers = getProtocolHandlers();
|
||||||
|
for (int i = 0; i < protocolHandlers.size(); ++i)
|
||||||
{
|
{
|
||||||
|
ProtocolHandler handler = protocolHandlers.get(i);
|
||||||
if (handler.accept(request, response))
|
if (handler.accept(request, response))
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
@ -614,19 +625,21 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the "User-Agent" HTTP header string of this {@link HttpClient}
|
* @return the "User-Agent" HTTP field of this {@link HttpClient}
|
||||||
*/
|
*/
|
||||||
public String getUserAgent()
|
public HttpField getUserAgentField()
|
||||||
{
|
{
|
||||||
return agent;
|
return agentField;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param agent the "User-Agent" HTTP header string of this {@link HttpClient}
|
* @param agent the "User-Agent" HTTP header string of this {@link HttpClient}
|
||||||
*/
|
*/
|
||||||
public void setUserAgent(String agent)
|
public void setUserAgentField(HttpField agent)
|
||||||
{
|
{
|
||||||
this.agent = agent;
|
if (agent.getHeader() != HttpHeader.USER_AGENT)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
this.agentField = agent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -844,6 +857,11 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
this.proxyConfig = proxyConfig;
|
this.proxyConfig = proxyConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected HttpField getAcceptEncodingField()
|
||||||
|
{
|
||||||
|
return encodingField;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dump(Appendable out, String indent) throws IOException
|
public void dump(Appendable out, String indent) throws IOException
|
||||||
{
|
{
|
||||||
|
@ -930,4 +948,118 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
this.promise = promise;
|
this.promise = promise;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ContentDecoderFactorySet implements Set<ContentDecoder.Factory>
|
||||||
|
{
|
||||||
|
private final Set<ContentDecoder.Factory> set = new HashSet<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(ContentDecoder.Factory e)
|
||||||
|
{
|
||||||
|
boolean result = set.add(e);
|
||||||
|
invalidate();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(Collection<? extends ContentDecoder.Factory> c)
|
||||||
|
{
|
||||||
|
boolean result = set.addAll(c);
|
||||||
|
invalidate();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o)
|
||||||
|
{
|
||||||
|
boolean result = set.remove(o);
|
||||||
|
invalidate();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(Collection<?> c)
|
||||||
|
{
|
||||||
|
boolean result = set.removeAll(c);
|
||||||
|
invalidate();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retainAll(Collection<?> c)
|
||||||
|
{
|
||||||
|
boolean result = set.retainAll(c);
|
||||||
|
invalidate();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
set.clear();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size()
|
||||||
|
{
|
||||||
|
return set.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty()
|
||||||
|
{
|
||||||
|
return set.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o)
|
||||||
|
{
|
||||||
|
return set.contains(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsAll(Collection<?> c)
|
||||||
|
{
|
||||||
|
return set.containsAll(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<ContentDecoder.Factory> iterator()
|
||||||
|
{
|
||||||
|
return set.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] toArray()
|
||||||
|
{
|
||||||
|
return set.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T[] toArray(T[] a)
|
||||||
|
{
|
||||||
|
return set.toArray(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void invalidate()
|
||||||
|
{
|
||||||
|
if (set.isEmpty())
|
||||||
|
{
|
||||||
|
encodingField = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringBuilder value = new StringBuilder();
|
||||||
|
for (Iterator<ContentDecoder.Factory> iterator = set.iterator(); iterator.hasNext();)
|
||||||
|
{
|
||||||
|
ContentDecoder.Factory decoderFactory = iterator.next();
|
||||||
|
value.append(decoderFactory.getEncoding());
|
||||||
|
if (iterator.hasNext())
|
||||||
|
value.append(",");
|
||||||
|
}
|
||||||
|
encodingField = new HttpField(HttpHeader.ACCEPT_ENCODING, value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,12 @@ package org.eclipse.jetty.client;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.HttpCookie;
|
import java.net.HttpCookie;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.UnsupportedCharsetException;
|
import java.nio.charset.UnsupportedCharsetException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
@ -37,8 +35,10 @@ import org.eclipse.jetty.client.api.ContentProvider;
|
||||||
import org.eclipse.jetty.client.api.Request;
|
import org.eclipse.jetty.client.api.Request;
|
||||||
import org.eclipse.jetty.client.api.Response;
|
import org.eclipse.jetty.client.api.Response;
|
||||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||||
|
import org.eclipse.jetty.http.HttpField;
|
||||||
import org.eclipse.jetty.http.HttpFields;
|
import org.eclipse.jetty.http.HttpFields;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
|
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||||
import org.eclipse.jetty.http.HttpMethod;
|
import org.eclipse.jetty.http.HttpMethod;
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
|
@ -51,6 +51,7 @@ import org.eclipse.jetty.util.log.Logger;
|
||||||
public class HttpConnection extends AbstractConnection implements Connection
|
public class HttpConnection extends AbstractConnection implements Connection
|
||||||
{
|
{
|
||||||
private static final Logger LOG = Log.getLogger(HttpConnection.class);
|
private static final Logger LOG = Log.getLogger(HttpConnection.class);
|
||||||
|
private static final HttpField CHUNKED_FIELD = new HttpField(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED);
|
||||||
|
|
||||||
private final AtomicReference<HttpExchange> exchange = new AtomicReference<>();
|
private final AtomicReference<HttpExchange> exchange = new AtomicReference<>();
|
||||||
private final HttpClient client;
|
private final HttpClient client;
|
||||||
|
@ -139,9 +140,6 @@ public class HttpConnection extends AbstractConnection implements Connection
|
||||||
if (request.getVersion() == null)
|
if (request.getVersion() == null)
|
||||||
request.version(HttpVersion.HTTP_1_1);
|
request.version(HttpVersion.HTTP_1_1);
|
||||||
|
|
||||||
if (request.getAgent() == null)
|
|
||||||
request.agent(client.getUserAgent());
|
|
||||||
|
|
||||||
if (request.getIdleTimeout() <= 0)
|
if (request.getIdleTimeout() <= 0)
|
||||||
request.idleTimeout(client.getIdleTimeout(), TimeUnit.MILLISECONDS);
|
request.idleTimeout(client.getIdleTimeout(), TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
@ -150,16 +148,19 @@ public class HttpConnection extends AbstractConnection implements Connection
|
||||||
HttpFields headers = request.getHeaders();
|
HttpFields headers = request.getHeaders();
|
||||||
ContentProvider content = request.getContent();
|
ContentProvider content = request.getContent();
|
||||||
|
|
||||||
|
if (request.getAgent() == null)
|
||||||
|
headers.put(client.getUserAgentField());
|
||||||
|
|
||||||
// Make sure the path is there
|
// Make sure the path is there
|
||||||
String path = request.getPath();
|
String path = request.getPath();
|
||||||
if (path.matches("\\s*"))
|
if (path.trim().length() == 0)
|
||||||
{
|
{
|
||||||
path = "/";
|
path = "/";
|
||||||
request.path(path);
|
request.path(path);
|
||||||
}
|
}
|
||||||
if (destination.isProxied() && HttpMethod.CONNECT != request.getMethod())
|
if (destination.isProxied() && HttpMethod.CONNECT != request.getMethod())
|
||||||
{
|
{
|
||||||
path = request.getURI();
|
path = request.getURI().toString();
|
||||||
request.path(path);
|
request.path(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,13 +209,7 @@ public class HttpConnection extends AbstractConnection implements Connection
|
||||||
if (version.getVersion() > 10)
|
if (version.getVersion() > 10)
|
||||||
{
|
{
|
||||||
if (!headers.containsKey(HttpHeader.HOST.asString()))
|
if (!headers.containsKey(HttpHeader.HOST.asString()))
|
||||||
{
|
headers.put(getDestination().getHostField());
|
||||||
String value = request.getHost();
|
|
||||||
int port = request.getPort();
|
|
||||||
if (port > 0)
|
|
||||||
value += ":" + port;
|
|
||||||
headers.put(HttpHeader.HOST, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add content headers
|
// Add content headers
|
||||||
|
@ -229,12 +224,12 @@ public class HttpConnection extends AbstractConnection implements Connection
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!headers.containsKey(HttpHeader.TRANSFER_ENCODING.asString()))
|
if (!headers.containsKey(HttpHeader.TRANSFER_ENCODING.asString()))
|
||||||
headers.put(HttpHeader.TRANSFER_ENCODING, "chunked");
|
headers.put(CHUNKED_FIELD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cookies
|
// Cookies
|
||||||
List<HttpCookie> cookies = client.getCookieStore().get(URI.create(request.getURI()));
|
List<HttpCookie> cookies = client.getCookieStore().get(request.getURI());
|
||||||
StringBuilder cookieString = null;
|
StringBuilder cookieString = null;
|
||||||
for (int i = 0; i < cookies.size(); ++i)
|
for (int i = 0; i < cookies.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -255,19 +250,9 @@ public class HttpConnection extends AbstractConnection implements Connection
|
||||||
|
|
||||||
if (!headers.containsKey(HttpHeader.ACCEPT_ENCODING.asString()))
|
if (!headers.containsKey(HttpHeader.ACCEPT_ENCODING.asString()))
|
||||||
{
|
{
|
||||||
Set<ContentDecoder.Factory> decoderFactories = client.getContentDecoderFactories();
|
HttpField acceptEncodingField = client.getAcceptEncodingField();
|
||||||
if (!decoderFactories.isEmpty())
|
if (acceptEncodingField != null)
|
||||||
{
|
headers.put(acceptEncodingField);
|
||||||
StringBuilder value = new StringBuilder();
|
|
||||||
for (Iterator<ContentDecoder.Factory> iterator = decoderFactories.iterator(); iterator.hasNext();)
|
|
||||||
{
|
|
||||||
ContentDecoder.Factory decoderFactory = iterator.next();
|
|
||||||
value.append(decoderFactory.getEncoding());
|
|
||||||
if (iterator.hasNext())
|
|
||||||
value.append(",");
|
|
||||||
}
|
|
||||||
headers.put(HttpHeader.ACCEPT_ENCODING, value.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.eclipse.jetty.client.api.Request;
|
||||||
import org.eclipse.jetty.client.api.Response;
|
import org.eclipse.jetty.client.api.Response;
|
||||||
import org.eclipse.jetty.client.api.Result;
|
import org.eclipse.jetty.client.api.Result;
|
||||||
import org.eclipse.jetty.client.util.TimedResponseListener;
|
import org.eclipse.jetty.client.util.TimedResponseListener;
|
||||||
|
import org.eclipse.jetty.http.HttpField;
|
||||||
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.HttpScheme;
|
||||||
|
@ -63,6 +64,7 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
|
||||||
private final RequestNotifier requestNotifier;
|
private final RequestNotifier requestNotifier;
|
||||||
private final ResponseNotifier responseNotifier;
|
private final ResponseNotifier responseNotifier;
|
||||||
private final InetSocketAddress proxyAddress;
|
private final InetSocketAddress proxyAddress;
|
||||||
|
private final HttpField hostField;
|
||||||
|
|
||||||
public HttpDestination(HttpClient client, String scheme, String host, int port)
|
public HttpDestination(HttpClient client, String scheme, String host, int port)
|
||||||
{
|
{
|
||||||
|
@ -79,6 +81,12 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
|
||||||
ProxyConfiguration proxyConfig = client.getProxyConfiguration();
|
ProxyConfiguration proxyConfig = client.getProxyConfiguration();
|
||||||
proxyAddress = proxyConfig != null && proxyConfig.matches(host, port) ?
|
proxyAddress = proxyConfig != null && proxyConfig.matches(host, port) ?
|
||||||
new InetSocketAddress(proxyConfig.getHost(), proxyConfig.getPort()) : null;
|
new InetSocketAddress(proxyConfig.getHost(), proxyConfig.getPort()) : null;
|
||||||
|
|
||||||
|
String hostValue = host;
|
||||||
|
if ("https".equalsIgnoreCase(scheme) && port != 443 ||
|
||||||
|
"http".equalsIgnoreCase(scheme) && port != 80)
|
||||||
|
hostValue += ":" + port;
|
||||||
|
hostField = new HttpField(HttpHeader.HOST, hostValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BlockingQueue<Connection> getIdleConnections()
|
protected BlockingQueue<Connection> getIdleConnections()
|
||||||
|
@ -121,6 +129,11 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
|
||||||
return proxyAddress != null;
|
return proxyAddress != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpField getHostField()
|
||||||
|
{
|
||||||
|
return hostField;
|
||||||
|
}
|
||||||
|
|
||||||
public void send(Request request, List<Response.ResponseListener> listeners)
|
public void send(Request request, List<Response.ResponseListener> listeners)
|
||||||
{
|
{
|
||||||
if (!scheme.equals(request.getScheme()))
|
if (!scheme.equals(request.getScheme()))
|
||||||
|
|
|
@ -224,13 +224,13 @@ public class HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeCookie(String uri, HttpField field)
|
private void storeCookie(URI uri, HttpField field)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Map<String, List<String>> header = new HashMap<>(1);
|
Map<String, List<String>> header = new HashMap<>(1);
|
||||||
header.put(field.getHeader().asString(), Collections.singletonList(field.getValue()));
|
header.put(field.getHeader().asString(), Collections.singletonList(field.getValue()));
|
||||||
connection.getHttpClient().getCookieManager().put(URI.create(uri), header);
|
connection.getHttpClient().getCookieManager().put(uri, header);
|
||||||
}
|
}
|
||||||
catch (IOException x)
|
catch (IOException x)
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,6 +59,7 @@ public class HttpRequest implements Request
|
||||||
private final long conversation;
|
private final long conversation;
|
||||||
private final String host;
|
private final String host;
|
||||||
private final int port;
|
private final int port;
|
||||||
|
private URI uri;
|
||||||
private String scheme;
|
private String scheme;
|
||||||
private String path;
|
private String path;
|
||||||
private HttpMethod method;
|
private HttpMethod method;
|
||||||
|
@ -91,6 +92,7 @@ public class HttpRequest implements Request
|
||||||
param(parts[0], parts.length < 2 ? "" : urlDecode(parts[1]));
|
param(parts[0], parts.length < 2 ? "" : urlDecode(parts[1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.uri = buildURI();
|
||||||
followRedirects(client.isFollowRedirects());
|
followRedirects(client.isFollowRedirects());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,6 +125,7 @@ public class HttpRequest implements Request
|
||||||
public Request scheme(String scheme)
|
public Request scheme(String scheme)
|
||||||
{
|
{
|
||||||
this.scheme = scheme;
|
this.scheme = scheme;
|
||||||
|
this.uri = buildURI();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,19 +164,14 @@ public class HttpRequest implements Request
|
||||||
public Request path(String path)
|
public Request path(String path)
|
||||||
{
|
{
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
this.uri = buildURI();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getURI()
|
public URI getURI()
|
||||||
{
|
{
|
||||||
String scheme = getScheme();
|
return uri;
|
||||||
String result = scheme + "://" + getHost();
|
|
||||||
int port = getPort();
|
|
||||||
result += "http".equals(scheme) && port != 80 ? ":" + port : "";
|
|
||||||
result += "https".equals(scheme) && port != 443 ? ":" + port : "";
|
|
||||||
result += getPath();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -247,9 +245,14 @@ public class HttpRequest implements Request
|
||||||
@Override
|
@Override
|
||||||
public <T extends RequestListener> List<T> getRequestListeners(Class<T> type)
|
public <T extends RequestListener> List<T> getRequestListeners(Class<T> type)
|
||||||
{
|
{
|
||||||
|
// This method is invoked often in a request/response conversation,
|
||||||
|
// so we avoid allocation if there is no need to filter.
|
||||||
|
if (type == null)
|
||||||
|
return (List<T>)requestListeners;
|
||||||
|
|
||||||
ArrayList<T> result = new ArrayList<>();
|
ArrayList<T> result = new ArrayList<>();
|
||||||
for (RequestListener listener : requestListeners)
|
for (RequestListener listener : requestListeners)
|
||||||
if (type == null || type.isInstance(listener))
|
if (type.isInstance(listener))
|
||||||
result.add((T)listener);
|
result.add((T)listener);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -466,6 +469,11 @@ public class HttpRequest implements Request
|
||||||
return aborted;
|
return aborted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private URI buildURI()
|
||||||
|
{
|
||||||
|
return URI.create(getScheme() + "://" + getHost() + ":" + getPort() + getPath());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.client;
|
package org.eclipse.jetty.client;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.api.Request;
|
import org.eclipse.jetty.client.api.Request;
|
||||||
|
@ -65,7 +66,7 @@ public class RedirectProtocolHandler extends Response.Listener.Empty implements
|
||||||
{
|
{
|
||||||
Request request = result.getRequest();
|
Request request = result.getRequest();
|
||||||
Response response = result.getResponse();
|
Response response = result.getResponse();
|
||||||
String location = response.getHeaders().get("location");
|
URI location = URI.create(response.getHeaders().get("location"));
|
||||||
int status = response.getStatus();
|
int status = response.getStatus();
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
|
@ -103,7 +104,7 @@ public class RedirectProtocolHandler extends Response.Listener.Empty implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void redirect(Result result, HttpMethod method, String location)
|
private void redirect(Result result, HttpMethod method, URI location)
|
||||||
{
|
{
|
||||||
final Request request = result.getRequest();
|
final Request request = result.getRequest();
|
||||||
HttpConversation conversation = client.getConversation(request.getConversationID(), false);
|
HttpConversation conversation = client.getConversation(request.getConversationID(), false);
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.client;
|
package org.eclipse.jetty.client;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.api.Request;
|
import org.eclipse.jetty.client.api.Request;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
@ -35,17 +37,26 @@ public class RequestNotifier
|
||||||
|
|
||||||
public void notifyQueued(Request request)
|
public void notifyQueued(Request request)
|
||||||
{
|
{
|
||||||
for (Request.QueuedListener listener : request.getRequestListeners(Request.QueuedListener.class))
|
// Optimized to avoid allocations of iterator instances
|
||||||
notifyQueued(listener, request);
|
List<Request.RequestListener> requestListeners = request.getRequestListeners(null);
|
||||||
for (Request.Listener listener : client.getRequestListeners())
|
for (int i = 0; i < requestListeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.RequestListener listener = requestListeners.get(i);
|
||||||
|
if (listener instanceof Request.QueuedListener)
|
||||||
|
notifyQueued((Request.QueuedListener)listener, request);
|
||||||
|
}
|
||||||
|
List<Request.Listener> listeners = client.getRequestListeners();
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.Listener listener = listeners.get(i);
|
||||||
notifyQueued(listener, request);
|
notifyQueued(listener, request);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyQueued(Request.QueuedListener listener, Request request)
|
private void notifyQueued(Request.QueuedListener listener, Request request)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (listener != null)
|
|
||||||
listener.onQueued(request);
|
listener.onQueued(request);
|
||||||
}
|
}
|
||||||
catch (Exception x)
|
catch (Exception x)
|
||||||
|
@ -56,17 +67,26 @@ public class RequestNotifier
|
||||||
|
|
||||||
public void notifyBegin(Request request)
|
public void notifyBegin(Request request)
|
||||||
{
|
{
|
||||||
for (Request.BeginListener listener : request.getRequestListeners(Request.BeginListener.class))
|
// Optimized to avoid allocations of iterator instances
|
||||||
notifyBegin(listener, request);
|
List<Request.RequestListener> requestListeners = request.getRequestListeners(null);
|
||||||
for (Request.Listener listener : client.getRequestListeners())
|
for (int i = 0; i < requestListeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.RequestListener listener = requestListeners.get(i);
|
||||||
|
if (listener instanceof Request.BeginListener)
|
||||||
|
notifyBegin((Request.BeginListener)listener, request);
|
||||||
|
}
|
||||||
|
List<Request.Listener> listeners = client.getRequestListeners();
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.Listener listener = listeners.get(i);
|
||||||
notifyBegin(listener, request);
|
notifyBegin(listener, request);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyBegin(Request.BeginListener listener, Request request)
|
private void notifyBegin(Request.BeginListener listener, Request request)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (listener != null)
|
|
||||||
listener.onBegin(request);
|
listener.onBegin(request);
|
||||||
}
|
}
|
||||||
catch (Exception x)
|
catch (Exception x)
|
||||||
|
@ -77,17 +97,26 @@ public class RequestNotifier
|
||||||
|
|
||||||
public void notifyHeaders(Request request)
|
public void notifyHeaders(Request request)
|
||||||
{
|
{
|
||||||
for (Request.HeadersListener listener : request.getRequestListeners(Request.HeadersListener.class))
|
// Optimized to avoid allocations of iterator instances
|
||||||
notifyHeaders(listener, request);
|
List<Request.RequestListener> requestListeners = request.getRequestListeners(null);
|
||||||
for (Request.Listener listener : client.getRequestListeners())
|
for (int i = 0; i < requestListeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.RequestListener listener = requestListeners.get(i);
|
||||||
|
if (listener instanceof Request.HeadersListener)
|
||||||
|
notifyHeaders((Request.HeadersListener)listener, request);
|
||||||
|
}
|
||||||
|
List<Request.Listener> listeners = client.getRequestListeners();
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.Listener listener = listeners.get(i);
|
||||||
notifyHeaders(listener, request);
|
notifyHeaders(listener, request);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyHeaders(Request.HeadersListener listener, Request request)
|
private void notifyHeaders(Request.HeadersListener listener, Request request)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (listener != null)
|
|
||||||
listener.onHeaders(request);
|
listener.onHeaders(request);
|
||||||
}
|
}
|
||||||
catch (Exception x)
|
catch (Exception x)
|
||||||
|
@ -98,17 +127,26 @@ public class RequestNotifier
|
||||||
|
|
||||||
public void notifyCommit(Request request)
|
public void notifyCommit(Request request)
|
||||||
{
|
{
|
||||||
for (Request.CommitListener listener : request.getRequestListeners(Request.CommitListener.class))
|
// Optimized to avoid allocations of iterator instances
|
||||||
notifyCommit(listener, request);
|
List<Request.RequestListener> requestListeners = request.getRequestListeners(null);
|
||||||
for (Request.Listener listener : client.getRequestListeners())
|
for (int i = 0; i < requestListeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.RequestListener listener = requestListeners.get(i);
|
||||||
|
if (listener instanceof Request.CommitListener)
|
||||||
|
notifyCommit((Request.CommitListener)listener, request);
|
||||||
|
}
|
||||||
|
List<Request.Listener> listeners = client.getRequestListeners();
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.Listener listener = listeners.get(i);
|
||||||
notifyCommit(listener, request);
|
notifyCommit(listener, request);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyCommit(Request.CommitListener listener, Request request)
|
private void notifyCommit(Request.CommitListener listener, Request request)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (listener != null)
|
|
||||||
listener.onCommit(request);
|
listener.onCommit(request);
|
||||||
}
|
}
|
||||||
catch (Exception x)
|
catch (Exception x)
|
||||||
|
@ -119,17 +157,26 @@ public class RequestNotifier
|
||||||
|
|
||||||
public void notifySuccess(Request request)
|
public void notifySuccess(Request request)
|
||||||
{
|
{
|
||||||
for (Request.SuccessListener listener : request.getRequestListeners(Request.SuccessListener.class))
|
// Optimized to avoid allocations of iterator instances
|
||||||
notifySuccess(listener, request);
|
List<Request.RequestListener> requestListeners = request.getRequestListeners(null);
|
||||||
for (Request.Listener listener : client.getRequestListeners())
|
for (int i = 0; i < requestListeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.RequestListener listener = requestListeners.get(i);
|
||||||
|
if (listener instanceof Request.SuccessListener)
|
||||||
|
notifySuccess((Request.SuccessListener)listener, request);
|
||||||
|
}
|
||||||
|
List<Request.Listener> listeners = client.getRequestListeners();
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.Listener listener = listeners.get(i);
|
||||||
notifySuccess(listener, request);
|
notifySuccess(listener, request);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifySuccess(Request.SuccessListener listener, Request request)
|
private void notifySuccess(Request.SuccessListener listener, Request request)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (listener != null)
|
|
||||||
listener.onSuccess(request);
|
listener.onSuccess(request);
|
||||||
}
|
}
|
||||||
catch (Exception x)
|
catch (Exception x)
|
||||||
|
@ -140,17 +187,26 @@ public class RequestNotifier
|
||||||
|
|
||||||
public void notifyFailure(Request request, Throwable failure)
|
public void notifyFailure(Request request, Throwable failure)
|
||||||
{
|
{
|
||||||
for (Request.FailureListener listener : request.getRequestListeners(Request.FailureListener.class))
|
// Optimized to avoid allocations of iterator instances
|
||||||
notifyFailure(listener, request, failure);
|
List<Request.RequestListener> requestListeners = request.getRequestListeners(null);
|
||||||
for (Request.Listener listener : client.getRequestListeners())
|
for (int i = 0; i < requestListeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.RequestListener listener = requestListeners.get(i);
|
||||||
|
if (listener instanceof Request.FailureListener)
|
||||||
|
notifyFailure((Request.FailureListener)listener, request, failure);
|
||||||
|
}
|
||||||
|
List<Request.Listener> listeners = client.getRequestListeners();
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Request.Listener listener = listeners.get(i);
|
||||||
notifyFailure(listener, request, failure);
|
notifyFailure(listener, request, failure);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyFailure(Request.FailureListener listener, Request request, Throwable failure)
|
private void notifyFailure(Request.FailureListener listener, Request request, Throwable failure)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (listener != null)
|
|
||||||
listener.onFailure(request, failure);
|
listener.onFailure(request, failure);
|
||||||
}
|
}
|
||||||
catch (Exception x)
|
catch (Exception x)
|
||||||
|
|
|
@ -42,10 +42,14 @@ public class ResponseNotifier
|
||||||
|
|
||||||
public void notifyBegin(List<Response.ResponseListener> listeners, Response response)
|
public void notifyBegin(List<Response.ResponseListener> listeners, Response response)
|
||||||
{
|
{
|
||||||
for (Response.ResponseListener listener : listeners)
|
// Optimized to avoid allocations of iterator instances
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Response.ResponseListener listener = listeners.get(i);
|
||||||
if (listener instanceof Response.BeginListener)
|
if (listener instanceof Response.BeginListener)
|
||||||
notifyBegin((Response.BeginListener)listener, response);
|
notifyBegin((Response.BeginListener)listener, response);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyBegin(Response.BeginListener listener, Response response)
|
private void notifyBegin(Response.BeginListener listener, Response response)
|
||||||
{
|
{
|
||||||
|
@ -62,9 +66,13 @@ public class ResponseNotifier
|
||||||
public boolean notifyHeader(List<Response.ResponseListener> listeners, Response response, HttpField field)
|
public boolean notifyHeader(List<Response.ResponseListener> listeners, Response response, HttpField field)
|
||||||
{
|
{
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
for (Response.ResponseListener listener : listeners)
|
// Optimized to avoid allocations of iterator instances
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Response.ResponseListener listener = listeners.get(i);
|
||||||
if (listener instanceof Response.HeaderListener)
|
if (listener instanceof Response.HeaderListener)
|
||||||
result &= notifyHeader((Response.HeaderListener)listener, response, field);
|
result &= notifyHeader((Response.HeaderListener)listener, response, field);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,10 +91,14 @@ public class ResponseNotifier
|
||||||
|
|
||||||
public void notifyHeaders(List<Response.ResponseListener> listeners, Response response)
|
public void notifyHeaders(List<Response.ResponseListener> listeners, Response response)
|
||||||
{
|
{
|
||||||
for (Response.ResponseListener listener : listeners)
|
// Optimized to avoid allocations of iterator instances
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Response.ResponseListener listener = listeners.get(i);
|
||||||
if (listener instanceof Response.HeadersListener)
|
if (listener instanceof Response.HeadersListener)
|
||||||
notifyHeaders((Response.HeadersListener)listener, response);
|
notifyHeaders((Response.HeadersListener)listener, response);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyHeaders(Response.HeadersListener listener, Response response)
|
private void notifyHeaders(Response.HeadersListener listener, Response response)
|
||||||
{
|
{
|
||||||
|
@ -102,10 +114,13 @@ public class ResponseNotifier
|
||||||
|
|
||||||
public void notifyContent(List<Response.ResponseListener> listeners, Response response, ByteBuffer buffer)
|
public void notifyContent(List<Response.ResponseListener> listeners, Response response, ByteBuffer buffer)
|
||||||
{
|
{
|
||||||
for (Response.ResponseListener listener : listeners)
|
// Optimized to avoid allocations of iterator instances
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Response.ResponseListener listener = listeners.get(i);
|
||||||
if (listener instanceof Response.ContentListener)
|
if (listener instanceof Response.ContentListener)
|
||||||
notifyContent((Response.ContentListener)listener, response, buffer);
|
notifyContent((Response.ContentListener)listener, response, buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyContent(Response.ContentListener listener, Response response, ByteBuffer buffer)
|
private void notifyContent(Response.ContentListener listener, Response response, ByteBuffer buffer)
|
||||||
|
@ -122,10 +137,14 @@ public class ResponseNotifier
|
||||||
|
|
||||||
public void notifySuccess(List<Response.ResponseListener> listeners, Response response)
|
public void notifySuccess(List<Response.ResponseListener> listeners, Response response)
|
||||||
{
|
{
|
||||||
for (Response.ResponseListener listener : listeners)
|
// Optimized to avoid allocations of iterator instances
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Response.ResponseListener listener = listeners.get(i);
|
||||||
if (listener instanceof Response.SuccessListener)
|
if (listener instanceof Response.SuccessListener)
|
||||||
notifySuccess((Response.SuccessListener)listener, response);
|
notifySuccess((Response.SuccessListener)listener, response);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifySuccess(Response.SuccessListener listener, Response response)
|
private void notifySuccess(Response.SuccessListener listener, Response response)
|
||||||
{
|
{
|
||||||
|
@ -141,10 +160,14 @@ public class ResponseNotifier
|
||||||
|
|
||||||
public void notifyFailure(List<Response.ResponseListener> listeners, Response response, Throwable failure)
|
public void notifyFailure(List<Response.ResponseListener> listeners, Response response, Throwable failure)
|
||||||
{
|
{
|
||||||
for (Response.ResponseListener listener : listeners)
|
// Optimized to avoid allocations of iterator instances
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Response.ResponseListener listener = listeners.get(i);
|
||||||
if (listener instanceof Response.FailureListener)
|
if (listener instanceof Response.FailureListener)
|
||||||
notifyFailure((Response.FailureListener)listener, response, failure);
|
notifyFailure((Response.FailureListener)listener, response, failure);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyFailure(Response.FailureListener listener, Response response, Throwable failure)
|
private void notifyFailure(Response.FailureListener listener, Response response, Throwable failure)
|
||||||
{
|
{
|
||||||
|
@ -160,10 +183,14 @@ public class ResponseNotifier
|
||||||
|
|
||||||
public void notifyComplete(List<Response.ResponseListener> listeners, Result result)
|
public void notifyComplete(List<Response.ResponseListener> listeners, Result result)
|
||||||
{
|
{
|
||||||
for (Response.ResponseListener listener : listeners)
|
// Optimized to avoid allocations of iterator instances
|
||||||
|
for (int i = 0; i < listeners.size(); ++i)
|
||||||
|
{
|
||||||
|
Response.ResponseListener listener = listeners.get(i);
|
||||||
if (listener instanceof Response.CompleteListener)
|
if (listener instanceof Response.CompleteListener)
|
||||||
notifyComplete((Response.CompleteListener)listener, result);
|
notifyComplete((Response.CompleteListener)listener, result);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyComplete(Response.CompleteListener listener, Result result)
|
private void notifyComplete(Response.CompleteListener listener, Result result)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.client.api;
|
package org.eclipse.jetty.client.api;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.Attributes;
|
import org.eclipse.jetty.util.Attributes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,7 +44,7 @@ public interface Authentication
|
||||||
* @param realm the authentication realm as provided in the {@code WWW-Authenticate} response header
|
* @param realm the authentication realm as provided in the {@code WWW-Authenticate} response header
|
||||||
* @return true if this authentication matches, false otherwise
|
* @return true if this authentication matches, false otherwise
|
||||||
*/
|
*/
|
||||||
boolean matches(String type, String uri, String realm);
|
boolean matches(String type, URI uri, String realm);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the authentication mechanism for the given request, returning a {@link Result} that can be
|
* Executes the authentication mechanism for the given request, returning a {@link Result} that can be
|
||||||
|
@ -70,7 +72,7 @@ public interface Authentication
|
||||||
/**
|
/**
|
||||||
* @return the URI of the request that has been used to generate this {@link Result}
|
* @return the URI of the request that has been used to generate this {@link Result}
|
||||||
*/
|
*/
|
||||||
String getURI();
|
URI getURI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the authentication result to the given request.
|
* Applies the authentication result to the given request.
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.client.api;
|
package org.eclipse.jetty.client.api;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A store for {@link Authentication}s and {@link Authentication.Result}s.
|
* A store for {@link Authentication}s and {@link Authentication.Result}s.
|
||||||
*/
|
*/
|
||||||
|
@ -48,7 +50,7 @@ public interface AuthenticationStore
|
||||||
* @param realm the authentication realm
|
* @param realm the authentication realm
|
||||||
* @return the authentication that matches the given parameters, or null
|
* @return the authentication that matches the given parameters, or null
|
||||||
*/
|
*/
|
||||||
public Authentication findAuthentication(String type, String uri, String realm);
|
public Authentication findAuthentication(String type, URI uri, String realm);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param result the {@link Authentication.Result} to add
|
* @param result the {@link Authentication.Result} to add
|
||||||
|
@ -72,5 +74,5 @@ public interface AuthenticationStore
|
||||||
* @param uri the request URI
|
* @param uri the request URI
|
||||||
* @return the {@link Authentication.Result} that matches the given URI, or null
|
* @return the {@link Authentication.Result} that matches the given URI, or null
|
||||||
*/
|
*/
|
||||||
public Authentication.Result findAuthenticationResult(String uri);
|
public Authentication.Result findAuthenticationResult(URI uri);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.eclipse.jetty.client.api;
|
package org.eclipse.jetty.client.api;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.EventListener;
|
import java.util.EventListener;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -96,7 +97,7 @@ public interface Request
|
||||||
/**
|
/**
|
||||||
* @return the full URI of this request such as "http://host:port/path"
|
* @return the full URI of this request such as "http://host:port/path"
|
||||||
*/
|
*/
|
||||||
String getURI();
|
URI getURI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the HTTP version of this request, such as "HTTP/1.1"
|
* @return the HTTP version of this request, such as "HTTP/1.1"
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.client.util;
|
package org.eclipse.jetty.client.util;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.eclipse.jetty.client.api.Authentication;
|
import org.eclipse.jetty.client.api.Authentication;
|
||||||
import org.eclipse.jetty.client.api.AuthenticationStore;
|
import org.eclipse.jetty.client.api.AuthenticationStore;
|
||||||
|
@ -37,7 +39,7 @@ import org.eclipse.jetty.util.StringUtil;
|
||||||
*/
|
*/
|
||||||
public class BasicAuthentication implements Authentication
|
public class BasicAuthentication implements Authentication
|
||||||
{
|
{
|
||||||
private final String uri;
|
private final URI uri;
|
||||||
private final String realm;
|
private final String realm;
|
||||||
private final String user;
|
private final String user;
|
||||||
private final String password;
|
private final String password;
|
||||||
|
@ -48,7 +50,7 @@ public class BasicAuthentication implements Authentication
|
||||||
* @param user the user that wants to authenticate
|
* @param user the user that wants to authenticate
|
||||||
* @param password the password of the user
|
* @param password the password of the user
|
||||||
*/
|
*/
|
||||||
public BasicAuthentication(String uri, String realm, String user, String password)
|
public BasicAuthentication(URI uri, String realm, String user, String password)
|
||||||
{
|
{
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
|
@ -57,12 +59,12 @@ public class BasicAuthentication implements Authentication
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(String type, String uri, String realm)
|
public boolean matches(String type, URI uri, String realm)
|
||||||
{
|
{
|
||||||
if (!"basic".equalsIgnoreCase(type))
|
if (!"basic".equalsIgnoreCase(type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!uri.startsWith(this.uri))
|
if (!uri.toString().startsWith(this.uri.toString()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return this.realm.equals(realm);
|
return this.realm.equals(realm);
|
||||||
|
@ -78,17 +80,17 @@ public class BasicAuthentication implements Authentication
|
||||||
|
|
||||||
private static class BasicResult implements Result
|
private static class BasicResult implements Result
|
||||||
{
|
{
|
||||||
private final String uri;
|
private final URI uri;
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
public BasicResult(String uri, String value)
|
public BasicResult(URI uri, String value)
|
||||||
{
|
{
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getURI()
|
public URI getURI()
|
||||||
{
|
{
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +98,7 @@ public class BasicAuthentication implements Authentication
|
||||||
@Override
|
@Override
|
||||||
public void apply(Request request)
|
public void apply(Request request)
|
||||||
{
|
{
|
||||||
if (request.getURI().startsWith(uri))
|
if (request.getURI().toString().startsWith(uri.toString()))
|
||||||
request.header(HttpHeader.AUTHORIZATION.asString(), value);
|
request.header(HttpHeader.AUTHORIZATION.asString(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.client.util;
|
package org.eclipse.jetty.client.util;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
@ -52,7 +53,7 @@ public class DigestAuthentication implements Authentication
|
||||||
{
|
{
|
||||||
private static final Pattern PARAM_PATTERN = Pattern.compile("([^=]+)=(.*)");
|
private static final Pattern PARAM_PATTERN = Pattern.compile("([^=]+)=(.*)");
|
||||||
|
|
||||||
private final String uri;
|
private final URI uri;
|
||||||
private final String realm;
|
private final String realm;
|
||||||
private final String user;
|
private final String user;
|
||||||
private final String password;
|
private final String password;
|
||||||
|
@ -63,7 +64,7 @@ public class DigestAuthentication implements Authentication
|
||||||
* @param user the user that wants to authenticate
|
* @param user the user that wants to authenticate
|
||||||
* @param password the password of the user
|
* @param password the password of the user
|
||||||
*/
|
*/
|
||||||
public DigestAuthentication(String uri, String realm, String user, String password)
|
public DigestAuthentication(URI uri, String realm, String user, String password)
|
||||||
{
|
{
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
|
@ -72,12 +73,12 @@ public class DigestAuthentication implements Authentication
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(String type, String uri, String realm)
|
public boolean matches(String type, URI uri, String realm)
|
||||||
{
|
{
|
||||||
if (!"digest".equalsIgnoreCase(type))
|
if (!"digest".equalsIgnoreCase(type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!uri.startsWith(this.uri))
|
if (!uri.toString().startsWith(this.uri.toString()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return this.realm.equals(realm);
|
return this.realm.equals(realm);
|
||||||
|
@ -180,7 +181,7 @@ public class DigestAuthentication implements Authentication
|
||||||
private class DigestResult implements Result
|
private class DigestResult implements Result
|
||||||
{
|
{
|
||||||
private final AtomicInteger nonceCount = new AtomicInteger();
|
private final AtomicInteger nonceCount = new AtomicInteger();
|
||||||
private final String uri;
|
private final URI uri;
|
||||||
private final byte[] content;
|
private final byte[] content;
|
||||||
private final String realm;
|
private final String realm;
|
||||||
private final String user;
|
private final String user;
|
||||||
|
@ -190,7 +191,7 @@ public class DigestAuthentication implements Authentication
|
||||||
private final String qop;
|
private final String qop;
|
||||||
private final String opaque;
|
private final String opaque;
|
||||||
|
|
||||||
public DigestResult(String uri, byte[] content, String realm, String user, String password, String algorithm, String nonce, String qop, String opaque)
|
public DigestResult(URI uri, byte[] content, String realm, String user, String password, String algorithm, String nonce, String qop, String opaque)
|
||||||
{
|
{
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
|
@ -204,7 +205,7 @@ public class DigestAuthentication implements Authentication
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getURI()
|
public URI getURI()
|
||||||
{
|
{
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
@ -212,7 +213,7 @@ public class DigestAuthentication implements Authentication
|
||||||
@Override
|
@Override
|
||||||
public void apply(Request request)
|
public void apply(Request request)
|
||||||
{
|
{
|
||||||
if (!request.getURI().startsWith(uri))
|
if (!request.getURI().toString().startsWith(uri.toString()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MessageDigest digester = getMessageDigest(algorithm);
|
MessageDigest digester = getMessageDigest(algorithm);
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.client;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
@ -34,7 +35,6 @@ import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
import org.eclipse.jetty.client.api.Request;
|
import org.eclipse.jetty.client.api.Request;
|
||||||
import org.eclipse.jetty.client.util.BasicAuthentication;
|
import org.eclipse.jetty.client.util.BasicAuthentication;
|
||||||
import org.eclipse.jetty.client.util.DigestAuthentication;
|
import org.eclipse.jetty.client.util.DigestAuthentication;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
|
||||||
import org.eclipse.jetty.security.Authenticator;
|
import org.eclipse.jetty.security.Authenticator;
|
||||||
import org.eclipse.jetty.security.ConstraintMapping;
|
import org.eclipse.jetty.security.ConstraintMapping;
|
||||||
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||||
|
@ -99,7 +99,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
||||||
public void test_BasicAuthentication() throws Exception
|
public void test_BasicAuthentication() throws Exception
|
||||||
{
|
{
|
||||||
startBasic(new EmptyServerHandler());
|
startBasic(new EmptyServerHandler());
|
||||||
String uri = scheme + "://localhost:" + connector.getLocalPort();
|
URI uri = URI.create(scheme + "://localhost:" + connector.getLocalPort());
|
||||||
test_Authentication(new BasicAuthentication(uri, realm, "basic", "basic"));
|
test_Authentication(new BasicAuthentication(uri, realm, "basic", "basic"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
||||||
public void test_DigestAuthentication() throws Exception
|
public void test_DigestAuthentication() throws Exception
|
||||||
{
|
{
|
||||||
startDigest(new EmptyServerHandler());
|
startDigest(new EmptyServerHandler());
|
||||||
String uri = scheme + "://localhost:" + connector.getLocalPort();
|
URI uri = URI.create(scheme + "://localhost:" + connector.getLocalPort());
|
||||||
test_Authentication(new DigestAuthentication(uri, realm, "digest", "digest"));
|
test_Authentication(new DigestAuthentication(uri, realm, "digest", "digest"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,6 +148,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
||||||
client.getRequestListeners().add(requestListener);
|
client.getRequestListeners().add(requestListener);
|
||||||
|
|
||||||
// Request with authentication causes a 401 (no previous successful authentication) + 200
|
// Request with authentication causes a 401 (no previous successful authentication) + 200
|
||||||
|
request = client.newRequest("localhost", connector.getLocalPort()).scheme(scheme).path("/secure");
|
||||||
response = request.timeout(5, TimeUnit.SECONDS).send();
|
response = request.timeout(5, TimeUnit.SECONDS).send();
|
||||||
Assert.assertNotNull(response);
|
Assert.assertNotNull(response);
|
||||||
Assert.assertEquals(200, response.getStatus());
|
Assert.assertEquals(200, response.getStatus());
|
||||||
|
@ -167,7 +168,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
||||||
|
|
||||||
// Further requests do not trigger 401 because there is a previous successful authentication
|
// Further requests do not trigger 401 because there is a previous successful authentication
|
||||||
// Remove existing header to be sure it's added by the implementation
|
// Remove existing header to be sure it's added by the implementation
|
||||||
request.header(HttpHeader.AUTHORIZATION.asString(), null);
|
request = client.newRequest("localhost", connector.getLocalPort()).scheme(scheme).path("/secure");
|
||||||
response = request.timeout(5, TimeUnit.SECONDS).send();
|
response = request.timeout(5, TimeUnit.SECONDS).send();
|
||||||
Assert.assertNotNull(response);
|
Assert.assertNotNull(response);
|
||||||
Assert.assertEquals(200, response.getStatus());
|
Assert.assertEquals(200, response.getStatus());
|
||||||
|
@ -191,7 +192,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
String uri = scheme + "://localhost:" + connector.getLocalPort();
|
URI uri = URI.create(scheme + "://localhost:" + connector.getLocalPort());
|
||||||
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "basic", "basic"));
|
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "basic", "basic"));
|
||||||
|
|
||||||
final CountDownLatch requests = new CountDownLatch(3);
|
final CountDownLatch requests = new CountDownLatch(3);
|
||||||
|
@ -230,7 +231,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
String uri = scheme + "://localhost:" + connector.getLocalPort();
|
URI uri = URI.create(scheme + "://localhost:" + connector.getLocalPort());
|
||||||
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "basic", "basic"));
|
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "basic", "basic"));
|
||||||
|
|
||||||
final CountDownLatch requests = new CountDownLatch(3);
|
final CountDownLatch requests = new CountDownLatch(3);
|
||||||
|
@ -272,7 +273,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
||||||
client.getRequestListeners().add(requestListener);
|
client.getRequestListeners().add(requestListener);
|
||||||
|
|
||||||
AuthenticationStore authenticationStore = client.getAuthenticationStore();
|
AuthenticationStore authenticationStore = client.getAuthenticationStore();
|
||||||
String uri = scheme + "://localhost:" + connector.getLocalPort();
|
URI uri = URI.create(scheme + "://localhost:" + connector.getLocalPort());
|
||||||
BasicAuthentication authentication = new BasicAuthentication(uri, realm, "basic", "basic");
|
BasicAuthentication authentication = new BasicAuthentication(uri, realm, "basic", "basic");
|
||||||
authenticationStore.addAuthentication(authentication);
|
authenticationStore.addAuthentication(authentication);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.eclipse.jetty.client;
|
package org.eclipse.jetty.client;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -113,13 +114,14 @@ public class HttpClientLoadTest extends AbstractHttpClientServerTest
|
||||||
Assert.assertTrue(failures.toString(), failures.isEmpty());
|
Assert.assertTrue(failures.toString(), failures.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void test(Random random, final CountDownLatch latch, final List<String> failures)
|
private void test(Random random, final CountDownLatch latch, final List<String> failures) throws InterruptedException
|
||||||
{
|
{
|
||||||
int maxContentLength = 64 * 1024;
|
int maxContentLength = 64 * 1024;
|
||||||
|
|
||||||
// Choose a random destination
|
// Choose a random destination
|
||||||
String host = random.nextBoolean() ? "localhost" : "127.0.0.1";
|
String host = random.nextBoolean() ? "localhost" : "127.0.0.1";
|
||||||
Request request = client.newRequest(host, connector.getLocalPort()).scheme(scheme);
|
URI uri = URI.create(scheme + "://" + host + ":" + connector.getLocalPort());
|
||||||
|
Request request = client.newRequest(uri);
|
||||||
|
|
||||||
// Choose a random method
|
// Choose a random method
|
||||||
HttpMethod method = random.nextBoolean() ? HttpMethod.GET : HttpMethod.POST;
|
HttpMethod method = random.nextBoolean() ? HttpMethod.GET : HttpMethod.POST;
|
||||||
|
@ -147,6 +149,7 @@ public class HttpClientLoadTest extends AbstractHttpClientServerTest
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final CountDownLatch requestLatch = new CountDownLatch(1);
|
||||||
request.send(new Response.Listener.Empty()
|
request.send(new Response.Listener.Empty()
|
||||||
{
|
{
|
||||||
private final AtomicInteger contentLength = new AtomicInteger();
|
private final AtomicInteger contentLength = new AtomicInteger();
|
||||||
|
@ -175,9 +178,11 @@ public class HttpClientLoadTest extends AbstractHttpClientServerTest
|
||||||
}
|
}
|
||||||
if (contentLength.get() != 0)
|
if (contentLength.get() != 0)
|
||||||
failures.add("Content length mismatch " + contentLength);
|
failures.add("Content length mismatch " + contentLength);
|
||||||
|
requestLatch.countDown();
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
requestLatch.await(5, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LoadHandler extends AbstractHandler
|
private class LoadHandler extends AbstractHandler
|
||||||
|
|
|
@ -192,7 +192,7 @@ public class Usage
|
||||||
HttpClient client = new HttpClient();
|
HttpClient client = new HttpClient();
|
||||||
client.start();
|
client.start();
|
||||||
|
|
||||||
String uri = "http://localhost:8080/secure";
|
URI uri = URI.create("http://localhost:8080/secure");
|
||||||
|
|
||||||
// Setup Basic authentication credentials for TestRealm
|
// Setup Basic authentication credentials for TestRealm
|
||||||
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, "TestRealm", "username", "password"));
|
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, "TestRealm", "username", "password"));
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.net.URI;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
|
@ -301,7 +302,7 @@ public class JdbcLoginServiceTest
|
||||||
executor.setName(executor.getName() + "-client");
|
executor.setName(executor.getName() + "-client");
|
||||||
_client.setExecutor(executor);
|
_client.setExecutor(executor);
|
||||||
AuthenticationStore authStore = _client.getAuthenticationStore();
|
AuthenticationStore authStore = _client.getAuthenticationStore();
|
||||||
authStore.addAuthentication(new BasicAuthentication(_baseUrl, __realm, "jetty", "jetty"));
|
authStore.addAuthentication(new BasicAuthentication(URI.create(_baseUrl), __realm, "jetty", "jetty"));
|
||||||
_client.start();
|
_client.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue