416314 - jetty async client wrong behaviour for HEAD Method + Redirect.

Fixed redirect behavior based on
http://greenbytes.de/tech/tc/httpredirects/.
This commit is contained in:
Simone Bordet 2013-09-03 10:34:30 +02:00
parent eec9d405e5
commit 78c322af8e
2 changed files with 138 additions and 5 deletions

View File

@ -96,16 +96,29 @@ public class RedirectProtocolHandler extends Response.Listener.Empty implements
case 301:
{
String method = request.method();
if (HttpMethod.GET.is(method) || HttpMethod.HEAD.is(method))
if (HttpMethod.GET.is(method) || HttpMethod.HEAD.is(method) || HttpMethod.PUT.is(method))
redirect(result, method, newURI);
else if (HttpMethod.POST.is(method))
redirect(result, HttpMethod.GET.asString(), newURI);
else
fail(result, new HttpResponseException("HTTP protocol violation: received 301 for non GET or HEAD request", response));
fail(result, new HttpResponseException("HTTP protocol violation: received 301 for non GET/HEAD/POST/PUT request", response));
break;
}
case 302:
{
String method = request.method();
if (HttpMethod.HEAD.is(method) || HttpMethod.PUT.is(method))
redirect(result, method, newURI);
else
redirect(result, HttpMethod.GET.asString(), newURI);
break;
}
case 303:
{
// Redirect must be done using GET
String method = request.method();
if (HttpMethod.HEAD.is(method))
redirect(result, method, newURI);
else
redirect(result, HttpMethod.GET.asString(), newURI);
break;
}

View File

@ -24,6 +24,7 @@ import java.nio.ByteBuffer;
import java.nio.channels.UnresolvedAddressException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -33,6 +34,7 @@ import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.util.ByteBufferContentProvider;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.IO;
@ -117,7 +119,7 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
{
client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.method(HttpMethod.POST)
.method(HttpMethod.DELETE)
.path("/301/localhost/done")
.timeout(5, TimeUnit.SECONDS)
.send();
@ -257,6 +259,124 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
}
}
@Test
public void test_HEAD_301() throws Exception
{
testSameMethodRedirect(HttpMethod.HEAD, HttpStatus.MOVED_PERMANENTLY_301);
}
@Test
public void test_POST_301() throws Exception
{
testGETRedirect(HttpMethod.POST, HttpStatus.MOVED_PERMANENTLY_301);
}
@Test
public void test_PUT_301() throws Exception
{
testSameMethodRedirect(HttpMethod.PUT, HttpStatus.MOVED_PERMANENTLY_301);
}
@Test
public void test_HEAD_302() throws Exception
{
testSameMethodRedirect(HttpMethod.HEAD, HttpStatus.FOUND_302);
}
@Test
public void test_POST_302() throws Exception
{
testGETRedirect(HttpMethod.POST, HttpStatus.FOUND_302);
}
@Test
public void test_PUT_302() throws Exception
{
testSameMethodRedirect(HttpMethod.PUT, HttpStatus.FOUND_302);
}
@Test
public void test_HEAD_303() throws Exception
{
testSameMethodRedirect(HttpMethod.HEAD, HttpStatus.SEE_OTHER_303);
}
@Test
public void test_POST_303() throws Exception
{
testGETRedirect(HttpMethod.POST, HttpStatus.SEE_OTHER_303);
}
@Test
public void test_PUT_303() throws Exception
{
testGETRedirect(HttpMethod.PUT, HttpStatus.SEE_OTHER_303);
}
@Test
public void test_HEAD_307() throws Exception
{
testSameMethodRedirect(HttpMethod.HEAD, HttpStatus.TEMPORARY_REDIRECT_307);
}
@Test
public void test_POST_307() throws Exception
{
testSameMethodRedirect(HttpMethod.POST, HttpStatus.TEMPORARY_REDIRECT_307);
}
@Test
public void test_PUT_307() throws Exception
{
testSameMethodRedirect(HttpMethod.PUT, HttpStatus.TEMPORARY_REDIRECT_307);
}
private void testSameMethodRedirect(final HttpMethod method, int redirectCode) throws Exception
{
testMethodRedirect(method, method, redirectCode);
}
private void testGETRedirect(final HttpMethod method, int redirectCode) throws Exception
{
testMethodRedirect(method, HttpMethod.GET, redirectCode);
}
private void testMethodRedirect(final HttpMethod requestMethod, final HttpMethod redirectMethod, int redirectCode) throws Exception
{
final AtomicInteger passes = new AtomicInteger();
client.getRequestListeners().add(new org.eclipse.jetty.client.api.Request.Listener.Empty()
{
@Override
public void onBegin(org.eclipse.jetty.client.api.Request request)
{
int pass = passes.incrementAndGet();
if (pass == 1)
{
if (!requestMethod.is(request.method()))
request.abort(new Exception());
}
else if (pass == 2)
{
if (!redirectMethod.is(request.method()))
request.abort(new Exception());
}
else
{
request.abort(new Exception());
}
}
});
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.method(requestMethod)
.path("/" + redirectCode + "/localhost/done")
.timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertEquals(200, response.getStatus());
}
private class RedirectHandler extends AbstractHandler
{
@Override