This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 848d116f99ec170fb3678d4eb0ee333a85f721a1 Author: Mark Thomas <ma...@apache.org> AuthorDate: Tue Mar 31 14:03:17 2020 +0100 Make the HTTP/2 connection ID and stream Id available to applications --- java/org/apache/catalina/Globals.java | 16 ++++++++++ java/org/apache/catalina/connector/Request.java | 27 ++++++++++++++++ java/org/apache/coyote/AbstractProcessor.java | 39 +++++++++++++++++++++++ java/org/apache/coyote/ActionCode.java | 14 +++++++- java/org/apache/coyote/http2/StreamProcessor.java | 12 +++++++ webapps/docs/changelog.xml | 5 +++ webapps/docs/config/http2.xml | 9 ++++++ 7 files changed, 121 insertions(+), 1 deletion(-) diff --git a/java/org/apache/catalina/Globals.java b/java/org/apache/catalina/Globals.java index 144a028..312d78b 100644 --- a/java/org/apache/catalina/Globals.java +++ b/java/org/apache/catalina/Globals.java @@ -51,6 +51,22 @@ public final class Globals { /** + * The request attribute used to expose the current connection ID associated + * with the request, if any. Used with multiplexing protocols such as + * HTTTP/2. + */ + public static final String CONNECTION_ID = "org.apache.coyote.connectionID"; + + + /** + * The request attribute used to expose the current stream ID associated + * with the request, if any. Used with multiplexing protocols such as + * HTTTP/2. + */ + public static final String STREAM_ID = "org.apache.coyote.streamID"; + + + /** * The request attribute that is set to {@code Boolean.TRUE} if some request * parameters have been ignored during request parameters parsing. It can * happen, for example, if there is a limit on the total count of parseable diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java index a38e97a..743be10 100644 --- a/java/org/apache/catalina/connector/Request.java +++ b/java/org/apache/catalina/connector/Request.java @@ -41,6 +41,7 @@ import java.util.TimeZone; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import javax.naming.NamingException; import javax.security.auth.Subject; @@ -3562,6 +3563,32 @@ public class Request implements org.apache.catalina.servlet4preview.http.HttpSer // NO-OP } }); + specialAttributes.put(Globals.CONNECTION_ID, + new SpecialAttributeAdapter() { + @Override + public Object get(Request request, String name) { + AtomicReference<Object> result = new AtomicReference<>(); + request.getCoyoteRequest().action(ActionCode.CONNECTION_ID, result); + return result.get(); + } + @Override + public void set(Request request, String name, Object value) { + // NO-OP + } + }); + specialAttributes.put(Globals.STREAM_ID, + new SpecialAttributeAdapter() { + @Override + public Object get(Request request, String name) { + AtomicReference<Object> result = new AtomicReference<>(); + request.getCoyoteRequest().action(ActionCode.STREAM_ID, result); + return result.get(); + } + @Override + public void set(Request request, String name, Object value) { + // NO-OP + } + }); for (SimpleDateFormat sdf : formatsTemplate) { sdf.setTimeZone(GMT_ZONE); diff --git a/java/org/apache/coyote/AbstractProcessor.java b/java/org/apache/coyote/AbstractProcessor.java index dd2b807..646578d 100644 --- a/java/org/apache/coyote/AbstractProcessor.java +++ b/java/org/apache/coyote/AbstractProcessor.java @@ -22,6 +22,7 @@ import java.nio.ByteBuffer; import java.util.Iterator; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import javax.servlet.RequestDispatcher; @@ -612,6 +613,20 @@ public abstract class AbstractProcessor extends AbstractProcessorLight implement doPush((Request) param); break; } + + // Identifiers associated with multiplexing protocols like HTTP/2 + case CONNECTION_ID: { + @SuppressWarnings("unchecked") + AtomicReference<Object> result = (AtomicReference<Object>) param; + result.set(getConnectionID()); + break; + } + case STREAM_ID: { + @SuppressWarnings("unchecked") + AtomicReference<Object> result = (AtomicReference<Object>) param; + result.set(getStreamID()); + break; + } } } @@ -933,6 +948,30 @@ public abstract class AbstractProcessor extends AbstractProcessorLight implement /** + * Protocols that support multiplexing (e.g. HTTP/2) should override this + * method and return the appropriate ID. + * + * @return The stream ID associated with this request or {@code null} if a + * multiplexing protocol is not being used + */ + protected Object getConnectionID() { + return null; + } + + + /** + * Protocols that support multiplexing (e.g. HTTP/2) should override this + * method and return the appropriate ID. + * + * @return The stream ID associated with this request or {@code null} if a + * multiplexing protocol is not being used + */ + protected Object getStreamID() { + return null; + } + + + /** * Flush any pending writes. Used during non-blocking writes to flush any * remaining data from a previous incomplete write. * diff --git a/java/org/apache/coyote/ActionCode.java b/java/org/apache/coyote/ActionCode.java index eb482bb..2795a81 100644 --- a/java/org/apache/coyote/ActionCode.java +++ b/java/org/apache/coyote/ActionCode.java @@ -251,5 +251,17 @@ public enum ActionCode { /** * Push a request on behalf of the client of the current request. */ - PUSH_REQUEST + PUSH_REQUEST, + + /** + * Obtain the connection identifier for the request. Used with multiplexing + * protocols such as HTTP/2. + */ + CONNECTION_ID, + + /** + * Obtain the stream identifier for the request. Used with multiplexing + * protocols such as HTTP/2. + */ + STREAM_ID } diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java index f3c380d..be6a353 100644 --- a/java/org/apache/coyote/http2/StreamProcessor.java +++ b/java/org/apache/coyote/http2/StreamProcessor.java @@ -300,6 +300,18 @@ class StreamProcessor extends AbstractProcessor { @Override + protected Object getConnectionID() { + return stream.getConnectionId(); + } + + + @Override + protected Object getStreamID() { + return stream.getIdentifier().toString(); + } + + + @Override public void recycle() { // StreamProcessor instances are not re-used. // Clear fields that can be cleared to aid GC and trigger NPEs if this diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 4a05330..164fcad 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -88,6 +88,11 @@ data on the request line after the URI are treated consistently. Such requests will now always be treated as HTTP/1.1. (markt) </fix> + <add> + Expose the HTTP/2 connection ID and stream ID to applications via the + request attributes <code>org.apache.coyote.connectionID</code> and + <code>org.apache.coyote.streamID</code> respectively. (markt) + </add> </changelog> </subsection> <subsection name="Jasper"> diff --git a/webapps/docs/config/http2.xml b/webapps/docs/config/http2.xml index d0055dd..8e72a25 100644 --- a/webapps/docs/config/http2.xml +++ b/webapps/docs/config/http2.xml @@ -44,6 +44,15 @@ the Servlet API is fundamentally blocking, each HTTP/2 stream requires a dedicated container thread for the duration of that stream.</p> + <p>Requests processed using HTTP/2 will have the following additional request + attributes available:</p> + <ul> + <li><code>org.apache.coyote.connectionID</code> will return the HTTP/2 + connection ID</li> + <li><code>org.apache.coyote.streamID</code> will return the HTTP/2 stream + ID</li> + </ul> + </section> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org