405424 X-Powered-By header

This commit is contained in:
Greg Wilkins 2013-06-24 17:09:44 +10:00
parent ebe98022ab
commit 4d0a796f72
5 changed files with 108 additions and 30 deletions

View File

@ -55,13 +55,18 @@ public class HttpGenerator
private long _contentPrepared = 0;
private boolean _noContent = false;
private Boolean _persistent = null;
private boolean _sendServerVersion;
private final int _send;
private final static int SEND_SERVER=0x01;
private final static int SEND_XPOWEREDBY=0x02;
/* ------------------------------------------------------------------------------- */
public static void setServerVersion(String version)
{
SERVER=StringUtil.getBytes("Server: Jetty("+version+")\015\012");
SEND[SEND_SERVER]=StringUtil.getBytes("Server: Jetty("+version+")\015\012");
SEND[SEND_XPOWEREDBY]=StringUtil.getBytes("X-Powered-By: Jetty("+version+")\015\012");
SEND[SEND_SERVER|SEND_XPOWEREDBY]=StringUtil.getBytes("Server: Jetty("+version+")\015\012X-Powered-By: Jetty("+version+")\015\012");
}
/* ------------------------------------------------------------------------------- */
@ -71,6 +76,13 @@ public class HttpGenerator
/* ------------------------------------------------------------------------------- */
public HttpGenerator()
{
this(false,false);
}
/* ------------------------------------------------------------------------------- */
public HttpGenerator(boolean sendServerVersion,boolean sendXPoweredBy)
{
_send=(sendServerVersion?SEND_SERVER:0) | (sendXPoweredBy?SEND_XPOWEREDBY:0);
}
/* ------------------------------------------------------------------------------- */
@ -86,15 +98,17 @@ public class HttpGenerator
}
/* ------------------------------------------------------------ */
@Deprecated
public boolean getSendServerVersion ()
{
return _sendServerVersion;
return (_send&SEND_SERVER)!=0;
}
/* ------------------------------------------------------------ */
@Deprecated
public void setSendServerVersion (boolean sendServerVersion)
{
_sendServerVersion = sendServerVersion;
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
@ -537,11 +551,11 @@ public class HttpGenerator
/* ------------------------------------------------------------ */
private void generateHeaders(Info _info,ByteBuffer header,ByteBuffer content,boolean last)
{
final RequestInfo _request=(_info instanceof RequestInfo)?(RequestInfo)_info:null;
final ResponseInfo _response=(_info instanceof ResponseInfo)?(ResponseInfo)_info:null;
final RequestInfo request=(_info instanceof RequestInfo)?(RequestInfo)_info:null;
final ResponseInfo response=(_info instanceof ResponseInfo)?(ResponseInfo)_info:null;
// default field values
boolean has_server = false;
int send=_send;
HttpField transfer_encoding=null;
boolean keep_alive=false;
boolean close=false;
@ -584,7 +598,7 @@ public class HttpGenerator
case CONNECTION:
{
if (_request!=null)
if (request!=null)
field.putTo(header);
// Lookup and/or split connection value field
@ -619,7 +633,7 @@ public class HttpGenerator
case CLOSE:
{
close=true;
if (_response!=null)
if (response!=null)
{
_persistent=false;
if (_endOfContent == EndOfContent.UNKNOWN_CONTENT)
@ -633,7 +647,7 @@ public class HttpGenerator
if (_info.getHttpVersion() == HttpVersion.HTTP_1_0)
{
keep_alive = true;
if (_response!=null)
if (response!=null)
_persistent=true;
}
break;
@ -656,11 +670,8 @@ public class HttpGenerator
case SERVER:
{
if (getSendServerVersion())
{
has_server=true;
field.putTo(header);
}
send=send&~SEND_SERVER;
field.putTo(header);
break;
}
@ -680,7 +691,7 @@ public class HttpGenerator
// 4. Content-Length
// 5. multipart/byteranges
// 6. close
int status=_response!=null?_response.getStatus():-1;
int status=response!=null?response.getStatus():-1;
switch (_endOfContent)
{
case UNKNOWN_CONTENT:
@ -688,14 +699,14 @@ public class HttpGenerator
// written yet?
// Response known not to have a body
if (_contentPrepared == 0 && _response!=null && (status < 200 || status == 204 || status == 304))
if (_contentPrepared == 0 && response!=null && (status < 200 || status == 204 || status == 304))
_endOfContent=EndOfContent.NO_CONTENT;
else if (_info.getContentLength()>0)
{
// we have been given a content length
_endOfContent=EndOfContent.CONTENT_LENGTH;
long content_length = _info.getContentLength();
if ((_response!=null || content_length>0 || content_type ) && !_noContent)
if ((response!=null || content_length>0 || content_type ) && !_noContent)
{
// known length but not actually set.
header.put(HttpHeader.CONTENT_LENGTH.getBytesColonSpace());
@ -710,7 +721,7 @@ public class HttpGenerator
long content_length = _contentPrepared+BufferUtil.length(content);
// Do we need to tell the headers about it
if ((_response!=null || content_length>0 || content_type ) && !_noContent)
if ((response!=null || content_length>0 || content_type ) && !_noContent)
{
header.put(HttpHeader.CONTENT_LENGTH.getBytesColonSpace());
BufferUtil.putDecLong(header, content_length);
@ -721,7 +732,7 @@ public class HttpGenerator
{
// No idea, so we must assume that a body is coming
_endOfContent = (!isPersistent() || _info.getHttpVersion().ordinal() < HttpVersion.HTTP_1_1.ordinal() ) ? EndOfContent.EOF_CONTENT : EndOfContent.CHUNKED_CONTENT;
if (_response!=null && _endOfContent==EndOfContent.EOF_CONTENT)
if (response!=null && _endOfContent==EndOfContent.EOF_CONTENT)
{
_endOfContent=EndOfContent.NO_CONTENT;
_noContent=true;
@ -731,7 +742,7 @@ public class HttpGenerator
case CONTENT_LENGTH:
long content_length = _info.getContentLength();
if ((_response!=null || content_length>0 || content_type ) && !_noContent)
if ((response!=null || content_length>0 || content_type ) && !_noContent)
{
// known length but not actually set.
header.put(HttpHeader.CONTENT_LENGTH.getBytesColonSpace());
@ -741,12 +752,12 @@ public class HttpGenerator
break;
case NO_CONTENT:
if (_response!=null && status >= 200 && status != 204 && status != 304)
if (response!=null && status >= 200 && status != 204 && status != 304)
header.put(CONTENT_LENGTH_0);
break;
case EOF_CONTENT:
_persistent = _request!=null;
_persistent = request!=null;
break;
case CHUNKED_CONTENT:
@ -780,7 +791,7 @@ public class HttpGenerator
}
// If this is a response, work out persistence
if (_response!=null)
if (response!=null)
{
if (!isPersistent() && (close || _info.getHttpVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal()))
{
@ -814,8 +825,8 @@ public class HttpGenerator
}
}
if (!has_server && status>199 && getSendServerVersion())
header.put(SERVER);
if (status>199)
header.put(SEND[send]);
// end the header.
header.put(HttpTokens.CRLF);
@ -851,7 +862,12 @@ public class HttpGenerator
private static final byte[] HTTP_1_1_SPACE = StringUtil.getBytes(HttpVersion.HTTP_1_1+" ");
private static final byte[] CRLF = StringUtil.getBytes("\015\012");
private static final byte[] TRANSFER_ENCODING_CHUNKED = StringUtil.getBytes("Transfer-Encoding: chunked\015\012");
private static byte[] SERVER = StringUtil.getBytes("Server: Jetty(7.0.x)\015\012");
private static final byte[][] SEND = new byte[][]{
new byte[0],
StringUtil.getBytes("Server: Jetty(9.x.x)\015\012"),
StringUtil.getBytes("X-Powered-By: Jetty(9.x.x)\015\012"),
StringUtil.getBytes("Server: Jetty(9.x.x)\015\012X-Powered-By: Jetty(9.x.x)\015\012")
};
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */

View File

@ -108,6 +108,8 @@ public enum HttpHeader
SET_COOKIE2("Set-Cookie2"),
MIME_VERSION("MIME-Version"),
IDENTITY("identity"),
X_POWERED_BY("X-Powered-By"),
UNKNOWN("::UNKNOWN::");

View File

@ -34,6 +34,7 @@ import java.util.List;
import org.eclipse.jetty.http.HttpGenerator.ResponseInfo;
import org.eclipse.jetty.util.BufferUtil;
import org.hamcrest.Matchers;
import org.junit.Test;
public class HttpGeneratorServerTest
@ -309,6 +310,54 @@ public class HttpGeneratorServerTest
}
}
}
@Test
public void testSendServerXPoweredBy() throws Exception
{
ByteBuffer header = BufferUtil.allocate(8096);
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), -1, 200, null, false);
HttpFields fields = new HttpFields();
fields.add(HttpHeader.SERVER,"SomeServer");
fields.add(HttpHeader.X_POWERED_BY,"SomePower");
ResponseInfo infoF = new ResponseInfo(HttpVersion.HTTP_1_1, fields, -1, 200, null, false);
String head;
HttpGenerator gen = new HttpGenerator(true,true);
gen.generateResponse(info, header, null, null, true);
head = BufferUtil.toString(header);
BufferUtil.clear(header);
assertThat(head, containsString("HTTP/1.1 200 OK"));
assertThat(head, containsString("Server: Jetty(9.x.x)"));
assertThat(head, containsString("X-Powered-By: Jetty(9.x.x)"));
gen.reset();
gen.generateResponse(infoF, 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(9.x.x)")));
assertThat(head, containsString("Server: SomeServer"));
assertThat(head, containsString("X-Powered-By: Jetty(9.x.x)"));
assertThat(head, containsString("X-Powered-By: SomePower"));
gen.reset();
gen = new HttpGenerator(false,false);
gen.generateResponse(info, 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(9.x.x)")));
assertThat(head, not(containsString("X-Powered-By: Jetty(9.x.x)")));
gen.reset();
gen.generateResponse(infoF, 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(9.x.x)")));
assertThat(head, containsString("Server: SomeServer"));
assertThat(head, not(containsString("X-Powered-By: Jetty(9.x.x)")));
assertThat(head, containsString("X-Powered-By: SomePower"));
gen.reset();
}
@Test
public void testResponseNoContent() throws Exception

View File

@ -48,6 +48,7 @@ public class HttpConfiguration
private int _securePort;
private String _secureScheme = HttpScheme.HTTPS.asString();
private boolean _sendServerVersion = true; //send Server: header
private boolean _sendXPoweredBy = false; //send X-Powered-By: header
private boolean _sendDateHeader = false; //send Date: header
@ -150,11 +151,22 @@ public class HttpConfiguration
_sendServerVersion = sendServerVersion;
}
@ManagedAttribute("if true, include the server version in HTTP headers")
@ManagedAttribute("if true, send the Server header in responses")
public boolean getSendServerVersion()
{
return _sendServerVersion;
}
public void setSendXPoweredBy (boolean sendXPoweredBy)
{
_sendXPoweredBy=sendXPoweredBy;
}
@ManagedAttribute("if true, send the X-Powered-By header in responses")
public boolean getSendXPoweredBy()
{
return _sendXPoweredBy;
}
public void setSendDateHeader(boolean sendDateHeader)
{

View File

@ -91,8 +91,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
_config = config;
_connector = connector;
_bufferPool = _connector.getByteBufferPool();
_generator = new HttpGenerator();
_generator.setSendServerVersion(_config.getSendServerVersion());
_generator = new HttpGenerator(_config.getSendServerVersion(),_config.getSendXPoweredBy());
_channel = new HttpChannelOverHttp(connector, config, endPoint, this, new Input());
_parser = newHttpParser();