On Wed, Mar 4, 2026 at 9:12 AM Mark Thomas <[email protected]> wrote:
>
> Thoughts on back-porting this? From a consistency point of view we
> probably should. If someone calls setHeader("Content-Type","something")
> they'd expect a call to getHeader("Content-Type") to return the value
> they just set.

I'm backporting it right now, it was late so I did not do it immediately.

Rémy

> Mark
>
> On 03/03/2026 23:15, [email protected] wrote:
> > This is an automated email from the ASF dual-hosted git repository.
> >
> > remm pushed a commit to branch main
> > in repository https://gitbox.apache.org/repos/asf/tomcat.git
> >
> >
> > The following commit(s) were added to refs/heads/main by this push:
> >       new 5f9bd1d87d Fix inconsistencies with special headers and getHeader
> > 5f9bd1d87d is described below
> >
> > commit 5f9bd1d87d18b3898ebcc5a103a8266f5f98ce9a
> > Author: remm <[email protected]>
> > AuthorDate: Wed Mar 4 00:15:20 2026 +0100
> >
> >      Fix inconsistencies with special headers and getHeader
> >
> >      Handling of Content-Type and Content-Length with getHeader,
> >      getHeaderNames and getHeaders.
> >      BZ69967
> > ---
> >   java/org/apache/catalina/connector/Response.java   | 46 
> > +++++++++++++++++++++-
> >   .../apache/catalina/connector/TestResponse.java    | 18 +++++++++
> >   webapps/docs/changelog.xml                         |  5 +++
> >   3 files changed, 68 insertions(+), 1 deletion(-)
> >
> > diff --git a/java/org/apache/catalina/connector/Response.java 
> > b/java/org/apache/catalina/connector/Response.java
> > index 3741673014..55aa8b826d 100644
> > --- a/java/org/apache/catalina/connector/Response.java
> > +++ b/java/org/apache/catalina/connector/Response.java
> > @@ -747,6 +747,23 @@ public class Response implements HttpServletResponse {
> >
> >       @Override
> >       public String getHeader(String name) {
> > +        // Need special handling for Content-Type and Content-Length due to
> > +        // special handling of these in coyoteResponse
> > +        char cc = name.charAt(0);
> > +        if (cc == 'C' || cc == 'c') {
> > +            if (name.equalsIgnoreCase("Content-Type")) {
> > +                // Will return null if this has not been set
> > +                return getCoyoteResponse().getContentType();
> > +            }
> > +            if (name.equalsIgnoreCase("Content-Length")) {
> > +                // -1 means not known and is not sent to client
> > +                if (getCoyoteResponse().getContentLengthLong() != -1) {
> > +                    return 
> > String.valueOf(getCoyoteResponse().getContentLengthLong());
> > +                } else {
> > +                    return null;
> > +                }
> > +            }
> > +        }
> >           return getCoyoteResponse().getMimeHeaders().getHeader(name);
> >       }
> >
> > @@ -759,13 +776,40 @@ public class Response implements HttpServletResponse {
> >           for (int i = 0; i < n; i++) {
> >               result.add(headers.getName(i).toString());
> >           }
> > +        if (getCoyoteResponse().getContentType() != null) {
> > +            result.add("Content-Type");
> > +        }
> > +        if (getCoyoteResponse().getContentLengthLong() != -1) {
> > +            result.add("Content-Length");
> > +        }
> >           return result;
> > -
> >       }
> >
> >
> >       @Override
> >       public Collection<String> getHeaders(String name) {
> > +        // Need special handling for Content-Type and Content-Length due to
> > +        // special handling of these in coyoteResponse
> > +        char cc = name.charAt(0);
> > +        if (cc == 'C' || cc == 'c') {
> > +            if (name.equalsIgnoreCase("Content-Type")) {
> > +                // Will return null if this has not been set
> > +                String contentType = getCoyoteResponse().getContentType();
> > +                if (contentType != null) {
> > +                    return Set.of(contentType);
> > +                } else {
> > +                    return Set.of();
> > +                }
> > +            }
> > +            if (name.equalsIgnoreCase("Content-Length")) {
> > +                // -1 means not known and is not sent to client
> > +                if (getCoyoteResponse().getContentLengthLong() != -1) {
> > +                    return 
> > Set.of(String.valueOf(getCoyoteResponse().getContentLengthLong()));
> > +                } else {
> > +                    return Set.of();
> > +                }
> > +            }
> > +        }
> >           Enumeration<String> enumeration = 
> > getCoyoteResponse().getMimeHeaders().values(name);
> >           Set<String> result = new LinkedHashSet<>();
> >           while (enumeration.hasMoreElements()) {
> > diff --git a/test/org/apache/catalina/connector/TestResponse.java 
> > b/test/org/apache/catalina/connector/TestResponse.java
> > index f79a3cebf8..9f0eb25a6b 100644
> > --- a/test/org/apache/catalina/connector/TestResponse.java
> > +++ b/test/org/apache/catalina/connector/TestResponse.java
> > @@ -736,6 +736,24 @@ public class TestResponse extends TomcatBaseTest {
> >       }
> >
> >
> > +    @Test
> > +    public void testSetContentLengthHeader() {
> > +        Response response = setupResponse();
> > +
> > +        response.setContentLength(10);
> > +        Assert.assertEquals("10", response.getHeader("Content-Length"));
> > +    }
> > +
> > +
> > +    @Test
> > +    public void testSetContentTypeHeader() {
> > +        Response response = setupResponse();
> > +
> > +        response.setContentType(TEXT_UTF_8);
> > +        Assert.assertEquals(TEXT_UTF_8, 
> > response.getHeader("Content-Type"));
> > +    }
> > +
> > +
> >       @Test
> >       public void testSetContentType01() {
> >           Response response = setupResponse();
> > diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
> > index 20d0219006..4851a94056 100644
> > --- a/webapps/docs/changelog.xml
> > +++ b/webapps/docs/changelog.xml
> > @@ -191,6 +191,11 @@
> >           to <code>true</code>. (markt)
> >         </update>
> >         <!-- Entries for backport and removal before 12.0.0-M1 below this 
> > line -->
> > +      <fix>
> > +        <bug>69967</bug>: Fix inconsistencies related to
> > +        <code>Content-Length</code> and <code>Content-Type</code> headers 
> > when
> > +        accessed using the <code>getHeader</code> method and similar. 
> > (remm)
> > +      </fix>
> >       </changelog>
> >     </subsection>
> >     <subsection name="Coyote">
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [email protected]
> > For additional commands, e-mail: [email protected]
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to