Merge remote-tracking branch 'origin/jetty-9.3.x'

This commit is contained in:
Greg Wilkins 2016-04-28 08:17:45 +10:00
commit 092ed57a17
10 changed files with 536 additions and 13 deletions

View File

@ -0,0 +1,174 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.jstl;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URI;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.JAR;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class JspIncludeTest
{
private static Server server;
private static URI baseUri;
@BeforeClass
public static void startServer() throws Exception
{
// Setup Server
server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(0);
server.addConnector(connector);
// Setup WebAppContext
File testWebAppDir = MavenTestingUtils.getProjectDir("src/test/webapp");
// Prepare WebApp libs
File libDir = new File(testWebAppDir, "WEB-INF/lib");
FS.ensureDirExists(libDir);
File testTagLibDir = MavenTestingUtils.getProjectDir("src/test/taglibjar");
JAR.create(testTagLibDir, new File(libDir, "testtaglib.jar"));
// Configure WebAppContext
Configuration.ClassList classlist = Configuration.ClassList
.setServerDefault(server);
classlist.addBefore(
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration");
WebAppContext context = new WebAppContext();
context.setContextPath("/");
File scratchDir = MavenTestingUtils.getTargetFile("tests/" + JspIncludeTest.class.getSimpleName() + "-scratch");
FS.ensureEmpty(scratchDir);
JspConfig.init(context, testWebAppDir.toURI(), scratchDir);
server.setHandler(context);
// Start Server
server.start();
// Figure out Base URI
String host = connector.getHost();
if (host == null)
{
host = "localhost";
}
int port = connector.getLocalPort();
baseUri = new URI(String.format("http://%s:%d/", host, port));
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Test
public void testTopWithIncluded() throws IOException
{
URI uri = baseUri.resolve("/top.jsp");
// System.out.println("GET (String): " + uri.toASCIIString());
InputStream in = null;
InputStreamReader reader = null;
HttpURLConnection connection = null;
try
{
connection = (HttpURLConnection) uri.toURL().openConnection();
connection.connect();
if (HttpURLConnection.HTTP_OK != connection.getResponseCode())
{
String body = getPotentialBody(connection);
String err = String.format("GET request failed (%d %s) %s%n%s", connection.getResponseCode(), connection.getResponseMessage(),
uri.toASCIIString(), body);
throw new IOException(err);
}
in = connection.getInputStream();
reader = new InputStreamReader(in);
StringWriter writer = new StringWriter();
IO.copy(reader, writer);
String response = writer.toString();
// System.out.printf("Response%n%s",response);
assertThat("Response", response, containsString("<h2> Hello, this is the top page."));
assertThat("Response", response, containsString("<h3> This is the included page"));
assertThat("Response Header[main-page-key]", connection.getHeaderField("main-page-key"), is("main-page-value"));
assertThat("Response Header[included-page-key]", connection.getHeaderField("included-page-key"), is("included-page-value"));
}
finally
{
IO.close(reader);
IO.close(in);
}
}
/**
* Attempt to obtain the body text if available. Do not throw an exception if body is unable to be fetched.
*
* @param connection the connection to fetch the body content from.
* @return the body content, if present.
*/
private String getPotentialBody(HttpURLConnection connection)
{
InputStream in = null;
InputStreamReader reader = null;
try
{
in = connection.getInputStream();
reader = new InputStreamReader(in);
StringWriter writer = new StringWriter();
IO.copy(reader, writer);
return writer.toString();
}
catch (IOException e)
{
return "<no body:" + e.getMessage() + ">";
}
finally
{
IO.close(reader);
IO.close(in);
}
}
}

View File

@ -76,16 +76,6 @@ public class JstlTest
WebAppContext context = new WebAppContext();
context.setContextPath("/");
/* TODO: Bug #486530 - sub-handler on WebAppContext prevents startup
context.setHandler(new AbstractHandler()
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
}
});
*/
File scratchDir = MavenTestingUtils.getTargetFile("tests/" + JstlTest.class.getSimpleName() + "-scratch");
FS.ensureEmpty(scratchDir);
JspConfig.init(context,testWebAppDir.toURI(),scratchDir);

View File

@ -0,0 +1,8 @@
<%
String headerPrefix = "";
if(request.getDispatcherType() == DispatcherType.INCLUDE)
headerPrefix = "org.eclipse.jetty.server.include.";
response.setHeader(headerPrefix + "included-page-key","included-page-value");
%>
<h3> This is the included page

View File

@ -0,0 +1,5 @@
<%
application.getRequestDispatcher("/included.jsp").include(request,response);
response.setHeader("main-page-key", "main-page-value");
%>
<h2> Hello, this is the top page.

View File

@ -1426,7 +1426,7 @@ public class HttpParser
break;
default:
setState(State.CLOSE);
_handler.badMessage(400,null);
_handler.badMessage(400,"Bad Message "+e.toString());
}
}
catch(Exception|Error e)

View File

@ -594,9 +594,21 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
if (status < 400 || status > 599)
status = HttpStatus.BAD_REQUEST_400;
Action action;
try
{
if (_state.handling()==Action.DISPATCH)
action=_state.handling();
}
catch(IllegalStateException e)
{
// The bad message cannot be handled in the current state, so throw
// to hopefull somebody that can handle
throw new BadMessageException(status,reason);
}
try
{
if (action==Action.DISPATCH)
{
ByteBuffer content=null;
HttpFields fields=new HttpFields();

View File

@ -369,6 +369,9 @@ public class Server extends HandlerWrapper implements Attributes
ShutdownMonitor.getInstance().start(); // initialize
LOG.info("jetty-" + getVersion());
if (!Jetty.STABLE)
LOG.warn("THIS IS NOT A STABLE RELEASE! DO NOT USE IN PRODUCTION!");
HttpGenerator.setJettyVersion(HttpConfiguration.SERVER_VERSION);
MultiException mex=new MultiException();

View File

@ -0,0 +1,177 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.servlet;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URI;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.toolchain.test.IO;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class IncludedServletTest
{
public static class TopServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
req.getRequestDispatcher("/included").include(req, resp);
resp.setHeader("main-page-key", "main-page-value");
PrintWriter out = resp.getWriter();
out.println("<h2> Hello, this is the top page.");
}
}
public static class IncludedServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
String headerPrefix = "";
if (req.getDispatcherType() == DispatcherType.INCLUDE)
headerPrefix = "org.eclipse.jetty.server.include.";
resp.setHeader(headerPrefix + "included-page-key", "included-page-value");
resp.getWriter().println("<h3> This is the included page");
}
}
private Server server;
private URI baseUri;
@Before
public void startServer() throws Exception
{
this.server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setHost("localhost");
connector.setPort(0);
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
context.addServlet(TopServlet.class, "/top");
context.addServlet(IncludedServlet.class, "/included");
server.setHandler(context);
server.start();
int port = connector.getLocalPort();
String host = connector.getHost();
baseUri = URI.create("http://" + host + ":" + port + "/");
}
@After
public void stopServer() throws Exception
{
this.server.stop();
}
@Test
public void testTopWithIncludedHeader() throws IOException
{
URI uri = baseUri.resolve("/top");
System.out.println("GET (String): " + uri.toASCIIString());
InputStream in = null;
InputStreamReader reader = null;
HttpURLConnection connection = null;
try
{
connection = (HttpURLConnection) uri.toURL().openConnection();
connection.connect();
if (HttpURLConnection.HTTP_OK != connection.getResponseCode())
{
String body = getPotentialBody(connection);
String err = String.format("GET request failed (%d %s) %s%n%s", connection.getResponseCode(), connection.getResponseMessage(),
uri.toASCIIString(), body);
throw new IOException(err);
}
in = connection.getInputStream();
reader = new InputStreamReader(in);
StringWriter writer = new StringWriter();
IO.copy(reader, writer);
String response = writer.toString();
// System.out.printf("Response%n%s",response);
assertThat("Response", response, containsString("<h2> Hello, this is the top page."));
assertThat("Response", response, containsString("<h3> This is the included page"));
assertThat("Response Header[main-page-key]", connection.getHeaderField("main-page-key"), is("main-page-value"));
assertThat("Response Header[included-page-key]", connection.getHeaderField("included-page-key"), is("included-page-value"));
}
finally
{
IO.close(reader);
IO.close(in);
}
}
/**
* Attempt to obtain the body text if available. Do not throw an exception if body is unable to be fetched.
*
* @param connection the connection to fetch the body content from.
* @return the body content, if present.
*/
private String getPotentialBody(HttpURLConnection connection)
{
InputStream in = null;
InputStreamReader reader = null;
try
{
in = connection.getInputStream();
reader = new InputStreamReader(in);
StringWriter writer = new StringWriter();
IO.copy(reader, writer);
return writer.toString();
}
catch (IOException e)
{
return "<no body:" + e.getMessage() + ">";
}
finally
{
IO.close(reader);
IO.close(in);
}
}
}

View File

@ -0,0 +1,145 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.servlet;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StacklessLogging;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class PostServletTest
{
private static final Logger LOG = Log.getLogger(PostServletTest.class);
public static class BasicReadPostServlet extends HttpServlet
{
protected void doPost(HttpServletRequest request, HttpServletResponse response)
{
try
{
byte[] buffer = new byte[4096];
ServletInputStream in = request.getInputStream();
int l = in.read(buffer);
while (l>0)
{
// System.err.println("READ: "+new String(buffer,0,l,StandardCharsets.ISO_8859_1));
l = in.read(buffer);
}
}
catch (IOException e0)
{
LOG.warn(e0);
}
}
}
private Server server;
private LocalConnector connector;
@Before
public void startServer() throws Exception
{
server = new Server();
connector = new LocalConnector(server);
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
context.addServlet(BasicReadPostServlet.class, "/post");
server.setHandler(context);
server.start();
}
@After
public void stopServer() throws Exception
{
this.server.stop();
}
@Test
public void testGoodPost() throws Exception
{
StringBuilder req = new StringBuilder();
req.append("POST /post HTTP/1.1\r\n");
req.append("Host: localhost\r\n");
req.append("Connection: close\r\n");
req.append("Transfer-Encoding: chunked\r\n");
req.append("\r\n");
req.append("6\r\n");
req.append("Hello ");
req.append("\r\n");
req.append("6\r\n");
req.append("World\n");
req.append("\r\n");
req.append("0\r\n");
req.append("\r\n");
String resp = connector.getResponses(req.toString());
assertThat("resp", resp, containsString("HTTP/1.1 200 OK"));
}
@Test
public void testBadPost() throws Exception
{
StringBuilder req = new StringBuilder();
req.append("POST /post HTTP/1.1\r\n");
req.append("Host: localhost\r\n");
req.append("Connection: close\r\n");
req.append("Transfer-Encoding: chunked\r\n");
req.append("\r\n");
req.append("6\r\n");
req.append("Hello ");
req.append("\r\n");
req.append("x\r\n");
req.append("World\n");
req.append("\r\n");
req.append("0\r\n");
req.append("\r\n");
try (StacklessLogging scope = new StacklessLogging(ServletHandler.class))
{
String resp = connector.getResponses(req.toString());
assertThat("resp", resp, containsString("HTTP/1.1 500 "));
}
}
}

View File

@ -22,6 +22,7 @@ public class Jetty
{
public static final String VERSION;
public static final String POWERED_BY;
public static final boolean STABLE;
static
{
@ -31,9 +32,17 @@ public class Jetty
pkg.getImplementationVersion() != null)
VERSION = pkg.getImplementationVersion();
else
VERSION = System.getProperty("jetty.version", "9.3.z-SNAPSHOT");
VERSION = System.getProperty("jetty.version", "9.4.z-SNAPSHOT");
POWERED_BY="<a href=\"http://eclipse.org/jetty\">Powered by Jetty:// "+VERSION+"</a>";
boolean stable=true;
for (char c: VERSION.toCharArray())
{
if (c!='.' && !Character.isDigit(c))
stable=false;
}
STABLE=stable;
}
private Jetty()