400734 - NPE for redirects with relative location.

Now resolving locations against original URL if it is relative.
This commit is contained in:
Simone Bordet 2013-02-13 21:53:27 +01:00
parent 12d9d77cd7
commit dd96cc50b2
2 changed files with 59 additions and 33 deletions

View File

@ -66,37 +66,48 @@ public class RedirectProtocolHandler extends Response.Listener.Empty implements
{
Request request = result.getRequest();
Response response = result.getResponse();
URI location = URI.create(response.getHeaders().get("location"));
int status = response.getStatus();
switch (status)
String location = response.getHeaders().get("location");
if (location != null)
{
case 301:
URI newURI = URI.create(location);
if (!newURI.isAbsolute())
newURI = request.getURI().resolve(newURI);
int status = response.getStatus();
switch (status)
{
if (request.getMethod() == HttpMethod.GET || request.getMethod() == HttpMethod.HEAD)
redirect(result, request.getMethod(), location);
else
fail(result, new HttpResponseException("HTTP protocol violation: received 301 for non GET or HEAD request", response));
break;
}
case 302:
case 303:
{
// Redirect must be done using GET
redirect(result, HttpMethod.GET, location);
break;
}
case 307:
{
// Keep same method
redirect(result, request.getMethod(), location);
break;
}
default:
{
fail(result, new HttpResponseException("Unhandled HTTP status code " + status, response));
break;
case 301:
{
if (request.getMethod() == HttpMethod.GET || request.getMethod() == HttpMethod.HEAD)
redirect(result, request.getMethod(), newURI);
else
fail(result, new HttpResponseException("HTTP protocol violation: received 301 for non GET or HEAD request", response));
break;
}
case 302:
case 303:
{
// Redirect must be done using GET
redirect(result, HttpMethod.GET, newURI);
break;
}
case 307:
{
// Keep same method
redirect(result, request.getMethod(), newURI);
break;
}
default:
{
fail(result, new HttpResponseException("Unhandled HTTP status code " + status, response));
break;
}
}
}
else
{
fail(result, new HttpResponseException("Missing Location header " + location, response));
}
}
else
{

View File

@ -18,13 +18,10 @@
package org.eclipse.jetty.client;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -42,6 +39,8 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.fail;
public class HttpClientRedirectTest extends AbstractHttpClientServerTest
{
public HttpClientRedirectTest(SslContextFactory sslContextFactory)
@ -199,6 +198,19 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
Assert.assertTrue(response.getHeaders().containsKey(HttpHeader.LOCATION.asString()));
}
@Test
public void testRelativeLocation() throws Exception
{
Response response = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.path("/303/localhost/done?relative=true")
.timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertNotNull(response);
Assert.assertEquals(200, response.getStatus());
Assert.assertFalse(response.getHeaders().containsKey(HttpHeader.LOCATION.asString()));
}
private class RedirectHandler extends AbstractHandler
{
@Override
@ -212,10 +224,13 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
response.setStatus(status);
String host = paths[2];
response.setHeader("Location", request.getScheme() + "://" + host + ":" + request.getServerPort() + "/" + paths[3]);
String path = paths[3];
boolean relative = Boolean.parseBoolean(request.getParameter("relative"));
String location = relative ? "" : request.getScheme() + "://" + host + ":" + request.getServerPort();
location += "/" + path;
response.setHeader("Location", location);
String close = request.getParameter("close");
if (Boolean.parseBoolean(close))
if (Boolean.parseBoolean(request.getParameter("close")))
response.setHeader("Connection", "close");
}
catch (NumberFormatException x)