Fixes #312 (REQUEST_URI should retain original query string in case of rewrites)

Added init-param "originalQueryAttribute" to FastCGIProxyServlet to
retrieve the original query in case of rewrites.
This commit is contained in:
Simone Bordet 2016-03-16 12:55:59 +01:00
parent 1c5a1fc6a2
commit 3c0b654141
3 changed files with 86 additions and 16 deletions

View File

@ -58,14 +58,17 @@ public class HttpChannelOverFCGI extends HttpChannel
protected void header(HttpField field)
{
if (FCGI.Headers.REQUEST_METHOD.equalsIgnoreCase(field.getName()))
method = field.getValue();
else if (FCGI.Headers.DOCUMENT_URI.equalsIgnoreCase(field.getName()))
path = field.getValue();
else if (FCGI.Headers.QUERY_STRING.equalsIgnoreCase(field.getName()))
query = field.getValue();
else if (FCGI.Headers.SERVER_PROTOCOL.equalsIgnoreCase(field.getName()))
version = field.getValue();
String name = field.getName();
String value = field.getValue();
getRequest().setAttribute(name, value);
if (FCGI.Headers.REQUEST_METHOD.equalsIgnoreCase(name))
method = value;
else if (FCGI.Headers.DOCUMENT_URI.equalsIgnoreCase(name))
path = value;
else if (FCGI.Headers.QUERY_STRING.equalsIgnoreCase(name))
query = value;
else if (FCGI.Headers.SERVER_PROTOCOL.equalsIgnoreCase(name))
version = value;
else
processField(field);
}
@ -107,10 +110,11 @@ public class HttpChannelOverFCGI extends HttpChannel
httpName.append(part.substring(1).toLowerCase(Locale.ENGLISH));
}
String headerName = httpName.toString();
String value = field.getValue();
if (HttpHeader.HOST.is(headerName))
return new HostPortHttpField(field.getValue());
return new HostPortHttpField(value);
else
return new HttpField(httpName.toString(), field.getValue());
return new HttpField(headerName, value);
}
return null;
}

View File

@ -71,6 +71,7 @@ public class FastCGIProxyServlet extends AsyncProxyServlet.Transparent
public static final String SCRIPT_ROOT_INIT_PARAM = "scriptRoot";
public static final String SCRIPT_PATTERN_INIT_PARAM = "scriptPattern";
public static final String ORIGINAL_URI_ATTRIBUTE_INIT_PARAM = "originalURIAttribute";
public static final String ORIGINAL_QUERY_ATTRIBUTE_INIT_PARAM = "originalQueryAttribute";
public static final String FASTCGI_HTTPS_INIT_PARAM = "fastCGI.HTTPS";
private static final String REMOTE_ADDR_ATTRIBUTE = FastCGIProxyServlet.class.getName() + ".remoteAddr";
@ -80,9 +81,11 @@ public class FastCGIProxyServlet extends AsyncProxyServlet.Transparent
private static final String SERVER_PORT_ATTRIBUTE = FastCGIProxyServlet.class.getName() + ".serverPort";
private static final String SCHEME_ATTRIBUTE = FastCGIProxyServlet.class.getName() + ".scheme";
private static final String REQUEST_URI_ATTRIBUTE = FastCGIProxyServlet.class.getName() + ".requestURI";
private static final String REQUEST_QUERY_ATTRIBUTE = FastCGIProxyServlet.class.getName() + ".requestQuery";
private Pattern scriptPattern;
private String originalURIAttribute;
private String originalQueryAttribute;
private boolean fcgiHTTPS;
@Override
@ -96,6 +99,7 @@ public class FastCGIProxyServlet extends AsyncProxyServlet.Transparent
scriptPattern = Pattern.compile(value);
originalURIAttribute = getInitParameter(ORIGINAL_URI_ATTRIBUTE_INIT_PARAM);
originalQueryAttribute = getInitParameter(ORIGINAL_QUERY_ATTRIBUTE_INIT_PARAM);
fcgiHTTPS = Boolean.parseBoolean(getInitParameter(FASTCGI_HTTPS_INIT_PARAM));
}
@ -122,14 +126,21 @@ public class FastCGIProxyServlet extends AsyncProxyServlet.Transparent
// Has the original URI been rewritten ?
String originalURI = null;
String originalQuery = null;
if (originalURIAttribute != null)
originalURI = (String)request.getAttribute(originalURIAttribute);
if (originalURI != null && originalQueryAttribute != null)
{
originalQuery = (String)request.getAttribute(originalQueryAttribute);
if (originalQuery != null)
originalURI += "?" + originalQuery;
}
if (originalURI == null)
{
// If we are forwarded or included, retain the original request URI.
String originalPath = (String)request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
String originalQuery = (String)request.getAttribute(RequestDispatcher.FORWARD_QUERY_STRING);
originalQuery = (String)request.getAttribute(RequestDispatcher.FORWARD_QUERY_STRING);
if (originalPath == null)
{
originalPath = (String)request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI);
@ -145,6 +156,8 @@ public class FastCGIProxyServlet extends AsyncProxyServlet.Transparent
if (originalURI != null)
proxyRequest.attribute(REQUEST_URI_ATTRIBUTE, originalURI);
if (originalQuery != null)
proxyRequest.attribute(REQUEST_QUERY_ATTRIBUTE, originalQuery);
// If the Host header is missing, add it.
if (!proxyRequest.getHeaders().containsKey(HttpHeader.HOST.asString()))
@ -200,6 +213,10 @@ public class FastCGIProxyServlet extends AsyncProxyServlet.Transparent
}
fastCGIHeaders.put(FCGI.Headers.REQUEST_URI, requestURI);
String requestQuery = (String)proxyRequest.getAttributes().get(REQUEST_QUERY_ATTRIBUTE);
if (requestQuery != null)
fastCGIHeaders.put(FCGI.Headers.QUERY_STRING, requestQuery);
String scriptName = rawPath;
Matcher matcher = scriptPattern.matcher(rawPath);
if (matcher.matches())

View File

@ -31,13 +31,17 @@ import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.fcgi.FCGI;
import org.eclipse.jetty.fcgi.server.ServerFCGIConnectionFactory;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
@ -57,6 +61,7 @@ public class FastCGIProxyServletTest
private Server server;
private ServerConnector httpConnector;
private ServerConnector fcgiConnector;
private ServletContextHandler context;
private HttpClient client;
public FastCGIProxyServletTest(boolean sendStatus200)
@ -76,7 +81,7 @@ public class FastCGIProxyServletTest
server.addConnector(fcgiConnector);
final String contextPath = "/";
ServletContextHandler context = new ServletContextHandler(server, contextPath);
context = new ServletContextHandler(server, contextPath);
final String servletPath = "/script";
FastCGIProxyServlet fcgiServlet = new FastCGIProxyServlet()
@ -138,11 +143,11 @@ public class FastCGIProxyServletTest
prepare(new HttpServlet()
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Assert.assertTrue(req.getRequestURI().endsWith(path));
resp.setContentLength(data.length);
resp.getOutputStream().write(data);
Assert.assertTrue(request.getRequestURI().endsWith(path));
response.setContentLength(data.length);
response.getOutputStream().write(data);
}
});
@ -169,4 +174,48 @@ public class FastCGIProxyServletTest
Assert.assertEquals(200, response.getStatus());
Assert.assertArrayEquals(data, response.getContent());
}
@Test
public void testURIRewrite() throws Exception
{
String originalPath = "/original/index.php";
String originalQuery = "foo=bar";
String remotePath = "/remote/index.php";
prepare(new HttpServlet()
{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Assert.assertThat((String)request.getAttribute(FCGI.Headers.REQUEST_URI), Matchers.startsWith(originalPath));
Assert.assertEquals(originalQuery, request.getAttribute(FCGI.Headers.QUERY_STRING));
Assert.assertThat(request.getRequestURI(), Matchers.endsWith(remotePath));
}
});
context.stop();
String pathAttribute = "_path_attribute";
String queryAttribute = "_query_attribute";
ServletHolder fcgi = context.getServletHandler().getServlet("fcgi");
fcgi.setInitParameter(FastCGIProxyServlet.ORIGINAL_URI_ATTRIBUTE_INIT_PARAM, pathAttribute);
fcgi.setInitParameter(FastCGIProxyServlet.ORIGINAL_QUERY_ATTRIBUTE_INIT_PARAM, queryAttribute);
context.insertHandler(new HandlerWrapper()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (target.startsWith("/remote/"))
{
request.setAttribute(pathAttribute, originalPath);
request.setAttribute(queryAttribute, originalQuery);
}
super.handle(target, baseRequest, request, response);
}
});
context.start();
ContentResponse response = client.newRequest("localhost", httpConnector.getLocalPort())
.path(remotePath)
.send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
}