Skip to content

Commit

Permalink
Issue #11292 - Missing Date Response Header.
Browse files Browse the repository at this point in the history
* Revert changes to boolean values in HttpConfiguration from commit 103e1d9
* Add Unit Tests for Date Response header
  in ee10 and DistributionTests
  • Loading branch information
joakime committed Jan 19, 2024
1 parent a2d86c7 commit f8d6d50
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 2 deletions.
4 changes: 2 additions & 2 deletions jetty-core/jetty-server/src/main/config/etc/jetty.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<Set name="requestHeaderSize" property="jetty.httpConfig.requestHeaderSize"/>
<Set name="responseHeaderSize" property="jetty.httpConfig.responseHeaderSize"/>
<Set name="sendServerVersion" property="jetty.httpConfig.sendServerVersion"/>
<Set name="sendDateHeader"><Property name="jetty.httpConfig.sendDateHeader" default="false"/></Set>
<Set name="sendDateHeader" property="jetty.httpConfig.sendDateHeader"/>
<Set name="headerCacheSize" property="jetty.httpConfig.headerCacheSize"/>
<Set name="delayDispatchUntilContent" property="jetty.httpConfig.delayDispatchUntilContent"/>
<Set name="maxErrorDispatches" property="jetty.httpConfig.maxErrorDispatches"/>
Expand All @@ -66,7 +66,7 @@
<Set name="uriCompliance"><Call class="org.eclipse.jetty.http.UriCompliance" name="from"><Arg><Property name="jetty.httpConfig.uriCompliance" default="DEFAULT"/></Arg></Call></Set>
<Set name="requestCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="from"><Arg><Property name="jetty.httpConfig.requestCookieCompliance" default="RFC6265"/></Arg></Call></Set>
<Set name="responseCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="from"><Arg><Property name="jetty.httpConfig.responseCookieCompliance" default="RFC6265"/></Arg></Call></Set>
<Set name="relativeRedirectAllowed"><Property name="jetty.httpConfig.relativeRedirectAllowed" default="false"/></Set>
<Set name="relativeRedirectAllowed" property="jetty.httpConfig.relativeRedirectAllowed"/>
<Set name="useInputDirectByteBuffers" property="jetty.httpConfig.useInputDirectByteBuffers"/>
<Set name="useOutputDirectByteBuffers" property="jetty.httpConfig.useOutputDirectByteBuffers"/>
</New>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@
package org.eclipse.jetty.ee10.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URI;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -24,26 +31,37 @@
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.stream.Stream;

import jakarta.servlet.MultipartConfigElement;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.http.UriCompliance;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.FormFields;
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.component.LifeCycle;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
Expand All @@ -56,13 +74,21 @@
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class RequestTest
{
private static final Logger LOG = LoggerFactory.getLogger(RequestTest.class);
private Server _server;
private LocalConnector _connector;

private void startServer(HttpServlet servlet) throws Exception
{
startServer(null, servlet);
}

private void startServer(Consumer<Server> configureServer, HttpServlet servlet) throws Exception
{
_server = new Server();

Expand All @@ -80,6 +106,9 @@ private void startServer(HttpServlet servlet) throws Exception
servletContextHandler.addServlet(servlet, "/*").getRegistration().setMultipartConfig(new MultipartConfigElement("here"));

_server.setHandler(servletContextHandler);

if (configureServer != null)
configureServer.accept(_server);
_server.start();
}

Expand Down Expand Up @@ -473,4 +502,74 @@ protected void service(HttpServletRequest request, HttpServletResponse resp) thr
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
assertThat(response.getStatus(), is(HttpStatus.OK_200));
}

public static Stream<Arguments> requestHostHeaders()
{
List<String> hostHeader = new ArrayList<>();
hostHeader.add("localhost");
hostHeader.add("127.0.0.1");
try
{
InetAddress localhost = InetAddress.getLocalHost();
hostHeader.add(localhost.getHostName());
hostHeader.add(localhost.getHostAddress());
}
catch (UnknownHostException e)
{
LOG.debug("Unable to obtain InetAddress.LocalHost", e);
}
return hostHeader.stream().map(Arguments::of);
}

@ParameterizedTest
@MethodSource("requestHostHeaders")
public void testDateResponseHeader(String hostHeader) throws Exception
{
startServer(
(server) ->
{
HttpConfiguration httpConfiguration = new HttpConfiguration();
// httpConfiguration.setSendDateHeader(true);
ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration));
connector.setPort(0);
server.addConnector(connector);
},
new HttpServlet()
{
@Override
protected void service(HttpServletRequest request, HttpServletResponse resp) throws IOException
{
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/plain");
resp.getWriter().println("Foo");
}
});

URI serverURI = _server.getURI();

String rawRequest = """
GET /foo HTTP/1.1
Host: %s
Connection: close
""".formatted(hostHeader);

try (Socket client = new Socket(hostHeader, serverURI.getPort()))
{
OutputStream out = client.getOutputStream();
out.write(rawRequest.getBytes(StandardCharsets.UTF_8));
out.flush();

InputStream in = client.getInputStream();
HttpTester.Response response = HttpTester.parseResponse(in);
assertThat(response.getStatus(), is(HttpStatus.OK_200));
String date = response.get(HttpHeader.DATE);
assertNotNull(date);
// asserting an exact value is tricky as the Date header is dynamic,
// so we just assert that it has some content and isn't blank
assertTrue(StringUtil.isNotBlank(date));
assertThat(date, containsString(","));
assertThat(date, containsString(":"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.net.http.WebSocket;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -65,6 +67,8 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.awaitility.Awaitility.await;
import static org.hamcrest.MatcherAssert.assertThat;
Expand All @@ -73,6 +77,7 @@
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
Expand All @@ -81,6 +86,8 @@

public class DistributionTests extends AbstractJettyHomeTest
{
private static final Logger LOG = LoggerFactory.getLogger(DistributionTests.class);

@Test
public void testStartStop() throws Exception
{
Expand Down Expand Up @@ -1726,6 +1733,61 @@ public void testInetAccessHandler() throws Exception
}
}

@Test
public void testSendDateHeader() throws Exception
{
Path jettyBase = newTestJettyBaseDirectory();
String jettyVersion = System.getProperty("jettyVersion");
JettyHomeTester distribution = JettyHomeTester.Builder.newInstance()
.jettyVersion(jettyVersion)
.jettyBase(jettyBase)
.build();

try (JettyHomeTester.Run run1 = distribution.start("--add-modules=http"))
{
assertTrue(run1.awaitFor(10, TimeUnit.SECONDS));
assertEquals(0, run1.getExitValue());

int httpPort = distribution.freePort();
List<String> args = List.of("jetty.http.port=" + httpPort);
try (JettyHomeTester.Run run2 = distribution.start(args))
{
assertTrue(run2.awaitConsoleLogsFor("Started oejs.Server@", START_TIMEOUT, TimeUnit.SECONDS));
startHttpClient();

List<String> hostHeaders = new ArrayList<>();
hostHeaders.add("localhost");
hostHeaders.add("127.0.0.1");
try
{
InetAddress localhost = InetAddress.getLocalHost();
hostHeaders.add(localhost.getHostName());
hostHeaders.add(localhost.getHostAddress());
}
catch (UnknownHostException e)
{
LOG.debug("Unable to obtain InetAddress.LocalHost", e);
}

for (String hostHeader: hostHeaders)
{
ContentResponse response = client.newRequest("http://" + hostHeader + ":" + httpPort + "/")
.timeout(15, TimeUnit.SECONDS)
.send();
assertEquals(HttpStatus.NOT_FOUND_404, response.getStatus());
String date = response.getHeaders().get(HttpHeader.DATE);
String msg = "Request to [%s]: Response Header [Date]".formatted(hostHeader);
assertThat(msg, date, notNullValue());
// asserting an exact value is tricky as the Date header is dynamic,
// so we just assert that it has some content and isn't blank
assertTrue(StringUtil.isNotBlank(date), msg);
assertThat(msg, date, containsString(","));
assertThat(msg, date, containsString(":"));
}
}
}
}

@Test
public void testCrossOriginModule() throws Exception
{
Expand Down

0 comments on commit f8d6d50

Please sign in to comment.