* Make HttpChannelState responsible for X-Powered-By / Server headers * Remove X-Powered-By handling in HttpGenerator
This commit is contained in:
parent
57d46fe0f7
commit
2178dc2913
|
@ -86,33 +86,17 @@ public class HttpGenerator
|
|||
private boolean _noContentResponse = false;
|
||||
private Boolean _persistent = null;
|
||||
|
||||
private final int _send;
|
||||
private static final int SEND_SERVER = 0x01;
|
||||
private static final int SEND_XPOWEREDBY = 0x02;
|
||||
private static final Index<Boolean> ASSUMED_CONTENT_METHODS = new Index.Builder<Boolean>()
|
||||
.caseSensitive(false)
|
||||
.with(HttpMethod.POST.asString(), Boolean.TRUE)
|
||||
.with(HttpMethod.PUT.asString(), Boolean.TRUE)
|
||||
.build();
|
||||
|
||||
public static void setJettyVersion(String serverVersion)
|
||||
{
|
||||
SEND[SEND_SERVER] = StringUtil.getBytes("Server: " + serverVersion + "\r\n");
|
||||
SEND[SEND_XPOWEREDBY] = StringUtil.getBytes("X-Powered-By: " + serverVersion + "\r\n");
|
||||
SEND[SEND_SERVER | SEND_XPOWEREDBY] = StringUtil.getBytes("Server: " + serverVersion + "\r\nX-Powered-By: " + serverVersion + "\r\n");
|
||||
}
|
||||
|
||||
// data
|
||||
private boolean _needCRLF = false;
|
||||
|
||||
public HttpGenerator()
|
||||
{
|
||||
this(false, false);
|
||||
}
|
||||
|
||||
public HttpGenerator(boolean sendServerVersion, boolean sendXPoweredBy)
|
||||
{
|
||||
_send = (sendServerVersion ? SEND_SERVER : 0) | (sendXPoweredBy ? SEND_XPOWEREDBY : 0);
|
||||
}
|
||||
|
||||
public void reset()
|
||||
|
@ -595,7 +579,6 @@ public class HttpGenerator
|
|||
}
|
||||
|
||||
// default field values
|
||||
int send = _send;
|
||||
HttpField transferEncoding = null;
|
||||
boolean http11 = _info.getHttpVersion() == HttpVersion.HTTP_1_1;
|
||||
boolean close = false;
|
||||
|
@ -669,13 +652,6 @@ public class HttpGenerator
|
|||
break;
|
||||
}
|
||||
|
||||
case SERVER:
|
||||
{
|
||||
send = send & ~SEND_SERVER;
|
||||
putTo(field, header);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
putTo(field, header);
|
||||
}
|
||||
|
@ -792,11 +768,6 @@ public class HttpGenerator
|
|||
}
|
||||
}
|
||||
|
||||
// Send server?
|
||||
int status = response != null ? response.getStatus() : -1;
|
||||
if (status > 199)
|
||||
header.put(SEND[send]);
|
||||
|
||||
// end the header.
|
||||
header.put(HttpTokens.CRLF);
|
||||
}
|
||||
|
@ -839,9 +810,9 @@ public class HttpGenerator
|
|||
private static final byte[] TRANSFER_ENCODING_CHUNKED = StringUtil.getBytes("Transfer-Encoding: chunked\r\n");
|
||||
private static final byte[][] SEND = new byte[][]{
|
||||
new byte[0],
|
||||
StringUtil.getBytes("Server: Jetty(10.x.x)\r\n"),
|
||||
StringUtil.getBytes("X-Powered-By: Jetty(10.x.x)\r\n"),
|
||||
StringUtil.getBytes("Server: Jetty(10.x.x)\r\nX-Powered-By: Jetty(10.x.x)\r\n")
|
||||
StringUtil.getBytes("Server: Jetty(12.x.x)\r\n"),
|
||||
StringUtil.getBytes("X-Powered-By: Jetty(12.x.x)\r\n"),
|
||||
StringUtil.getBytes("Server: Jetty(12.x.x)\r\nX-Powered-By: Jetty(12.x.x)\r\n")
|
||||
};
|
||||
|
||||
// Build cache of response lines for status
|
||||
|
|
|
@ -213,55 +213,6 @@ public class HttpGeneratorServerTest
|
|||
assertThat(response, containsString("\r\n0123456789"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendServerXPoweredBy() throws Exception
|
||||
{
|
||||
ByteBuffer header = BufferUtil.allocate(8096);
|
||||
HttpFields.Mutable fields1 = HttpFields.build();
|
||||
MetaData.Response info = new MetaData.Response(200, null, HttpVersion.HTTP_1_1, fields1);
|
||||
HttpFields.Mutable fields2 = HttpFields.build();
|
||||
fields2.add(HttpHeader.SERVER, "SomeServer");
|
||||
fields2.add(HttpHeader.X_POWERED_BY, "SomePower");
|
||||
MetaData.Response infoF = new MetaData.Response(200, null, HttpVersion.HTTP_1_1, fields2);
|
||||
String head;
|
||||
|
||||
HttpGenerator gen = new HttpGenerator(true, true);
|
||||
gen.generateResponse(info, false, header, null, null, true);
|
||||
head = BufferUtil.toString(header);
|
||||
BufferUtil.clear(header);
|
||||
assertThat(head, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(head, containsString("Server: Jetty(10.x.x)"));
|
||||
assertThat(head, containsString("X-Powered-By: Jetty(10.x.x)"));
|
||||
gen.reset();
|
||||
gen.generateResponse(infoF, false, header, null, null, true);
|
||||
head = BufferUtil.toString(header);
|
||||
BufferUtil.clear(header);
|
||||
assertThat(head, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(head, not(containsString("Server: Jetty(10.x.x)")));
|
||||
assertThat(head, containsString("Server: SomeServer"));
|
||||
assertThat(head, containsString("X-Powered-By: Jetty(10.x.x)"));
|
||||
assertThat(head, containsString("X-Powered-By: SomePower"));
|
||||
gen.reset();
|
||||
|
||||
gen = new HttpGenerator(false, false);
|
||||
gen.generateResponse(info, false, header, null, null, true);
|
||||
head = BufferUtil.toString(header);
|
||||
BufferUtil.clear(header);
|
||||
assertThat(head, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(head, not(containsString("Server: Jetty(10.x.x)")));
|
||||
assertThat(head, not(containsString("X-Powered-By: Jetty(10.x.x)")));
|
||||
gen.reset();
|
||||
gen.generateResponse(infoF, false, header, null, null, true);
|
||||
head = BufferUtil.toString(header);
|
||||
BufferUtil.clear(header);
|
||||
assertThat(head, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(head, not(containsString("Server: Jetty(10.x.x)")));
|
||||
assertThat(head, containsString("Server: SomeServer"));
|
||||
assertThat(head, not(containsString("X-Powered-By: Jetty(10.x.x)")));
|
||||
assertThat(head, containsString("X-Powered-By: SomePower"));
|
||||
gen.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResponseIncorrectContentLength() throws Exception
|
||||
{
|
||||
|
|
|
@ -31,7 +31,6 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import org.eclipse.jetty.http.DateGenerator;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpGenerator;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
|
@ -527,8 +526,6 @@ public class Server extends Handler.Wrapper implements Attributes
|
|||
LOG.warn("Download a stable release from https://download.eclipse.org/jetty/");
|
||||
}
|
||||
|
||||
HttpGenerator.setJettyVersion(HttpConfiguration.SERVER_VERSION);
|
||||
|
||||
final ExceptionUtil.MultiException multiException = new ExceptionUtil.MultiException();
|
||||
|
||||
// Open network connector to ensure ports are available
|
||||
|
|
|
@ -165,7 +165,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Writ
|
|||
|
||||
protected HttpGenerator newHttpGenerator()
|
||||
{
|
||||
return new HttpGenerator(_configuration.getSendServerVersion(), _configuration.getSendXPoweredBy());
|
||||
return new HttpGenerator();
|
||||
}
|
||||
|
||||
protected HttpParser newHttpParser(HttpCompliance compliance)
|
||||
|
|
|
@ -94,7 +94,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
private static final String REQUEST1 = REQUEST1_HEADER + REQUEST1_CONTENT.getBytes().length + "\n\n" + REQUEST1_CONTENT;
|
||||
|
||||
private static final String RESPONSE1 = "HTTP/1.1 200 OK\n" +
|
||||
"Server: Jetty(" + Server.getVersion() + ")\n" +
|
||||
"Content-Type: text/plain;charset=utf-8\n" +
|
||||
"Content-Length: 5\n" +
|
||||
"\n" +
|
||||
|
@ -124,7 +123,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
|
||||
protected static final String RESPONSE2 =
|
||||
"HTTP/1.1 200 OK\n" +
|
||||
"Server: Jetty(" + Server.getVersion() + ")\n" +
|
||||
"Content-Type: text/xml; charset=ISO-8859-1\n" +
|
||||
"Content-Length: " + REQUEST2_CONTENT.getBytes().length + "\n" +
|
||||
"\n" +
|
||||
|
@ -728,7 +726,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Feed the server fragmentary headers and see how it copes with it.
|
||||
*/
|
||||
@Test
|
||||
|
|
|
@ -63,6 +63,7 @@ public class HttpServerTestFixture
|
|||
_connector = connector;
|
||||
_httpConfiguration = _connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration();
|
||||
_httpConfiguration.setSendDateHeader(false);
|
||||
_httpConfiguration.setSendServerVersion(false);
|
||||
_server.addConnector(_connector);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.eclipse.jetty.http.HttpCookie;
|
||||
|
@ -31,6 +32,7 @@ import org.junit.jupiter.api.Test;
|
|||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class ResponseTest
|
||||
|
@ -194,6 +196,80 @@ public class ResponseTest
|
|||
assertThat(response.get(HttpHeader.LOCATION), is("/somewhere/else"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXPoweredByDefault() throws Exception
|
||||
{
|
||||
server.getConnectors()[0].getConnectionFactory(HttpConnectionFactory.class)
|
||||
.getHttpConfiguration().setSendXPoweredBy(true);
|
||||
server.setHandler(new Handler.Abstract()
|
||||
{
|
||||
@Override
|
||||
public boolean handle(Request request, Response response, Callback callback)
|
||||
{
|
||||
Content.Sink.write(response, true, "Test", callback);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
server.start();
|
||||
|
||||
String request = """
|
||||
GET /test HTTP/1.0\r
|
||||
Host: hostname\r
|
||||
\r
|
||||
""";
|
||||
HttpTester.Response response = HttpTester.parseResponse(connector.getResponse(request));
|
||||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
|
||||
// ensure there are only 1 entry for each of these headers
|
||||
List<HttpHeader> expectedHeaders = List.of(HttpHeader.SERVER, HttpHeader.X_POWERED_BY, HttpHeader.DATE, HttpHeader.CONTENT_LENGTH);
|
||||
for (HttpHeader expectedHeader: expectedHeaders)
|
||||
{
|
||||
List<String> actualHeader = response.getValuesList(expectedHeader);
|
||||
assertThat(expectedHeader + " exists", actualHeader, is(notNullValue()));
|
||||
assertThat(expectedHeader + " header count", actualHeader.size(), is(1));
|
||||
}
|
||||
assertThat(response.get(HttpHeader.CONTENT_LENGTH), is("4"));
|
||||
assertThat(response.get(HttpHeader.X_POWERED_BY), is(HttpConfiguration.SERVER_VERSION));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXPoweredByOverride() throws Exception
|
||||
{
|
||||
server.getConnectors()[0].getConnectionFactory(HttpConnectionFactory.class)
|
||||
.getHttpConfiguration().setSendXPoweredBy(true);
|
||||
server.setHandler(new Handler.Abstract()
|
||||
{
|
||||
@Override
|
||||
public boolean handle(Request request, Response response, Callback callback)
|
||||
{
|
||||
// replace the X-Powered-By value
|
||||
response.getHeaders().put(HttpHeader.X_POWERED_BY, "SomeServer");
|
||||
Content.Sink.write(response, true, "Test", callback);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
server.start();
|
||||
|
||||
String request = """
|
||||
GET /test HTTP/1.0\r
|
||||
Host: hostname\r
|
||||
\r
|
||||
""";
|
||||
HttpTester.Response response = HttpTester.parseResponse(connector.getResponse(request));
|
||||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
|
||||
// ensure there are only 1 entry for each of these headers
|
||||
List<HttpHeader> expectedHeaders = List.of(HttpHeader.SERVER, HttpHeader.X_POWERED_BY, HttpHeader.DATE, HttpHeader.CONTENT_LENGTH);
|
||||
for (HttpHeader expectedHeader: expectedHeaders)
|
||||
{
|
||||
List<String> actualHeader = response.getValuesList(expectedHeader);
|
||||
assertThat(expectedHeader + " exists", actualHeader, is(notNullValue()));
|
||||
assertThat(expectedHeader + " header count", actualHeader.size(), is(1));
|
||||
}
|
||||
assertThat(response.get(HttpHeader.CONTENT_LENGTH), is("4"));
|
||||
assertThat(response.get(HttpHeader.X_POWERED_BY), is("SomeServer"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpCookieProcessing() throws Exception
|
||||
{
|
||||
|
|
|
@ -93,13 +93,11 @@ public class SSLEngineTest
|
|||
* The expected response.
|
||||
*/
|
||||
private static final String RESPONSE0 = "HTTP/1.1 200 OK\n" +
|
||||
"Server: Jetty(" + JETTY_VERSION + ")\n" +
|
||||
"Content-Length: " + HELLO_WORLD.length() + "\n" +
|
||||
'\n' +
|
||||
HELLO_WORLD;
|
||||
|
||||
private static final String RESPONSE1 = "HTTP/1.1 200 OK\n" +
|
||||
"Server: Jetty(" + JETTY_VERSION + ")\n" +
|
||||
"Content-Length: " + HELLO_WORLD.length() + "\n" +
|
||||
"Connection: close\n" +
|
||||
'\n' +
|
||||
|
@ -121,6 +119,7 @@ public class SSLEngineTest
|
|||
HttpConnectionFactory http = new HttpConnectionFactory();
|
||||
http.setInputBufferSize(512);
|
||||
http.getHttpConfiguration().setRequestHeaderSize(512);
|
||||
http.getHttpConfiguration().setSendServerVersion(false);
|
||||
connector = new ServerConnector(server, sslContextFactory, http);
|
||||
connector.setPort(0);
|
||||
connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration().setSendDateHeader(false);
|
||||
|
|
Loading…
Reference in New Issue