// ========================================================================
// Copyright (c) 2004-2009 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.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.GenericServlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import junit.framework.Assert;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class DispatcherTest
{
private Server _server;
private LocalConnector _connector;
private ContextHandlerCollection _contextCollection;
private ServletContextHandler _contextHandler;
private ResourceHandler _resourceHandler;
@Before
public void init() throws Exception
{
_server = new Server();
_server.setSendServerVersion(false);
_connector = new LocalConnector();
_contextCollection = new ContextHandlerCollection();
_contextHandler = new ServletContextHandler();
_contextHandler.setContextPath("/context");
_contextCollection.addHandler(_contextHandler);
_resourceHandler = new ResourceHandler();
_resourceHandler.setResourceBase(MavenTestingUtils.getTestResourceDir("dispatchResourceTest").getAbsolutePath());
ContextHandler resourceContextHandler = new ContextHandler("/resource");
resourceContextHandler.setHandler(_resourceHandler);
_contextCollection.addHandler(resourceContextHandler);
_server.setHandler(_contextCollection);
_server.addConnector( _connector );
_server.start();
}
@After
public void destroy() throws Exception
{
_server.stop();
_server.join();
}
@Test
public void testForward() throws Exception
{
_contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*");
_contextHandler.addServlet(AssertForwardServlet.class, "/AssertForwardServlet/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
"Content-Type: text/html\r\n"+
"Content-Length: 0\r\n"+
"\r\n";
String responses = _connector.getResponses("GET /context/ForwardServlet?do=assertforward&do=more&test=1 HTTP/1.1\n" + "Host: localhost\n\n");
assertEquals(expected, responses);
}
@Test
public void testInclude() throws Exception
{
_contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*");
_contextHandler.addServlet(AssertIncludeServlet.class, "/AssertIncludeServlet/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
"Content-Length: 0\r\n"+
"\r\n";
String responses = _connector.getResponses("GET /context/IncludeServlet?do=assertinclude&do=more&test=1 HTTP/1.1\n" + "Host: localhost\n\n");
assertEquals(expected, responses);
}
@Test
public void testForwardThenInclude() throws Exception
{
_contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*");
_contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*");
_contextHandler.addServlet(AssertForwardIncludeServlet.class, "/AssertForwardIncludeServlet/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
"Content-Length: 0\r\n"+
"\r\n";
String responses = _connector.getResponses("GET /context/ForwardServlet/forwardpath?do=include HTTP/1.1\n" + "Host: localhost\n\n");
assertEquals(expected, responses);
}
@Test
public void testIncludeThenForward() throws Exception
{
_contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*");
_contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*");
_contextHandler.addServlet(AssertIncludeForwardServlet.class, "/AssertIncludeForwardServlet/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
"Transfer-Encoding: chunked\r\n"+
"\r\n"+
"0\r\n"+
"\r\n";
String responses = _connector.getResponses("GET /context/IncludeServlet/includepath?do=forward HTTP/1.1\n" + "Host: localhost\n\n");
assertEquals(expected, responses);
}
@Test
public void testServletForward() throws Exception
{
_contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*");
_contextHandler.addServlet(RogerThatServlet.class, "/roger/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
"Content-Length: 11\r\n"+
"\r\n"+
"Roger That!";
String responses = _connector.getResponses("GET /context/dispatch/test?forward=/roger/that HTTP/1.0\n" + "Host: localhost\n\n");
assertEquals(expected, responses);
}
@Test
public void testServletInclude() throws Exception
{
_contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*");
_contextHandler.addServlet(RogerThatServlet.class, "/roger/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
"Content-Length: 11\r\n"+
"\r\n"+
"Roger That!";
String responses = _connector.getResponses("GET /context/dispatch/test?include=/roger/that HTTP/1.0\n" + "Host: localhost\n\n");
assertEquals(expected, responses);
}
@Test
public void testWorkingResourceHandler() throws Exception
{
String responses = _connector.getResponses("GET /resource/content.txt HTTP/1.0\n" + "Host: localhost\n\n");
assertTrue(responses.contains("content goes here")); // from inside the context.txt file
}
@Test
public void testIncludeToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
String responses = _connector.getResponses("GET /context/resourceServlet/content.txt?do=include HTTP/1.0\n" + "Host: localhost\n\n");
// from inside the context.txt file
Assert.assertNotNull(responses);
assertTrue(responses.contains("content goes here"));
}
@Test
public void testForwardToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
String responses = _connector.getResponses("GET /context/resourceServlet/content.txt?do=forward HTTP/1.0\n" + "Host: localhost\n\n");
// from inside the context.txt file
assertTrue(responses.contains("content goes here"));
}
@Test
public void testWrappedIncludeToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
String responses = _connector.getResponses("GET /context/resourceServlet/content.txt?do=include&wrapped=true HTTP/1.0\n" + "Host: localhost\n\n");
// from inside the context.txt file
assertTrue(responses.contains("content goes here"));
}
@Test
public void testWrappedForwardToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
String responses = _connector.getResponses("GET /context/resourceServlet/content.txt?do=forward&wrapped=true HTTP/1.0\n" + "Host: localhost\n\n");
// from inside the context.txt file
assertTrue(responses.contains("content goes here"));
}
@Test
public void testForwardFilterToRogerServlet() throws Exception
{
_contextHandler.addServlet(RogerThatServlet.class, "/*");
_contextHandler.addServlet(ReserveEchoServlet.class,"/recho/*");
_contextHandler.addServlet(EchoServlet.class, "/echo/*");
_contextHandler.addFilter(ForwardFilter.class, "/*", FilterMapping.REQUEST);
String rogerResponse = _connector.getResponses("GET /context/ HTTP/1.0\n" + "Host: localhost\n\n");
String echoResponse = _connector.getResponses("GET /context/foo?echo=echoText HTTP/1.0\n" + "Host: localhost\n\n");
String rechoResponse = _connector.getResponses("GET /context/?echo=echoText HTTP/1.0\n" + "Host: localhost\n\n");
assertTrue(rogerResponse.contains("Roger That!"));
assertTrue(echoResponse.contains("echoText"));
assertTrue(rechoResponse.contains("txeTohce"));
}
public static class ForwardServlet extends HttpServlet implements Servlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
RequestDispatcher dispatcher = null;
if(request.getParameter("do").equals("include"))
dispatcher = getServletContext().getRequestDispatcher("/IncludeServlet/includepath?do=assertforwardinclude");
else if(request.getParameter("do").equals("assertincludeforward"))
dispatcher = getServletContext().getRequestDispatcher("/AssertIncludeForwardServlet/assertpath?do=end");
else if(request.getParameter("do").equals("assertforward"))
dispatcher = getServletContext().getRequestDispatcher("/AssertForwardServlet?do=end&do=the");
dispatcher.forward(request, response);
}
}
/*
* Forward filter works with roger, echo and reverse echo servlets to test various
* forwarding bits using filters.
*
* when there is an echo parameter and the path info is / it forwards to the reverse echo
* anything else in the pathInfo and it sends straight to the echo servlet...otherwise its
* all roger servlet
*/
public static class ForwardFilter implements Filter
{
ServletContext servletContext;
public void init(FilterConfig filterConfig) throws ServletException
{
servletContext = filterConfig.getServletContext().getContext("/context");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
if ( servletContext == null || !(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse))
{
chain.doFilter(request,response);
return;
}
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
if ( req.getParameter("echo") != null && "/".equals(req.getPathInfo()))
{
RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/recho");
dispatcher.forward(request,response);
}
else if ( req.getParameter("echo") != null )
{
RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/echo");
dispatcher.forward(request,response);
}
else
{
chain.doFilter(request,response);
return;
}
}
public void destroy()
{
}
}
public static class DispatchServletServlet extends HttpServlet implements Servlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
RequestDispatcher dispatcher = null;
if(request.getParameter("include")!=null)
{
dispatcher = getServletContext().getRequestDispatcher(request.getParameter("include"));
dispatcher.include(new ServletRequestWrapper(request), new ServletResponseWrapper(response));
}
else if(request.getParameter("forward")!=null)
{
dispatcher = getServletContext().getRequestDispatcher(request.getParameter("forward"));
dispatcher.forward(new ServletRequestWrapper(request), new ServletResponseWrapper(response));
}
}
}
public static class IncludeServlet extends HttpServlet implements Servlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
RequestDispatcher dispatcher = null;
if(request.getParameter("do").equals("forward"))
dispatcher = getServletContext().getRequestDispatcher("/ForwardServlet/forwardpath?do=assertincludeforward");
else if(request.getParameter("do").equals("assertforwardinclude"))
dispatcher = getServletContext().getRequestDispatcher("/AssertForwardIncludeServlet/assertpath?do=end");
else if(request.getParameter("do").equals("assertinclude"))
dispatcher = getServletContext().getRequestDispatcher("/AssertIncludeServlet?do=end&do=the");
dispatcher.include(request, response);
}
}
public static class RogerThatServlet extends GenericServlet
{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
res.getWriter().print("Roger That!");
}
}
public static class EchoServlet extends GenericServlet
{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
String echoText = req.getParameter("echo");
if ( echoText == null )
{
throw new ServletException("echo is a required parameter");
}
else
{
res.getWriter().print(echoText);
}
}
}
public static class ReserveEchoServlet extends GenericServlet
{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
String echoText = req.getParameter("echo");
if ( echoText == null )
{
throw new ServletException("echo is a required parameter");
}
else
{
res.getWriter().print(new StringBuffer(echoText).reverse().toString());
}
}
}
public static class DispatchToResourceServlet extends HttpServlet implements Servlet
{
@Override
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
ServletContext targetContext = getServletConfig().getServletContext().getContext("/resource");
RequestDispatcher dispatcher = targetContext.getRequestDispatcher(req.getPathInfo());
if ( "true".equals(req.getParameter("wrapped")))
{
if (req.getParameter("do").equals("forward"))
{
dispatcher.forward(new HttpServletRequestWrapper(req),new HttpServletResponseWrapper(res));
}
else if (req.getParameter("do").equals("include"))
{
dispatcher.include(new HttpServletRequestWrapper(req),new HttpServletResponseWrapper(res));
}
else
{
throw new ServletException("type of forward or include is required");
}
}
else
{
if (req.getParameter("do").equals("forward"))
{
dispatcher.forward(req,res);
}
else if (req.getParameter("do").equals("include"))
{
dispatcher.include(req,res);
}
else
{
throw new ServletException("type of forward or include is required");
}
}
}
}
public static class AssertForwardServlet extends HttpServlet implements Servlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
assertEquals( "/context/ForwardServlet", request.getAttribute(Dispatcher.FORWARD_REQUEST_URI));
assertEquals( "/context", request.getAttribute(Dispatcher.FORWARD_CONTEXT_PATH) );
assertEquals( "/ForwardServlet", request.getAttribute(Dispatcher.FORWARD_SERVLET_PATH));
assertEquals( null, request.getAttribute(Dispatcher.FORWARD_PATH_INFO));
assertEquals( "do=assertforward&do=more&test=1", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING) );
List<String> expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH,
Dispatcher.FORWARD_SERVLET_PATH, Dispatcher.FORWARD_QUERY_STRING);
List<String> requestAttributeNames = Collections.list(request.getAttributeNames());
assertTrue(requestAttributeNames.containsAll(expectedAttributeNames));
assertEquals(null, request.getPathInfo());
assertEquals(null, request.getPathTranslated());
assertEquals("do=end&do=the&test=1", request.getQueryString());
assertEquals("/context/AssertForwardServlet", request.getRequestURI());
assertEquals("/context", request.getContextPath());
assertEquals("/AssertForwardServlet", request.getServletPath());
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
}
}
public static class AssertIncludeServlet extends HttpServlet implements Servlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
assertEquals( "/context/AssertIncludeServlet", request.getAttribute(Dispatcher.INCLUDE_REQUEST_URI));
assertEquals( "/context", request.getAttribute(Dispatcher.INCLUDE_CONTEXT_PATH) );
assertEquals( "/AssertIncludeServlet", request.getAttribute(Dispatcher.INCLUDE_SERVLET_PATH));
assertEquals( null, request.getAttribute(Dispatcher.INCLUDE_PATH_INFO));
assertEquals( "do=end&do=the", request.getAttribute(Dispatcher.INCLUDE_QUERY_STRING));
List expectedAttributeNames = Arrays.asList(Dispatcher.INCLUDE_REQUEST_URI, Dispatcher.INCLUDE_CONTEXT_PATH,
Dispatcher.INCLUDE_SERVLET_PATH, Dispatcher.INCLUDE_QUERY_STRING);
List requestAttributeNames = Collections.list(request.getAttributeNames());
assertTrue(requestAttributeNames.containsAll(expectedAttributeNames));
assertEquals(null, request.getPathInfo());
assertEquals(null, request.getPathTranslated());
assertEquals("do=assertinclude&do=more&test=1", request.getQueryString());
assertEquals("/context/IncludeServlet", request.getRequestURI());
assertEquals("/context", request.getContextPath());
assertEquals("/IncludeServlet", request.getServletPath());
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
}
}
public static class AssertForwardIncludeServlet extends HttpServlet implements Servlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// include doesn't hide forward
assertEquals( "/context/ForwardServlet/forwardpath", request.getAttribute(Dispatcher.FORWARD_REQUEST_URI));
assertEquals( "/context", request.getAttribute(Dispatcher.FORWARD_CONTEXT_PATH) );
assertEquals( "/ForwardServlet", request.getAttribute(Dispatcher.FORWARD_SERVLET_PATH));
assertEquals( "/forwardpath", request.getAttribute(Dispatcher.FORWARD_PATH_INFO));
assertEquals( "do=include", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING) );
assertEquals( "/context/AssertForwardIncludeServlet/assertpath", request.getAttribute(Dispatcher.INCLUDE_REQUEST_URI));
assertEquals( "/context", request.getAttribute(Dispatcher.INCLUDE_CONTEXT_PATH) );
assertEquals( "/AssertForwardIncludeServlet", request.getAttribute(Dispatcher.INCLUDE_SERVLET_PATH));
assertEquals( "/assertpath", request.getAttribute(Dispatcher.INCLUDE_PATH_INFO));
assertEquals( "do=end", request.getAttribute(Dispatcher.INCLUDE_QUERY_STRING));
List expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH, Dispatcher.FORWARD_SERVLET_PATH,
Dispatcher.FORWARD_PATH_INFO, Dispatcher.FORWARD_QUERY_STRING,
Dispatcher.INCLUDE_REQUEST_URI, Dispatcher.INCLUDE_CONTEXT_PATH, Dispatcher.INCLUDE_SERVLET_PATH,
Dispatcher.INCLUDE_PATH_INFO, Dispatcher.INCLUDE_QUERY_STRING);
List requestAttributeNames = Collections.list(request.getAttributeNames());
assertTrue(requestAttributeNames.containsAll(expectedAttributeNames));
assertEquals("/includepath", request.getPathInfo());
assertEquals(null, request.getPathTranslated());
assertEquals("do=assertforwardinclude", request.getQueryString());
assertEquals("/context/IncludeServlet/includepath", request.getRequestURI());
assertEquals("/context", request.getContextPath());
assertEquals("/IncludeServlet", request.getServletPath());
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
}
}
public static class AssertIncludeForwardServlet extends HttpServlet implements Servlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// forward hides include
assertEquals( null, request.getAttribute(Dispatcher.INCLUDE_REQUEST_URI));
assertEquals( null, request.getAttribute(Dispatcher.INCLUDE_CONTEXT_PATH) );
assertEquals( null, request.getAttribute(Dispatcher.INCLUDE_SERVLET_PATH));
assertEquals( null, request.getAttribute(Dispatcher.INCLUDE_PATH_INFO));
assertEquals( null, request.getAttribute(Dispatcher.INCLUDE_QUERY_STRING));
assertEquals( "/context/IncludeServlet/includepath", request.getAttribute(Dispatcher.FORWARD_REQUEST_URI));
assertEquals( "/context", request.getAttribute(Dispatcher.FORWARD_CONTEXT_PATH) );
assertEquals( "/IncludeServlet", request.getAttribute(Dispatcher.FORWARD_SERVLET_PATH));
assertEquals( "/includepath", request.getAttribute(Dispatcher.FORWARD_PATH_INFO));
assertEquals( "do=forward", request.getAttribute(Dispatcher.FORWARD_QUERY_STRING) );
List expectedAttributeNames = Arrays.asList(Dispatcher.FORWARD_REQUEST_URI, Dispatcher.FORWARD_CONTEXT_PATH, Dispatcher.FORWARD_SERVLET_PATH,
Dispatcher.FORWARD_PATH_INFO, Dispatcher.FORWARD_QUERY_STRING);
List requestAttributeNames = Collections.list(request.getAttributeNames());
assertTrue(requestAttributeNames.containsAll(expectedAttributeNames));
assertEquals("/assertpath", request.getPathInfo());
assertEquals(null, request.getPathTranslated());
assertEquals("do=end", request.getQueryString());
assertEquals("/context/AssertIncludeForwardServlet/assertpath", request.getRequestURI());
assertEquals("/context", request.getContextPath());
assertEquals("/AssertIncludeForwardServlet", request.getServletPath());
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
}
}
}