Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimone Bordet2015-03-31 17:17:02 +0000
committerSimone Bordet2015-03-31 17:17:02 +0000
commit48dd4d8b568b73c8642e9eef35d05733e919231b (patch)
tree83c7e0b12d410d703d7278d99cb53b0f2cd71f0a
parent6263972d1ea084fa58eea809583d571914d128c0 (diff)
downloadorg.eclipse.jetty.project-48dd4d8b568b73c8642e9eef35d05733e919231b.tar.gz
org.eclipse.jetty.project-48dd4d8b568b73c8642e9eef35d05733e919231b.tar.xz
org.eclipse.jetty.project-48dd4d8b568b73c8642e9eef35d05733e919231b.zip
440106 - Improve ProtocolHandler APIs.
Introduced ProtocolHandlers, the container for ProtocolHandler instances, which now have also a name.
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/ContinueProtocolHandler.java14
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java22
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/ProtocolHandler.java29
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/ProtocolHandlers.java94
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/ProxyAuthenticationProtocolHandler.java14
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/RedirectProtocolHandler.java11
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/WWWAuthenticationProtocolHandler.java14
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientContinueTest.java14
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HttpRequestAbortTest.java3
9 files changed, 183 insertions, 32 deletions
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/ContinueProtocolHandler.java b/jetty-client/src/main/java/org/eclipse/jetty/client/ContinueProtocolHandler.java
index 2120ac2cf0..460f01499f 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/ContinueProtocolHandler.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/ContinueProtocolHandler.java
@@ -27,20 +27,28 @@ import org.eclipse.jetty.client.util.BufferingResponseListener;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
+/**
+ * <p>A protocol handler that handles the 100 response code.</p>
+ */
public class ContinueProtocolHandler implements ProtocolHandler
{
+ public static final String NAME = "continue";
private static final String ATTRIBUTE = ContinueProtocolHandler.class.getName() + ".100continue";
- private final HttpClient client;
private final ResponseNotifier notifier;
- public ContinueProtocolHandler(HttpClient client)
+ public ContinueProtocolHandler()
{
- this.client = client;
this.notifier = new ResponseNotifier();
}
@Override
+ public String getName()
+ {
+ return NAME;
+ }
+
+ @Override
public boolean accept(Request request, Response response)
{
boolean expect100 = request.getHeaders().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString());
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
index f30a22378b..999f1b56af 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
@@ -109,7 +109,7 @@ public class HttpClient extends ContainerLifeCycle
private static final Logger LOG = Log.getLogger(HttpClient.class);
private final ConcurrentMap<Origin, HttpDestination> destinations = new ConcurrentHashMap<>();
- private final List<ProtocolHandler> handlers = new ArrayList<>();
+ private final ProtocolHandlers handlers = new ProtocolHandlers();
private final List<Request.Listener> requestListeners = new ArrayList<>();
private final AuthenticationStore authenticationStore = new HttpAuthenticationStore();
private final Set<ContentDecoder.Factory> decoderFactories = new ContentDecoderFactorySet();
@@ -210,10 +210,10 @@ public class HttpClient extends ContainerLifeCycle
resolver = new SocketAddressResolver(executor, scheduler, getAddressResolutionTimeout());
- handlers.add(new ContinueProtocolHandler(this));
- handlers.add(new RedirectProtocolHandler(this));
- handlers.add(new WWWAuthenticationProtocolHandler(this));
- handlers.add(new ProxyAuthenticationProtocolHandler(this));
+ handlers.put(new ContinueProtocolHandler());
+ handlers.put(new RedirectProtocolHandler(this));
+ handlers.put(new WWWAuthenticationProtocolHandler(this));
+ handlers.put(new ProxyAuthenticationProtocolHandler(this));
decoderFactories.add(new GZIPContentDecoder.Factory());
@@ -547,22 +547,14 @@ public class HttpClient extends ContainerLifeCycle
return new HttpConversation();
}
- protected List<ProtocolHandler> getProtocolHandlers()
+ public ProtocolHandlers getProtocolHandlers()
{
return handlers;
}
protected ProtocolHandler findProtocolHandler(Request request, Response response)
{
- // 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))
- return handler;
- }
- return null;
+ return handlers.find(request, response);
}
/**
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/ProtocolHandler.java b/jetty-client/src/main/java/org/eclipse/jetty/client/ProtocolHandler.java
index a74e6578a4..3f347b2812 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/ProtocolHandler.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/ProtocolHandler.java
@@ -21,9 +21,38 @@ package org.eclipse.jetty.client;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
+/**
+ * <p>A protocol handler performs HTTP protocol operations on
+ * behalf of the application, typically like a browser would.</p>
+ * <p>A typical example is handling HTTP redirects. {@link HttpClient}
+ * could just return the redirect response to the application,
+ * but the application would have to implement the redirect
+ * functionality (while browsers do this automatically).</p>
+ */
public interface ProtocolHandler
{
+ /**
+ * @return a unique name among protocol handlers
+ */
+ public String getName();
+
+ /**
+ * <p>Inspects the given {@code request} and {@code response}
+ * to detect whether this protocol handler should handle them.</p>
+ * <p>For example, a redirect protocol handler can inspect the
+ * response code and return true if it is a redirect response code.</p>
+ * <p>This method is being called just after the response line has
+ * been parsed, and before the response headers are available.</p>
+ *
+ * @param request the request to accept
+ * @param response the response to accept
+ * @return true if this protocol handler can handle the given request and response
+ */
public boolean accept(Request request, Response response);
+ /**
+ * @return a response listener that will handle the request and response
+ * on behalf of the application.
+ */
public Response.Listener getResponseListener();
}
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/ProtocolHandlers.java b/jetty-client/src/main/java/org/eclipse/jetty/client/ProtocolHandlers.java
new file mode 100644
index 0000000000..d0686519b8
--- /dev/null
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/ProtocolHandlers.java
@@ -0,0 +1,94 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.client;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.api.Response;
+
+/**
+ * <p>A container for {@link ProtocolHandler}s accessible from {@link HttpClient#getProtocolHandlers()}.</p>
+ */
+public class ProtocolHandlers
+{
+ private final Map<String, ProtocolHandler> handlers = new LinkedHashMap<>();
+
+ protected ProtocolHandlers()
+ {
+ }
+
+ /**
+ * <p>Stores the given {@code protocolHandler} in this container.</p>
+ * <p>If a protocol handler with the same name exists, it is
+ * replaced by the given one, and the existing returned.</p>
+ *
+ * @param protocolHandler the protocol handler to store
+ * @return the existing protocol handler with the same name,
+ * or null if no protocol handler with that name was already stored
+ * @see #remove(String)
+ */
+ public ProtocolHandler put(ProtocolHandler protocolHandler)
+ {
+ return handlers.put(protocolHandler.getName(), protocolHandler);
+ }
+
+ /**
+ * <p>Removes the protocol handler with the given name.</p>
+ *
+ * @param name the name of the protocol handler to remove
+ * @return the removed protocol handler, or null if no
+ * protocol handler with that name was already stored
+ * @see #put(ProtocolHandler)
+ * @see #clear()
+ */
+ public ProtocolHandler remove(String name)
+ {
+ return handlers.remove(name);
+ }
+
+ /**
+ * <p>Removes all protocol handlers from this container.</p>
+ */
+ public void clear()
+ {
+ handlers.clear();
+ }
+
+ /**
+ * <p>Finds the first protocol handler that
+ * {@link ProtocolHandler#accept(Request, Response) accepts}
+ * the given request and response.</p>
+ *
+ * @param request the request to accept
+ * @param response the response to accept
+ * @return the protocol handler that accepted the request and response,
+ * or null if none of the protocol handlers accepted the request and response
+ */
+ public ProtocolHandler find(Request request, Response response)
+ {
+ for (ProtocolHandler handler : handlers.values())
+ {
+ if (handler.accept(request, response))
+ return handler;
+ }
+ return null;
+ }
+}
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyAuthenticationProtocolHandler.java b/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyAuthenticationProtocolHandler.java
index 64491b2a12..059bc0fe87 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyAuthenticationProtocolHandler.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyAuthenticationProtocolHandler.java
@@ -25,8 +25,16 @@ import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
+/**
+ * <p>A protocol handler that handles the 401 response code
+ * in association with the {@code Proxy-Authenticate} header.</p>
+ *
+ * @see WWWAuthenticationProtocolHandler
+ */
public class ProxyAuthenticationProtocolHandler extends AuthenticationProtocolHandler
{
+ public static final String NAME = "proxy-authenticate";
+
public ProxyAuthenticationProtocolHandler(HttpClient client)
{
this(client, DEFAULT_MAX_CONTENT_LENGTH);
@@ -38,6 +46,12 @@ public class ProxyAuthenticationProtocolHandler extends AuthenticationProtocolHa
}
@Override
+ public String getName()
+ {
+ return NAME;
+ }
+
+ @Override
public boolean accept(Request request, Response response)
{
return response.getStatus() == HttpStatus.PROXY_AUTHENTICATION_REQUIRED_407;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/RedirectProtocolHandler.java b/jetty-client/src/main/java/org/eclipse/jetty/client/RedirectProtocolHandler.java
index 8ed88bf64e..8be72da040 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/RedirectProtocolHandler.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/RedirectProtocolHandler.java
@@ -22,8 +22,13 @@ import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
+/**
+ * <p>A protocol handler that handles redirect status codes 301, 302, 303, 307 and 308.</p>
+ */
public class RedirectProtocolHandler extends Response.Listener.Adapter implements ProtocolHandler
{
+ public static final String NAME = "redirect";
+
private final HttpRedirector redirector;
public RedirectProtocolHandler(HttpClient client)
@@ -32,6 +37,12 @@ public class RedirectProtocolHandler extends Response.Listener.Adapter implement
}
@Override
+ public String getName()
+ {
+ return NAME;
+ }
+
+ @Override
public boolean accept(Request request, Response response)
{
return redirector.isRedirect(response) && request.isFollowRedirects();
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/WWWAuthenticationProtocolHandler.java b/jetty-client/src/main/java/org/eclipse/jetty/client/WWWAuthenticationProtocolHandler.java
index 4bc6258b10..1ff41a3c1e 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/WWWAuthenticationProtocolHandler.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/WWWAuthenticationProtocolHandler.java
@@ -25,8 +25,16 @@ import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
+/**
+ * <p>A protocol handler that handles the 401 response code
+ * in association with the {@code WWW-Authenticate} header.</p>
+ *
+ * @see ProxyAuthenticationProtocolHandler
+ */
public class WWWAuthenticationProtocolHandler extends AuthenticationProtocolHandler
{
+ public static final String NAME = "www-authenticate";
+
public WWWAuthenticationProtocolHandler(HttpClient client)
{
this(client, DEFAULT_MAX_CONTENT_LENGTH);
@@ -38,6 +46,12 @@ public class WWWAuthenticationProtocolHandler extends AuthenticationProtocolHand
}
@Override
+ public String getName()
+ {
+ return NAME;
+ }
+
+ @Override
public boolean accept(Request request, Response response)
{
return response.getStatus() == HttpStatus.UNAUTHORIZED_401;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientContinueTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientContinueTest.java
index 792c936a0d..1c511f85a4 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientContinueTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientContinueTest.java
@@ -27,11 +27,8 @@ import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
-import java.util.Iterator;
-import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
@@ -405,7 +402,7 @@ public class HttpClientContinueTest extends AbstractHttpClientServerTest
});
client.getProtocolHandlers().clear();
- client.getProtocolHandlers().add(new ContinueProtocolHandler(client)
+ client.getProtocolHandlers().put(new ContinueProtocolHandler()
{
@Override
public Response.Listener getResponseListener()
@@ -609,14 +606,7 @@ public class HttpClientContinueTest extends AbstractHttpClientServerTest
final DeferredContentProvider content = new DeferredContentProvider(ByteBuffer.wrap(chunk1));
- List<ProtocolHandler> protocolHandlers = client.getProtocolHandlers();
- for (Iterator<ProtocolHandler> iterator = protocolHandlers.iterator(); iterator.hasNext();)
- {
- ProtocolHandler protocolHandler = iterator.next();
- if (protocolHandler instanceof ContinueProtocolHandler)
- iterator.remove();
- }
- protocolHandlers.add(new ContinueProtocolHandler(client)
+ client.getProtocolHandlers().put(new ContinueProtocolHandler()
{
@Override
public Response.Listener getResponseListener()
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpRequestAbortTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpRequestAbortTest.java
index 0531950c65..c4d6010c51 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpRequestAbortTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpRequestAbortTest.java
@@ -25,7 +25,6 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
-
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -528,7 +527,7 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
final AtomicBoolean aborted = new AtomicBoolean();
final CountDownLatch latch = new CountDownLatch(1);
client.getProtocolHandlers().clear();
- client.getProtocolHandlers().add(new RedirectProtocolHandler(client)
+ client.getProtocolHandlers().put(new RedirectProtocolHandler(client)
{
@Override
public void onComplete(Result result)

Back to the top