You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2024/07/19 15:09:19 UTC

(tomcat) branch main updated (ebd5cae558 -> 809548fd8a)

This is an automated email from the ASF dual-hosted git repository.

markt pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


    from ebd5cae558 Fix warning
     new 3a1659ebe6 Rename method that performs commit to commit()
     new 9dba4efc0f Remove deprecated code
     new ff7a869fd2 Refactor writing of the status code
     new 2d939ecf4c Refactoring writing of HTTP headers to separate method
     new 3f37960753 Implement early hints for HTTP/1.1
     new 26a9aef3e4 Remove deprecated code
     new d4db19dabf AJP doesn't support 1xx responses.
     new 73df9bd7d9 Add HTTP/2 support for early hints
     new 809548fd8a Add a changelog entry

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/catalina/connector/OutputBuffer.java    |  2 +-
 java/org/apache/catalina/connector/Response.java   | 14 +++++
 .../apache/catalina/connector/ResponseFacade.java  |  4 ++
 java/org/apache/coyote/AbstractProcessor.java      | 11 ++++
 java/org/apache/coyote/ActionCode.java             |  7 ++-
 java/org/apache/coyote/Response.java               |  2 +-
 java/org/apache/coyote/ajp/AjpProcessor.java       |  6 ++
 .../apache/coyote/http11/Http11OutputBuffer.java   |  8 ++-
 java/org/apache/coyote/http11/Http11Processor.java | 23 ++++++--
 .../org/apache/coyote/http2/Http2OutputBuffer.java |  2 +-
 java/org/apache/coyote/http2/Stream.java           | 16 ++++++
 java/org/apache/coyote/http2/StreamProcessor.java  |  6 ++
 .../apache/coyote/http11/TestHttp11Processor.java  | 49 ++++++++++++++++
 .../apache/coyote/http2/TestStreamProcessor.java   | 67 ++++++++++++++++++++++
 webapps/docs/changelog.xml                         | 12 ++++
 15 files changed, 218 insertions(+), 11 deletions(-)


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 01/09: Rename method that performs commit to commit()

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 3a1659ebe6a9afc7aa771ee594680a4b57620812
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 4 13:50:37 2024 +0100

    Rename method that performs commit to commit()
    
    This refactoring is in preparation for RFC 8293 (Early Hints) support.
    That will introduce a method that writes headers without a commit. This
    rename will reduce potential confusion between writeHeaders() and
    sendHeaders().
---
 java/org/apache/catalina/connector/OutputBuffer.java |  2 +-
 java/org/apache/coyote/Response.java                 | 11 +++++++++++
 java/org/apache/coyote/http2/Http2OutputBuffer.java  |  2 +-
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/catalina/connector/OutputBuffer.java b/java/org/apache/catalina/connector/OutputBuffer.java
index 03b6737af6..b185561ef3 100644
--- a/java/org/apache/catalina/connector/OutputBuffer.java
+++ b/java/org/apache/catalina/connector/OutputBuffer.java
@@ -270,7 +270,7 @@ public class OutputBuffer extends Writer {
         try {
             doFlush = true;
             if (initial) {
-                coyoteResponse.sendHeaders();
+                coyoteResponse.commit();
                 initial = false;
             }
             if (cb.remaining() > 0) {
diff --git a/java/org/apache/coyote/Response.java b/java/org/apache/coyote/Response.java
index 118aa92917..ca89a1afca 100644
--- a/java/org/apache/coyote/Response.java
+++ b/java/org/apache/coyote/Response.java
@@ -447,8 +447,19 @@ public final class Response {
 
     /**
      * Signal that we're done with the headers, and body will follow.
+     *
+     * @deprecated Unused. Will be removed in Tomcat 11 onwards. Use {@link #commit()}.
      */
+    @Deprecated
     public void sendHeaders() {
+        commit();
+    }
+
+
+    /**
+     * Signal that we're done with the headers, and body will follow.
+     */
+    public void commit() {
         action(ActionCode.COMMIT, this);
         setCommitted(true);
     }
diff --git a/java/org/apache/coyote/http2/Http2OutputBuffer.java b/java/org/apache/coyote/http2/Http2OutputBuffer.java
index 1de4569900..3d4d6b96c5 100644
--- a/java/org/apache/coyote/http2/Http2OutputBuffer.java
+++ b/java/org/apache/coyote/http2/Http2OutputBuffer.java
@@ -52,7 +52,7 @@ public class Http2OutputBuffer implements HttpOutputBuffer {
     @Override
     public int doWrite(ByteBuffer chunk) throws IOException {
         if (!coyoteResponse.isCommitted()) {
-            coyoteResponse.sendHeaders();
+            coyoteResponse.commit();
         }
         return next.doWrite(chunk);
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 04/09: Refactoring writing of HTTP headers to separate method

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 2d939ecf4ce214281d6f3db41a6c98fb8134cc47
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 4 14:18:16 2024 +0100

    Refactoring writing of HTTP headers to separate method
    
    This in preparation for RFC 8297 (Early Hints) support that will need to
    write the current headers without committing the response.
---
 java/org/apache/coyote/http11/Http11Processor.java | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/java/org/apache/coyote/http11/Http11Processor.java b/java/org/apache/coyote/http11/Http11Processor.java
index f6f34e8f45..dac9e8e419 100644
--- a/java/org/apache/coyote/http11/Http11Processor.java
+++ b/java/org/apache/coyote/http11/Http11Processor.java
@@ -1035,9 +1035,15 @@ public class Http11Processor extends AbstractProcessor {
             headers.removeHeader("transfer-encoding");
         }
 
-        // Build the response header
+        writeHeaders(response.getStatus(), headers);
+
+        outputBuffer.commit();
+    }
+
+
+    private void writeHeaders(int status, MimeHeaders headers) {
         try {
-            outputBuffer.sendStatus(response.getStatus());
+            outputBuffer.sendStatus(status);
 
             int size = headers.size();
             for (int i = 0; i < size; i++) {
@@ -1054,7 +1060,7 @@ public class Http11Processor extends AbstractProcessor {
                     outputBuffer.resetHeaderBuffer();
                     // -1 as it will be incremented at the start of the loop and header indexes start at 0.
                     i = -1;
-                    outputBuffer.sendStatus(response.getStatus());
+                    outputBuffer.sendStatus(status);
                 }
             }
             outputBuffer.endHeaders();
@@ -1065,10 +1071,9 @@ public class Http11Processor extends AbstractProcessor {
             outputBuffer.resetHeaderBuffer();
             throw t;
         }
-
-        outputBuffer.commit();
     }
 
+
     private static boolean isConnectionToken(MimeHeaders headers, String token) throws IOException {
         MessageBytes connection = headers.getValue(Constants.CONNECTION);
         if (connection == null) {


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 06/09: Remove deprecated code

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 26a9aef3e4f7f91d449e07202c365473279ac332
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 4 15:49:19 2024 +0100

    Remove deprecated code
---
 java/org/apache/coyote/http11/Http11OutputBuffer.java | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/java/org/apache/coyote/http11/Http11OutputBuffer.java b/java/org/apache/coyote/http11/Http11OutputBuffer.java
index 07381f1b50..bd1a66730f 100644
--- a/java/org/apache/coyote/http11/Http11OutputBuffer.java
+++ b/java/org/apache/coyote/http11/Http11OutputBuffer.java
@@ -321,17 +321,6 @@ public class Http11OutputBuffer implements HttpOutputBuffer {
     }
 
 
-    /**
-     * Send the response status line.
-     *
-     * @deprecated Unused. Will be removed in Tomcat 11. Use {@link #sendStatus(int)}.
-     */
-    @Deprecated
-    public void sendStatus() {
-        sendStatus(response.getStatus());
-    }
-
-
     /**
      * Send the response status line.
      *


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 09/09: Add a changelog entry

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 809548fd8a3157735ef867675ccd726320f52349
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Jul 19 12:44:17 2024 +0100

    Add a changelog entry
---
 webapps/docs/changelog.xml | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 944d0bfaf3..0fa7268704 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -105,6 +105,18 @@
   issues do not "pop up" wrt. others).
 -->
 <section name="Tomcat 11.0.0-M23 (markt)" rtext="in development">
+  <subsection name="Catalina">
+    <changelog>
+      <add>
+        Add support for RFC 8297 (Early Hints). Applications can use this
+        feature by casting the <code>HttpServletResponse</code> to
+        <code>org.apache.catalina.connector.Reponse</code> and then calling the
+        method <code>void sendEarlyHints()</code>. This method will be added to
+        the Servlet API (removing the need for the cast) in Servlet 6.2 onwards.
+        (markt)
+      </add>
+    </changelog>
+  </subsection>
   <subsection name="Coyote">
     <changelog>
       <update>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 07/09: AJP doesn't support 1xx responses.

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit d4db19dabf59b2696f10149a4df106c14607db7b
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 4 16:09:33 2024 +0100

    AJP doesn't support 1xx responses.
---
 java/org/apache/coyote/ajp/AjpProcessor.java | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/java/org/apache/coyote/ajp/AjpProcessor.java b/java/org/apache/coyote/ajp/AjpProcessor.java
index 9563c2b592..8df1960e10 100644
--- a/java/org/apache/coyote/ajp/AjpProcessor.java
+++ b/java/org/apache/coyote/ajp/AjpProcessor.java
@@ -1059,8 +1059,7 @@ public class AjpProcessor extends AbstractProcessor {
 
     @Override
     protected void earlyHints() throws IOException {
-        // TODO Auto-generated method stub
-        // NO-OP for now
+        // NO-OP for AJP
     }
 
 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 08/09: Add HTTP/2 support for early hints

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 73df9bd7d98ef3a562ccdb67403f6d29a2ff185c
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 4 16:53:21 2024 +0100

    Add HTTP/2 support for early hints
---
 java/org/apache/coyote/http2/Stream.java           | 16 ++++++
 java/org/apache/coyote/http2/StreamProcessor.java  |  3 +-
 .../apache/coyote/http2/TestStreamProcessor.java   | 67 ++++++++++++++++++++++
 3 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java
index f8e80be5b8..923f7c9c9c 100644
--- a/java/org/apache/coyote/http2/Stream.java
+++ b/java/org/apache/coyote/http2/Stream.java
@@ -590,6 +590,22 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
     }
 
 
+    final void writeEarlyHints() throws IOException {
+        MimeHeaders headers = coyoteResponse.getMimeHeaders();
+        String originalStatus = headers.getHeader(":status");
+        headers.setValue(":status").setString("103");
+        try {
+            handler.writeHeaders(this, headers, false, Constants.DEFAULT_HEADERS_FRAME_SIZE);
+        } finally {
+            if (originalStatus == null) {
+                headers.removeHeader(":status");
+            } else {
+                headers.setValue(":status").setString(originalStatus);
+            }
+        }
+    }
+
+
     @Override
     final String getConnectionId() {
         return handler.getConnectionId();
diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java
index c99a1691b7..89a6116854 100644
--- a/java/org/apache/coyote/http2/StreamProcessor.java
+++ b/java/org/apache/coyote/http2/StreamProcessor.java
@@ -270,8 +270,7 @@ class StreamProcessor extends AbstractProcessor {
 
     @Override
     protected void earlyHints() throws IOException {
-        // TODO Auto-generated method stub
-        // NO-OP for now
+        stream.writeEarlyHints();
     }
 
 
diff --git a/test/org/apache/coyote/http2/TestStreamProcessor.java b/test/org/apache/coyote/http2/TestStreamProcessor.java
index ac362c6e30..4208ff5954 100644
--- a/test/org/apache/coyote/http2/TestStreamProcessor.java
+++ b/test/org/apache/coyote/http2/TestStreamProcessor.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -36,6 +37,7 @@ import org.junit.Test;
 import org.apache.catalina.Context;
 import org.apache.catalina.Wrapper;
 import org.apache.catalina.connector.Connector;
+import org.apache.catalina.connector.ResponseFacade;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.tomcat.util.compat.JrePlatform;
 import org.apache.tomcat.util.http.FastHttpDateFormat;
@@ -586,4 +588,69 @@ public class TestStreamProcessor extends Http2TestBase {
         String trace = output.getTrace();
         Assert.assertTrue(trace, trace.contains("3-Header-[:status]-[501]"));
     }
+
+
+    @Test
+    public void testEarlyHints() throws Exception {
+        enableHttp2();
+
+        Tomcat tomcat = getTomcatInstance();
+
+        Context ctxt = getProgrammaticRootContext();
+        Tomcat.addServlet(ctxt, "simple", new SimpleServlet());
+        ctxt.addServletMappingDecoded("/simple", "simple");
+        Tomcat.addServlet(ctxt, "ehs", new EarlyHintsServlet());
+        ctxt.addServletMappingDecoded("/ehs", "ehs");
+        tomcat.start();
+
+        openClientConnection();
+        doHttpUpgrade();
+        sendClientPreface();
+        validateHttp2InitialResponse();
+
+        // Disable overhead protection for window update as it breaks some tests
+        http2Protocol.setOverheadWindowUpdateThreshold(0);
+
+        byte[] headersFrameHeader = new byte[9];
+        ByteBuffer headersPayload = ByteBuffer.allocate(128);
+
+        buildGetRequest(headersFrameHeader, headersPayload, null, 3, "/ehs");
+
+        // Write the headers
+        writeFrame(headersFrameHeader, headersPayload);
+
+        parser.readFrame();
+
+        Assert.assertEquals("3-HeadersStart\n" + "3-Header-[:status]-[103]\n" +
+                "3-Header-[link]-[</style.css>; rel=preload; as=style]\n" + "3-HeadersEnd\n", output.getTrace());
+        output.clearTrace();
+
+        parser.readFrame();
+        parser.readFrame();
+
+        Assert.assertEquals("3-HeadersStart\n" + "3-Header-[:status]-[200]\n" +
+                "3-Header-[link]-[</style.css>; rel=preload; as=style]\n" +
+                "3-Header-[content-type]-[text/plain;charset=UTF-8]\n" +
+                "3-Header-[content-length]-[2]\n" +
+                "3-Header-[date]-[" + DEFAULT_DATE + "]\n" + "3-HeadersEnd\n" + "3-Body-2\n" + "3-EndOfStream\n",
+                output.getTrace());
+    }
+
+
+    private static class EarlyHintsServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+            resp.addHeader("Link", "</style.css>; rel=preload; as=style");
+
+            ((ResponseFacade) resp).sendEarlyHints();
+
+            resp.setCharacterEncoding(StandardCharsets.UTF_8);
+            resp.setContentType("text/plain");
+
+            resp.getWriter().write("OK");
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: (tomcat) 03/09: Refactor writing of the status code

Posted by Koteswararao Gundapaneni <ap...@gmail.com>.
Hi Mark,

response.getStatus() should be identical I mean it is json eval


On Fri, 19 Jul 2024, 20:39 , <ma...@apache.org> wrote:

> This is an automated email from the ASF dual-hosted git repository.
>
> markt pushed a commit to branch main
> in repository https://gitbox.apache.org/repos/asf/tomcat.git
>
> commit ff7a869fd203b3b60ffd699c47da1d07e77f0c3a
> Author: Mark Thomas <ma...@apache.org>
> AuthorDate: Thu Jul 4 14:15:50 2024 +0100
>
>     Refactor writing of the status code
>
>     This refactoring is part of the preparation for RFC 8297 (Early Hints)
>     support.
> ---
>  java/org/apache/coyote/http11/Http11OutputBuffer.java | 14 +++++++++++++-
>  java/org/apache/coyote/http11/Http11Processor.java    |  4 ++--
>  2 files changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/java/org/apache/coyote/http11/Http11OutputBuffer.java
> b/java/org/apache/coyote/http11/Http11OutputBuffer.java
> index be7955c1b0..76fdb0d126 100644
> --- a/java/org/apache/coyote/http11/Http11OutputBuffer.java
> +++ b/java/org/apache/coyote/http11/Http11OutputBuffer.java
> @@ -320,14 +320,26 @@ public class Http11OutputBuffer implements
> HttpOutputBuffer {
>
>      /**
>       * Send the response status line.
> +     *
> +     * @deprecated Unused. Will be removed in Tomcat 11. Use {@link
> #sendStatus(int)}.
>       */
> +    @Deprecated
>      public void sendStatus() {
> +        sendStatus(response.getStatus());
> +    }
> +
> +
> +    /**
> +     * Send the response status line.
> +     *
> +     * @param status The HTTP status code to include in the status line
> +     */
> +    public void sendStatus(int status) {
>          // Write protocol name
>          write(Constants.HTTP_11_BYTES);
>          headerBuffer.put(Constants.SP);
>
>          // Write status code
> -        int status = response.getStatus();
>          switch (status) {
>              case 200:
>                  write(Constants._200_BYTES);
> diff --git a/java/org/apache/coyote/http11/Http11Processor.java
> b/java/org/apache/coyote/http11/Http11Processor.java
> index 681db0e96b..f6f34e8f45 100644
> --- a/java/org/apache/coyote/http11/Http11Processor.java
> +++ b/java/org/apache/coyote/http11/Http11Processor.java
> @@ -1037,7 +1037,7 @@ public class Http11Processor extends
> AbstractProcessor {
>
>          // Build the response header
>          try {
> -            outputBuffer.sendStatus();
> +            outputBuffer.sendStatus(response.getStatus());
>
>              int size = headers.size();
>              for (int i = 0; i < size; i++) {
> @@ -1054,7 +1054,7 @@ public class Http11Processor extends
> AbstractProcessor {
>                      outputBuffer.resetHeaderBuffer();
>                      // -1 as it will be incremented at the start of the
> loop and header indexes start at 0.
>                      i = -1;
> -                    outputBuffer.sendStatus();
> +                    outputBuffer.sendStatus(response.getStatus());
>                  }
>              }
>              outputBuffer.endHeaders();
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>
>

(tomcat) 03/09: Refactor writing of the status code

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit ff7a869fd203b3b60ffd699c47da1d07e77f0c3a
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 4 14:15:50 2024 +0100

    Refactor writing of the status code
    
    This refactoring is part of the preparation for RFC 8297 (Early Hints)
    support.
---
 java/org/apache/coyote/http11/Http11OutputBuffer.java | 14 +++++++++++++-
 java/org/apache/coyote/http11/Http11Processor.java    |  4 ++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/java/org/apache/coyote/http11/Http11OutputBuffer.java b/java/org/apache/coyote/http11/Http11OutputBuffer.java
index be7955c1b0..76fdb0d126 100644
--- a/java/org/apache/coyote/http11/Http11OutputBuffer.java
+++ b/java/org/apache/coyote/http11/Http11OutputBuffer.java
@@ -320,14 +320,26 @@ public class Http11OutputBuffer implements HttpOutputBuffer {
 
     /**
      * Send the response status line.
+     *
+     * @deprecated Unused. Will be removed in Tomcat 11. Use {@link #sendStatus(int)}.
      */
+    @Deprecated
     public void sendStatus() {
+        sendStatus(response.getStatus());
+    }
+
+
+    /**
+     * Send the response status line.
+     *
+     * @param status The HTTP status code to include in the status line
+     */
+    public void sendStatus(int status) {
         // Write protocol name
         write(Constants.HTTP_11_BYTES);
         headerBuffer.put(Constants.SP);
 
         // Write status code
-        int status = response.getStatus();
         switch (status) {
             case 200:
                 write(Constants._200_BYTES);
diff --git a/java/org/apache/coyote/http11/Http11Processor.java b/java/org/apache/coyote/http11/Http11Processor.java
index 681db0e96b..f6f34e8f45 100644
--- a/java/org/apache/coyote/http11/Http11Processor.java
+++ b/java/org/apache/coyote/http11/Http11Processor.java
@@ -1037,7 +1037,7 @@ public class Http11Processor extends AbstractProcessor {
 
         // Build the response header
         try {
-            outputBuffer.sendStatus();
+            outputBuffer.sendStatus(response.getStatus());
 
             int size = headers.size();
             for (int i = 0; i < size; i++) {
@@ -1054,7 +1054,7 @@ public class Http11Processor extends AbstractProcessor {
                     outputBuffer.resetHeaderBuffer();
                     // -1 as it will be incremented at the start of the loop and header indexes start at 0.
                     i = -1;
-                    outputBuffer.sendStatus();
+                    outputBuffer.sendStatus(response.getStatus());
                 }
             }
             outputBuffer.endHeaders();


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 05/09: Implement early hints for HTTP/1.1

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 3f37960753a54e9cd500268c05f117ca1701e5d6
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 4 15:48:18 2024 +0100

    Implement early hints for HTTP/1.1
---
 java/org/apache/catalina/connector/Response.java   | 14 +++++++
 .../apache/catalina/connector/ResponseFacade.java  |  4 ++
 java/org/apache/coyote/AbstractProcessor.java      | 11 +++++
 java/org/apache/coyote/ActionCode.java             |  7 +++-
 java/org/apache/coyote/ajp/AjpProcessor.java       |  7 ++++
 .../apache/coyote/http11/Http11OutputBuffer.java   |  3 ++
 java/org/apache/coyote/http11/Http11Processor.java |  8 ++++
 java/org/apache/coyote/http2/StreamProcessor.java  |  7 ++++
 .../apache/coyote/http11/TestHttp11Processor.java  | 49 ++++++++++++++++++++++
 9 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/catalina/connector/Response.java b/java/org/apache/catalina/connector/Response.java
index 21fc8f1138..66dd7cab47 100644
--- a/java/org/apache/catalina/connector/Response.java
+++ b/java/org/apache/catalina/connector/Response.java
@@ -1037,6 +1037,20 @@ public class Response implements HttpServletResponse {
     }
 
 
+    public void sendEarlyHints() {
+        if (isCommitted()) {
+            return;
+        }
+
+        // Ignore any call from an included servlet
+        if (included) {
+            return;
+        }
+
+        getCoyoteResponse().action(ActionCode.EARLY_HINTS, null);
+    }
+
+
     @Override
     public void sendError(int status) throws IOException {
         sendError(status, null);
diff --git a/java/org/apache/catalina/connector/ResponseFacade.java b/java/org/apache/catalina/connector/ResponseFacade.java
index b09b4731a8..dcc4ee059d 100644
--- a/java/org/apache/catalina/connector/ResponseFacade.java
+++ b/java/org/apache/catalina/connector/ResponseFacade.java
@@ -245,6 +245,10 @@ public class ResponseFacade implements HttpServletResponse {
     }
 
 
+    public void sendEarlyHints() {
+        response.sendEarlyHints();
+    }
+
     @Override
     public void sendError(int sc, String msg) throws IOException {
         checkCommitted("coyoteResponse.sendError.ise");
diff --git a/java/org/apache/coyote/AbstractProcessor.java b/java/org/apache/coyote/AbstractProcessor.java
index 21a7ef2304..30e4e12bd5 100644
--- a/java/org/apache/coyote/AbstractProcessor.java
+++ b/java/org/apache/coyote/AbstractProcessor.java
@@ -393,6 +393,14 @@ public abstract class AbstractProcessor extends AbstractProcessorLight implement
                 ack((ContinueResponseTiming) param);
                 break;
             }
+            case EARLY_HINTS: {
+                try {
+                    earlyHints();
+                } catch (IOException e) {
+                    handleIOException(e);
+                }
+                break;
+            }
             case CLIENT_FLUSH: {
                 action(ActionCode.COMMIT, null);
                 try {
@@ -734,6 +742,9 @@ public abstract class AbstractProcessor extends AbstractProcessorLight implement
     protected abstract void ack(ContinueResponseTiming continueResponseTiming);
 
 
+    protected abstract void earlyHints() throws IOException;
+
+
     /**
      * Callback to write data from the buffer.
      * @throws IOException IO exception during the write
diff --git a/java/org/apache/coyote/ActionCode.java b/java/org/apache/coyote/ActionCode.java
index 15531f7c39..2b233fb82c 100644
--- a/java/org/apache/coyote/ActionCode.java
+++ b/java/org/apache/coyote/ActionCode.java
@@ -265,5 +265,10 @@ public enum ActionCode {
     /**
      * Obtain the servlet connection instance for the network connection supporting the current request.
      */
-    SERVLET_CONNECTION
+    SERVLET_CONNECTION,
+
+    /**
+     * Send an RFC 8297 Early Hints informational response.
+     */
+    EARLY_HINTS
 }
diff --git a/java/org/apache/coyote/ajp/AjpProcessor.java b/java/org/apache/coyote/ajp/AjpProcessor.java
index 1c568b05aa..9563c2b592 100644
--- a/java/org/apache/coyote/ajp/AjpProcessor.java
+++ b/java/org/apache/coyote/ajp/AjpProcessor.java
@@ -1057,6 +1057,13 @@ public class AjpProcessor extends AbstractProcessor {
     }
 
 
+    @Override
+    protected void earlyHints() throws IOException {
+        // TODO Auto-generated method stub
+        // NO-OP for now
+    }
+
+
     @Override
     protected final int available(boolean doRead) {
         if (endOfStream) {
diff --git a/java/org/apache/coyote/http11/Http11OutputBuffer.java b/java/org/apache/coyote/http11/Http11OutputBuffer.java
index 76fdb0d126..07381f1b50 100644
--- a/java/org/apache/coyote/http11/Http11OutputBuffer.java
+++ b/java/org/apache/coyote/http11/Http11OutputBuffer.java
@@ -300,7 +300,10 @@ public class Http11OutputBuffer implements HttpOutputBuffer {
      */
     protected void commit() throws IOException {
         response.setCommitted(true);
+        writeHeaders();
+    }
 
+    protected void writeHeaders() throws IOException {
         if (headerBuffer.position() > 0) {
             // Sending the response header buffer
             headerBuffer.flip();
diff --git a/java/org/apache/coyote/http11/Http11Processor.java b/java/org/apache/coyote/http11/Http11Processor.java
index dac9e8e419..7d1b2e0431 100644
--- a/java/org/apache/coyote/http11/Http11Processor.java
+++ b/java/org/apache/coyote/http11/Http11Processor.java
@@ -1242,6 +1242,14 @@ public class Http11Processor extends AbstractProcessor {
     }
 
 
+    @Override
+    protected void earlyHints() throws IOException {
+        writeHeaders(103, response.getMimeHeaders());
+        outputBuffer.writeHeaders();
+        outputBuffer.resetHeaderBuffer();
+    }
+
+
     @Override
     protected final void flush() throws IOException {
         outputBuffer.flush();
diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java
index fdc8c4b160..c99a1691b7 100644
--- a/java/org/apache/coyote/http2/StreamProcessor.java
+++ b/java/org/apache/coyote/http2/StreamProcessor.java
@@ -268,6 +268,13 @@ class StreamProcessor extends AbstractProcessor {
     }
 
 
+    @Override
+    protected void earlyHints() throws IOException {
+        // TODO Auto-generated method stub
+        // NO-OP for now
+    }
+
+
     @Override
     protected final void flush() throws IOException {
         stream.getOutputBuffer().flush();
diff --git a/test/org/apache/coyote/http11/TestHttp11Processor.java b/test/org/apache/coyote/http11/TestHttp11Processor.java
index 857d51185d..c1fad26110 100644
--- a/test/org/apache/coyote/http11/TestHttp11Processor.java
+++ b/test/org/apache/coyote/http11/TestHttp11Processor.java
@@ -53,6 +53,7 @@ import org.junit.Test;
 import org.apache.catalina.Context;
 import org.apache.catalina.Wrapper;
 import org.apache.catalina.connector.Connector;
+import org.apache.catalina.connector.ResponseFacade;
 import org.apache.catalina.startup.SimpleHttpClient;
 import org.apache.catalina.startup.TesterServlet;
 import org.apache.catalina.startup.Tomcat;
@@ -1912,4 +1913,52 @@ public class TestHttp11Processor extends TomcatBaseTest {
 
         }
     }
+
+
+    @Test
+    public void testEarlyHints() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+
+        // No file system docBase required
+        Context ctx = getProgrammaticRootContext();
+
+        // Add servlet
+        Tomcat.addServlet(ctx, "EarlyHintsServlet", new EarlyHintsServlet());
+        ctx.addServletMappingDecoded("/ehs", "EarlyHintsServlet");
+
+        tomcat.start();
+
+        String request = "GET /ehs HTTP/1.1" + SimpleHttpClient.CRLF +
+                "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
+                SimpleHttpClient.CRLF;
+
+        Client client = new Client(tomcat.getConnector().getLocalPort());
+        client.setRequest(new String[] { request });
+
+        client.connect(600000, 600000);
+        client.processRequest(false);
+
+        Assert.assertEquals(103, client.getStatusCode());
+
+        client.readResponse(false);
+        Assert.assertEquals(HttpServletResponse.SC_OK, client.getStatusCode());
+    }
+
+
+    private static class EarlyHintsServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+            resp.addHeader("Link", "</style.css>; rel=preload; as=style");
+
+            ((ResponseFacade) resp).sendEarlyHints();
+
+            resp.setCharacterEncoding(StandardCharsets.UTF_8);
+            resp.setContentType("text/plain");
+
+            resp.getWriter().write("OK");
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


(tomcat) 02/09: Remove deprecated code

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 9dba4efc0f0f878076d3bfe113366c047c600b0d
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 4 13:50:56 2024 +0100

    Remove deprecated code
---
 java/org/apache/coyote/Response.java | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/java/org/apache/coyote/Response.java b/java/org/apache/coyote/Response.java
index ca89a1afca..cdc15a854e 100644
--- a/java/org/apache/coyote/Response.java
+++ b/java/org/apache/coyote/Response.java
@@ -445,17 +445,6 @@ public final class Response {
     }
 
 
-    /**
-     * Signal that we're done with the headers, and body will follow.
-     *
-     * @deprecated Unused. Will be removed in Tomcat 11 onwards. Use {@link #commit()}.
-     */
-    @Deprecated
-    public void sendHeaders() {
-        commit();
-    }
-
-
     /**
      * Signal that we're done with the headers, and body will follow.
      */


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org