Added test cases for ProtocolExec and RedirectExec
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1512264 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
23f6255cd7
commit
553e7dd320
|
@ -175,6 +175,18 @@ public final class HttpRoute implements RouteInfo, Cloneable {
|
||||||
secure ? LayerType.LAYERED : LayerType.PLAIN);
|
secure ? LayerType.LAYERED : LayerType.PLAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new plain route through a proxy.
|
||||||
|
*
|
||||||
|
* @param target the host to which to route
|
||||||
|
* @param proxy the proxy to use
|
||||||
|
*
|
||||||
|
* @since 4.3
|
||||||
|
*/
|
||||||
|
public HttpRoute(final HttpHost target, final HttpHost proxy) {
|
||||||
|
this(target, null, proxy, false);
|
||||||
|
}
|
||||||
|
|
||||||
public final HttpHost getTargetHost() {
|
public final HttpHost getTargetHost() {
|
||||||
return this.targetHost;
|
return this.targetHost;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ import org.apache.http.client.params.ClientPNames;
|
||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
import org.apache.http.client.utils.URIUtils;
|
import org.apache.http.client.utils.URIUtils;
|
||||||
import org.apache.http.conn.routing.HttpRoute;
|
import org.apache.http.conn.routing.HttpRoute;
|
||||||
|
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||||
import org.apache.http.params.HttpParams;
|
import org.apache.http.params.HttpParams;
|
||||||
import org.apache.http.protocol.HttpProcessor;
|
import org.apache.http.protocol.HttpProcessor;
|
||||||
import org.apache.http.util.Args;
|
import org.apache.http.util.Args;
|
||||||
|
@ -72,7 +73,7 @@ public class ProtocolExec implements ClientExecChain {
|
||||||
this.httpProcessor = httpProcessor;
|
this.httpProcessor = httpProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rewriteRequestURI(
|
void rewriteRequestURI(
|
||||||
final HttpRequestWrapper request,
|
final HttpRequestWrapper request,
|
||||||
final HttpRoute route) throws ProtocolException {
|
final HttpRoute route) throws ProtocolException {
|
||||||
try {
|
try {
|
||||||
|
@ -101,8 +102,11 @@ public class ProtocolExec implements ClientExecChain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CloseableHttpResponse execute(final HttpRoute route, final HttpRequestWrapper request,
|
public CloseableHttpResponse execute(
|
||||||
final HttpClientContext context, final HttpExecutionAware execAware) throws IOException,
|
final HttpRoute route,
|
||||||
|
final HttpRequestWrapper request,
|
||||||
|
final HttpClientContext context,
|
||||||
|
final HttpExecutionAware execAware) throws IOException,
|
||||||
HttpException {
|
HttpException {
|
||||||
Args.notNull(route, "HTTP route");
|
Args.notNull(route, "HTTP route");
|
||||||
Args.notNull(request, "HTTP request");
|
Args.notNull(request, "HTTP request");
|
||||||
|
@ -159,7 +163,11 @@ public class ProtocolExec implements ClientExecChain {
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
final String userinfo = uri.getUserInfo();
|
final String userinfo = uri.getUserInfo();
|
||||||
if (userinfo != null) {
|
if (userinfo != null) {
|
||||||
final CredentialsProvider credsProvider = context.getCredentialsProvider();
|
CredentialsProvider credsProvider = context.getCredentialsProvider();
|
||||||
|
if (credsProvider == null) {
|
||||||
|
credsProvider = new BasicCredentialsProvider();
|
||||||
|
context.setCredentialsProvider(credsProvider);
|
||||||
|
}
|
||||||
credsProvider.setCredentials(
|
credsProvider.setCredentials(
|
||||||
new AuthScope(target),
|
new AuthScope(target),
|
||||||
new UsernamePasswordCredentials(userinfo));
|
new UsernamePasswordCredentials(userinfo));
|
||||||
|
|
|
@ -636,10 +636,9 @@ public class TestMainClientExec {
|
||||||
final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
|
||||||
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
|
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
|
||||||
|
|
||||||
final ArgumentCaptor<HttpRequest> reqCaptor = ArgumentCaptor.forClass(HttpRequest.class);
|
|
||||||
Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE);
|
Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE);
|
||||||
Mockito.when(requestExecutor.execute(
|
Mockito.when(requestExecutor.execute(
|
||||||
reqCaptor.capture(),
|
Mockito.<HttpRequest>any(),
|
||||||
Mockito.<HttpClientConnection>any(),
|
Mockito.<HttpClientConnection>any(),
|
||||||
Mockito.<HttpClientContext>any())).thenReturn(response);
|
Mockito.<HttpClientContext>any())).thenReturn(response);
|
||||||
|
|
||||||
|
@ -647,7 +646,11 @@ public class TestMainClientExec {
|
||||||
|
|
||||||
Mockito.verify(connManager).connect(managedConn, route, 321, context);
|
Mockito.verify(connManager).connect(managedConn, route, 321, context);
|
||||||
Mockito.verify(connManager).routeComplete(managedConn, route, context);
|
Mockito.verify(connManager).routeComplete(managedConn, route, context);
|
||||||
|
final ArgumentCaptor<HttpRequest> reqCaptor = ArgumentCaptor.forClass(HttpRequest.class);
|
||||||
|
Mockito.verify(requestExecutor).execute(
|
||||||
|
reqCaptor.capture(),
|
||||||
|
Mockito.same(managedConn),
|
||||||
|
Mockito.same(context));
|
||||||
final HttpRequest connect = reqCaptor.getValue();
|
final HttpRequest connect = reqCaptor.getValue();
|
||||||
Assert.assertNotNull(connect);
|
Assert.assertNotNull(connect);
|
||||||
Assert.assertEquals("CONNECT", connect.getRequestLine().getMethod());
|
Assert.assertEquals("CONNECT", connect.getRequestLine().getMethod());
|
||||||
|
|
|
@ -26,41 +26,131 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.http.impl.execchain;
|
package org.apache.http.impl.execchain;
|
||||||
|
|
||||||
|
import org.apache.http.HttpException;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
|
import org.apache.http.auth.AuthScope;
|
||||||
|
import org.apache.http.auth.Credentials;
|
||||||
|
import org.apache.http.client.CredentialsProvider;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpExecutionAware;
|
import org.apache.http.client.methods.HttpExecutionAware;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpRequestWrapper;
|
import org.apache.http.client.methods.HttpRequestWrapper;
|
||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
import org.apache.http.conn.routing.HttpRoute;
|
import org.apache.http.conn.routing.HttpRoute;
|
||||||
import org.apache.http.message.BasicHttpRequest;
|
import org.apache.http.message.BasicHttpRequest;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
import org.apache.http.protocol.HttpProcessor;
|
import org.apache.http.protocol.HttpProcessor;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
public class TestProtocolExec {
|
public class TestProtocolExec {
|
||||||
|
|
||||||
|
@Mock
|
||||||
private ClientExecChain requestExecutor;
|
private ClientExecChain requestExecutor;
|
||||||
|
@Mock
|
||||||
private HttpProcessor httpProcessor;
|
private HttpProcessor httpProcessor;
|
||||||
private ProtocolExec protocolExec;
|
@Mock
|
||||||
private HttpClientContext context;
|
|
||||||
private HttpRequestWrapper request;
|
|
||||||
private HttpExecutionAware execAware;
|
private HttpExecutionAware execAware;
|
||||||
private HttpRoute route;
|
|
||||||
|
private ProtocolExec protocolExec;
|
||||||
|
private HttpHost target;
|
||||||
|
private HttpHost proxy;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws Exception {
|
public void setup() throws Exception {
|
||||||
requestExecutor = Mockito.mock(ClientExecChain.class);
|
MockitoAnnotations.initMocks(this);
|
||||||
httpProcessor = Mockito.mock(HttpProcessor.class);
|
|
||||||
protocolExec = new ProtocolExec(requestExecutor, httpProcessor);
|
protocolExec = new ProtocolExec(requestExecutor, httpProcessor);
|
||||||
route = new HttpRoute(new HttpHost("foo", 8080));
|
target = new HttpHost("foo", 80);
|
||||||
context = new HttpClientContext();
|
proxy = new HttpHost("bar", 8888);
|
||||||
execAware = Mockito.mock(HttpExecutionAware.class);
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFundamentals() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("/test"));
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
|
||||||
|
final CloseableHttpResponse response = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response);
|
||||||
|
|
||||||
|
protocolExec.execute(route, request, context, execAware);
|
||||||
|
|
||||||
|
Mockito.verify(httpProcessor).process(request, context);
|
||||||
|
Mockito.verify(requestExecutor).execute(route, request, context, execAware);
|
||||||
|
Mockito.verify(httpProcessor).process(response, context);
|
||||||
|
|
||||||
|
Assert.assertEquals(new HttpHost("foo", 80), context.getTargetHost());
|
||||||
|
Assert.assertEquals(target, context.getTargetHost());
|
||||||
|
Assert.assertEquals(route, context.getHttpRoute());
|
||||||
|
Assert.assertSame(request, context.getRequest());
|
||||||
|
Assert.assertSame(response, context.getResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRewriteAbsoluteRequestURI() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(
|
||||||
|
new HttpGet("http://foo/test"));
|
||||||
|
protocolExec.rewriteRequestURI(request, route);
|
||||||
|
Assert.assertEquals(new URI("/test"), request.getURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRewriteEmptyRequestURI() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(
|
||||||
|
new HttpGet(""));
|
||||||
|
protocolExec.rewriteRequestURI(request, route);
|
||||||
|
Assert.assertEquals(new URI("/"), request.getURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRewriteAbsoluteRequestURIViaPRoxy() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target, proxy);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(
|
||||||
|
new HttpGet("http://foo/test"));
|
||||||
|
protocolExec.rewriteRequestURI(request, route);
|
||||||
|
Assert.assertEquals(new URI("http://foo/test"), request.getURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRewriteRelativeRequestURIViaPRoxy() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target, proxy);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(
|
||||||
|
new HttpGet("/test"));
|
||||||
|
protocolExec.rewriteRequestURI(request, route);
|
||||||
|
Assert.assertEquals(new URI("http://foo:80/test"), request.getURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHostHeaderUriRequest() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(
|
||||||
|
new HttpGet("http://bar/test"));
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
protocolExec.execute(route, request, context, execAware);
|
||||||
|
// ProtocolExect should have extracted the host from request URI
|
||||||
|
Assert.assertEquals(new HttpHost("bar", -1, "http"), context.getTargetHost());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHostHeaderWhenNonUriRequest() throws Exception {
|
public void testHostHeaderWhenNonUriRequest() throws Exception {
|
||||||
request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "http://bar/test"));
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(
|
||||||
|
new BasicHttpRequest("GET", "http://bar/test"));
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
protocolExec.execute(route, request, context, execAware);
|
protocolExec.execute(route, request, context, execAware);
|
||||||
// ProtocolExect should have extracted the host from request URI
|
// ProtocolExect should have extracted the host from request URI
|
||||||
Assert.assertEquals(new HttpHost("bar", -1, "http"), context.getTargetHost());
|
Assert.assertEquals(new HttpHost("bar", -1, "http"), context.getTargetHost());
|
||||||
|
@ -68,11 +158,107 @@ public class TestProtocolExec {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHostHeaderWhenNonUriRequestAndInvalidUri() throws Exception {
|
public void testHostHeaderWhenNonUriRequestAndInvalidUri() throws Exception {
|
||||||
request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "http://bar/test|"));
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(
|
||||||
|
new BasicHttpRequest("GET", "http://bar/test|"));
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
protocolExec.execute(route, request, context, execAware);
|
protocolExec.execute(route, request, context, execAware);
|
||||||
// ProtocolExect should have fall back to physical host as request URI
|
// ProtocolExect should have fall back to physical host as request URI
|
||||||
// is not parseable
|
// is not parseable
|
||||||
Assert.assertEquals(new HttpHost("foo", 8080, "http"), context.getTargetHost());
|
Assert.assertEquals(new HttpHost("foo", 80, "http"), context.getTargetHost());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHostHeaderImplicitHost() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(new HttpHost("somehost", 8080));
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(
|
||||||
|
new HttpGet("/test"));
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
protocolExec.execute(route, request, context, execAware);
|
||||||
|
Assert.assertEquals(new HttpHost("somehost", 8080), context.getTargetHost());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUserInfoInRequestURI() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(new HttpHost("somehost", 8080));
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(
|
||||||
|
new HttpGet("http://somefella:secret@bar/test"));
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
protocolExec.execute(route, request, context, execAware);
|
||||||
|
Assert.assertEquals(new URI("/test"), request.getURI());
|
||||||
|
Assert.assertEquals(new HttpHost("bar", -1), context.getTargetHost());
|
||||||
|
final CredentialsProvider credentialsProvider = context.getCredentialsProvider();
|
||||||
|
Assert.assertNotNull(credentialsProvider);
|
||||||
|
final Credentials creds = credentialsProvider.getCredentials(new AuthScope("bar", -1, null));
|
||||||
|
Assert.assertNotNull(creds);
|
||||||
|
Assert.assertEquals("somefella", creds.getUserPrincipal().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HttpException.class)
|
||||||
|
public void testPostProcessHttpException() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("/test"));
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
|
||||||
|
final CloseableHttpResponse response = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response);
|
||||||
|
Mockito.doThrow(new HttpException("Ooopsie")).when(httpProcessor).process(
|
||||||
|
Mockito.same(response), Mockito.<HttpContext>any());
|
||||||
|
try {
|
||||||
|
protocolExec.execute(route, request, context, execAware);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Mockito.verify(response).close();
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IOException.class)
|
||||||
|
public void testPostProcessIOException() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("/test"));
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
|
||||||
|
final CloseableHttpResponse response = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response);
|
||||||
|
Mockito.doThrow(new IOException("Ooopsie")).when(httpProcessor).process(
|
||||||
|
Mockito.same(response), Mockito.<HttpContext>any());
|
||||||
|
try {
|
||||||
|
protocolExec.execute(route, request, context, execAware);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Mockito.verify(response).close();
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = RuntimeException.class)
|
||||||
|
public void testPostProcessRuntimeException() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("/test"));
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
|
||||||
|
final CloseableHttpResponse response = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response);
|
||||||
|
Mockito.doThrow(new RuntimeException("Ooopsie")).when(httpProcessor).process(
|
||||||
|
Mockito.same(response), Mockito.<HttpContext>any());
|
||||||
|
try {
|
||||||
|
protocolExec.execute(route, request, context, execAware);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Mockito.verify(response).close();
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,370 @@
|
||||||
|
/*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This software consists of voluntary contributions made by many
|
||||||
|
* individuals on behalf of the Apache Software Foundation. For more
|
||||||
|
* information on the Apache Software Foundation, please see
|
||||||
|
* <http://www.apache.org/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.apache.http.impl.execchain;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.HttpException;
|
||||||
|
import org.apache.http.HttpHost;
|
||||||
|
import org.apache.http.HttpRequest;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.ProtocolException;
|
||||||
|
import org.apache.http.auth.AuthProtocolState;
|
||||||
|
import org.apache.http.auth.AuthState;
|
||||||
|
import org.apache.http.auth.NTCredentials;
|
||||||
|
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||||
|
import org.apache.http.client.RedirectException;
|
||||||
|
import org.apache.http.client.RedirectStrategy;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
import org.apache.http.client.entity.EntityBuilder;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpExecutionAware;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpRequestWrapper;
|
||||||
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
|
import org.apache.http.conn.routing.HttpRoute;
|
||||||
|
import org.apache.http.conn.routing.HttpRoutePlanner;
|
||||||
|
import org.apache.http.impl.auth.BasicScheme;
|
||||||
|
import org.apache.http.impl.auth.NTLMScheme;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.ArgumentMatcher;
|
||||||
|
import org.mockito.Matchers;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TestRedirectExec {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ClientExecChain requestExecutor;
|
||||||
|
@Mock
|
||||||
|
private HttpRoutePlanner httpRoutePlanner;
|
||||||
|
@Mock
|
||||||
|
private RedirectStrategy redirectStrategy;
|
||||||
|
@Mock
|
||||||
|
private HttpExecutionAware execAware;
|
||||||
|
|
||||||
|
private RedirectExec redirectExec;
|
||||||
|
private HttpHost target;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() throws Exception {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
redirectExec = new RedirectExec(requestExecutor, httpRoutePlanner, redirectStrategy);
|
||||||
|
target = new HttpHost("localhost", 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFundamentals() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpGet get = new HttpGet("/test");
|
||||||
|
get.addHeader("header", "this");
|
||||||
|
get.addHeader("header", "that");
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(get);
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
|
||||||
|
final CloseableHttpResponse response1 = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3}));
|
||||||
|
final HttpEntity entity1 = EntityBuilder.create()
|
||||||
|
.setStream(instream1)
|
||||||
|
.build();
|
||||||
|
Mockito.when(response1.getEntity()).thenReturn(entity1);
|
||||||
|
final CloseableHttpResponse response2 = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
final InputStream instream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3}));
|
||||||
|
final HttpEntity entity2 = EntityBuilder.create()
|
||||||
|
.setStream(instream2)
|
||||||
|
.build();
|
||||||
|
Mockito.when(response2.getEntity()).thenReturn(entity2);
|
||||||
|
final HttpGet redirect = new HttpGet("http://localhost:80/redirect");
|
||||||
|
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response1);
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
HttpRequestWrapperMatcher.same(redirect),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response2);
|
||||||
|
Mockito.when(redirectStrategy.isRedirected(
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.same(response1),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(Boolean.TRUE);
|
||||||
|
Mockito.when(redirectStrategy.getRedirect(
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.same(response1),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(redirect);
|
||||||
|
Mockito.when(httpRoutePlanner.determineRoute(
|
||||||
|
Mockito.eq(target),
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(route);
|
||||||
|
|
||||||
|
redirectExec.execute(route, request, context, execAware);
|
||||||
|
|
||||||
|
final ArgumentCaptor<HttpRequestWrapper> reqCaptor = ArgumentCaptor.forClass(
|
||||||
|
HttpRequestWrapper.class);
|
||||||
|
Mockito.verify(requestExecutor, Mockito.times(2)).execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
reqCaptor.capture(),
|
||||||
|
Mockito.same(context),
|
||||||
|
Mockito.same(execAware));
|
||||||
|
|
||||||
|
final List<HttpRequestWrapper> allValues = reqCaptor.getAllValues();
|
||||||
|
Assert.assertNotNull(allValues);
|
||||||
|
Assert.assertEquals(2, allValues.size());
|
||||||
|
Assert.assertSame(request, allValues.get(0));
|
||||||
|
final HttpRequestWrapper redirectWrapper = allValues.get(1);
|
||||||
|
final Header[] headers = redirectWrapper.getHeaders("header");
|
||||||
|
Assert.assertNotNull(headers);
|
||||||
|
Assert.assertEquals(2, headers.length);
|
||||||
|
Assert.assertEquals("this", headers[0].getValue());
|
||||||
|
Assert.assertEquals("that", headers[1].getValue());
|
||||||
|
|
||||||
|
Mockito.verify(response1, Mockito.times(1)).close();
|
||||||
|
Mockito.verify(instream1, Mockito.times(1)).close();
|
||||||
|
Mockito.verify(response2, Mockito.never()).close();
|
||||||
|
Mockito.verify(instream2, Mockito.never()).close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = RedirectException.class)
|
||||||
|
public void testMaxRedirect() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpGet get = new HttpGet("/test");
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(get);
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
final RequestConfig config = RequestConfig.custom()
|
||||||
|
.setRedirectsEnabled(true)
|
||||||
|
.setMaxRedirects(3)
|
||||||
|
.build();
|
||||||
|
context.setRequestConfig(config);
|
||||||
|
|
||||||
|
final CloseableHttpResponse response1 = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
final HttpGet redirect = new HttpGet("http://localhost:80/redirect");
|
||||||
|
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response1);
|
||||||
|
Mockito.when(redirectStrategy.isRedirected(
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpResponse>any(),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(Boolean.TRUE);
|
||||||
|
Mockito.when(redirectStrategy.getRedirect(
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpResponse>any(),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(redirect);
|
||||||
|
Mockito.when(httpRoutePlanner.determineRoute(
|
||||||
|
Mockito.eq(target),
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(route);
|
||||||
|
|
||||||
|
redirectExec.execute(route, request, context, execAware);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HttpException.class)
|
||||||
|
public void testRelativeRedirect() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpGet get = new HttpGet("/test");
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(get);
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
|
||||||
|
final CloseableHttpResponse response1 = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
final CloseableHttpResponse response2 = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
final HttpGet redirect = new HttpGet("/redirect");
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response1);
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
HttpRequestWrapperMatcher.same(redirect),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response2);
|
||||||
|
Mockito.when(redirectStrategy.isRedirected(
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.same(response1),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(Boolean.TRUE);
|
||||||
|
Mockito.when(redirectStrategy.getRedirect(
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.same(response1),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(redirect);
|
||||||
|
Mockito.when(httpRoutePlanner.determineRoute(
|
||||||
|
Mockito.eq(target),
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(route);
|
||||||
|
|
||||||
|
redirectExec.execute(route, request, context, execAware);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCrossSiteRedirect() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpGet get = new HttpGet("/test");
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(get);
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
|
||||||
|
final AuthState targetAuthState = new AuthState();
|
||||||
|
targetAuthState.setState(AuthProtocolState.SUCCESS);
|
||||||
|
targetAuthState.update(new BasicScheme(), new UsernamePasswordCredentials("user:pass"));
|
||||||
|
final AuthState proxyAuthState = new AuthState();
|
||||||
|
proxyAuthState.setState(AuthProtocolState.SUCCESS);
|
||||||
|
proxyAuthState.update(new NTLMScheme(), new NTCredentials("user:pass"));
|
||||||
|
context.setAttribute(HttpClientContext.TARGET_AUTH_STATE, targetAuthState);
|
||||||
|
context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, proxyAuthState);
|
||||||
|
|
||||||
|
final CloseableHttpResponse response1 = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
final CloseableHttpResponse response2 = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
final HttpGet redirect = new HttpGet("http://otherhost/redirect");
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response1);
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
HttpRequestWrapperMatcher.same(redirect),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response2);
|
||||||
|
Mockito.when(redirectStrategy.isRedirected(
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.same(response1),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(Boolean.TRUE);
|
||||||
|
Mockito.when(redirectStrategy.getRedirect(
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.same(response1),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(redirect);
|
||||||
|
Mockito.when(httpRoutePlanner.determineRoute(
|
||||||
|
Mockito.eq(target),
|
||||||
|
Mockito.<HttpRequestWrapper>any(),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(new HttpRoute(new HttpHost("otherhost")));
|
||||||
|
|
||||||
|
redirectExec.execute(route, request, context, execAware);
|
||||||
|
|
||||||
|
Assert.assertNotNull(context.getTargetAuthState());
|
||||||
|
Assert.assertEquals(AuthProtocolState.UNCHALLENGED, context.getTargetAuthState().getState());
|
||||||
|
Assert.assertEquals(null, context.getTargetAuthState().getAuthScheme());
|
||||||
|
Assert.assertNotNull(context.getProxyAuthState());
|
||||||
|
Assert.assertEquals(AuthProtocolState.UNCHALLENGED, context.getProxyAuthState().getState());
|
||||||
|
Assert.assertEquals(null, context.getProxyAuthState().getAuthScheme());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = RuntimeException.class)
|
||||||
|
public void testRedirectRuntimeException() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpGet get = new HttpGet("/test");
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(get);
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
|
||||||
|
final CloseableHttpResponse response1 = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response1);
|
||||||
|
Mockito.when(redirectStrategy.isRedirected(
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.same(response1),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(Boolean.TRUE);
|
||||||
|
Mockito.doThrow(new RuntimeException("Oppsie")).when(redirectStrategy.getRedirect(
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.same(response1),
|
||||||
|
Mockito.<HttpClientContext>any()));
|
||||||
|
|
||||||
|
try {
|
||||||
|
redirectExec.execute(route, request, context, execAware);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Mockito.verify(response1).close();
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ProtocolException.class)
|
||||||
|
public void testRedirectProtocolException() throws Exception {
|
||||||
|
final HttpRoute route = new HttpRoute(target);
|
||||||
|
final HttpGet get = new HttpGet("/test");
|
||||||
|
final HttpRequestWrapper request = HttpRequestWrapper.wrap(get);
|
||||||
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
|
|
||||||
|
final CloseableHttpResponse response1 = Mockito.mock(CloseableHttpResponse.class);
|
||||||
|
final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3}));
|
||||||
|
final HttpEntity entity1 = EntityBuilder.create()
|
||||||
|
.setStream(instream1)
|
||||||
|
.build();
|
||||||
|
Mockito.when(response1.getEntity()).thenReturn(entity1);
|
||||||
|
Mockito.when(requestExecutor.execute(
|
||||||
|
Mockito.eq(route),
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.<HttpClientContext>any(),
|
||||||
|
Mockito.<HttpExecutionAware>any())).thenReturn(response1);
|
||||||
|
Mockito.when(redirectStrategy.isRedirected(
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.same(response1),
|
||||||
|
Mockito.<HttpClientContext>any())).thenReturn(Boolean.TRUE);
|
||||||
|
Mockito.doThrow(new ProtocolException("Oppsie")).when(redirectStrategy).getRedirect(
|
||||||
|
Mockito.same(request),
|
||||||
|
Mockito.same(response1),
|
||||||
|
Mockito.<HttpClientContext>any());
|
||||||
|
|
||||||
|
try {
|
||||||
|
redirectExec.execute(route, request, context, execAware);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Mockito.verify(instream1).close();
|
||||||
|
Mockito.verify(response1).close();
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class HttpRequestWrapperMatcher extends ArgumentMatcher<HttpRequestWrapper> {
|
||||||
|
|
||||||
|
private final HttpRequest original;
|
||||||
|
|
||||||
|
HttpRequestWrapperMatcher(final HttpRequest original) {
|
||||||
|
super();
|
||||||
|
this.original = original;
|
||||||
|
}
|
||||||
|
public boolean matches(final Object obj) {
|
||||||
|
final HttpRequestWrapper wrapper = (HttpRequestWrapper) obj;
|
||||||
|
return original == wrapper.getOriginal();
|
||||||
|
}
|
||||||
|
|
||||||
|
static HttpRequestWrapper same(final HttpRequest original) {
|
||||||
|
return Matchers.argThat(new HttpRequestWrapperMatcher(original));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue