Skip to content

Commit d9afadb

Browse files
committed
Add test
1 parent 31f81ae commit d9afadb

File tree

2 files changed

+192
-0
lines changed

2 files changed

+192
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* ====================================================================
3+
* Licensed to the Apache Software Foundation (ASF) under one
4+
* or more contributor license agreements. See the NOTICE file
5+
* distributed with this work for additional information
6+
* regarding copyright ownership. The ASF licenses this file
7+
* to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance
9+
* with the License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing,
14+
* software distributed under the License is distributed on an
15+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
* KIND, either express or implied. See the License for the
17+
* specific language governing permissions and limitations
18+
* under the License.
19+
* ====================================================================
20+
*
21+
* This software consists of voluntary contributions made by many
22+
* individuals on behalf of the Apache Software Foundation. For more
23+
* information on the Apache Software Foundation, please see
24+
* <http://www.apache.org/>.
25+
*
26+
*/
27+
package org.apache.hc.client5.http.impl.async;
28+
29+
import java.io.IOException;
30+
import java.util.Collections;
31+
import java.util.concurrent.atomic.AtomicInteger;
32+
33+
import org.apache.hc.client5.http.AuthenticationStrategy;
34+
import org.apache.hc.client5.http.HttpRoute;
35+
import org.apache.hc.client5.http.async.AsyncExecCallback;
36+
import org.apache.hc.client5.http.async.AsyncExecChain;
37+
import org.apache.hc.client5.http.async.AsyncExecRuntime;
38+
import org.apache.hc.client5.http.auth.AuthExchange;
39+
import org.apache.hc.client5.http.auth.AuthScope;
40+
import org.apache.hc.client5.http.auth.ChallengeType;
41+
import org.apache.hc.client5.http.auth.StandardAuthScheme;
42+
import org.apache.hc.client5.http.impl.auth.BasicScheme;
43+
import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
44+
import org.apache.hc.client5.http.protocol.HttpClientContext;
45+
import org.apache.hc.core5.concurrent.CancellableDependency;
46+
import org.apache.hc.core5.http.EntityDetails;
47+
import org.apache.hc.core5.http.HttpHeaders;
48+
import org.apache.hc.core5.http.HttpHost;
49+
import org.apache.hc.core5.http.HttpRequest;
50+
import org.apache.hc.core5.http.HttpResponse;
51+
import org.apache.hc.core5.http.message.BasicHttpResponse;
52+
import org.apache.hc.core5.http.nio.AsyncDataConsumer;
53+
import org.apache.hc.core5.http.nio.AsyncEntityProducer;
54+
import org.apache.hc.core5.http.support.BasicRequestBuilder;
55+
import org.junit.jupiter.api.Assertions;
56+
import org.junit.jupiter.api.BeforeEach;
57+
import org.junit.jupiter.api.Test;
58+
import org.mockito.Mock;
59+
import org.mockito.Mockito;
60+
import org.mockito.MockitoAnnotations;
61+
62+
class TestAsyncProtocolExec {
63+
64+
@Mock
65+
private AuthenticationStrategy targetAuthStrategy;
66+
@Mock
67+
private AuthenticationStrategy proxyAuthStrategy;
68+
@Mock
69+
private AsyncExecChain chain;
70+
@Mock
71+
private AsyncExecRuntime execRuntime;
72+
73+
private AsyncProtocolExec protocolExec;
74+
private HttpHost target;
75+
76+
@BeforeEach
77+
void setup() {
78+
MockitoAnnotations.openMocks(this);
79+
protocolExec = new AsyncProtocolExec(targetAuthStrategy, proxyAuthStrategy, null, true);
80+
target = new HttpHost("http", "foo", 80);
81+
}
82+
83+
@Test
84+
void testAuthExchangePathPrefixRestoredAfterChallenge() throws Exception {
85+
final HttpRoute route = new HttpRoute(target);
86+
final HttpClientContext context = HttpClientContext.create();
87+
context.setCredentialsProvider(CredentialsProviderBuilder.create()
88+
.add(new AuthScope(target), "user", "pass".toCharArray())
89+
.build());
90+
91+
Mockito.when(targetAuthStrategy.select(
92+
Mockito.eq(ChallengeType.TARGET),
93+
Mockito.any(),
94+
Mockito.<HttpClientContext>any()))
95+
.thenReturn(Collections.singletonList(new BasicScheme()));
96+
97+
Mockito.when(execRuntime.isEndpointConnected()).thenReturn(true);
98+
99+
final AtomicInteger proceedCount = new AtomicInteger(0);
100+
101+
Mockito.doAnswer(invocation -> {
102+
final AsyncExecCallback cb = invocation.getArgument(3, AsyncExecCallback.class);
103+
final int i = proceedCount.getAndIncrement();
104+
105+
if (i == 0) {
106+
final HttpResponse resp1 = new BasicHttpResponse(401, "Huh?");
107+
resp1.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=test");
108+
cb.handleResponse(resp1, (EntityDetails) null);
109+
cb.completed();
110+
} else {
111+
final HttpResponse resp2 = new BasicHttpResponse(200, "OK");
112+
cb.handleResponse(resp2, (EntityDetails) null);
113+
cb.completed();
114+
}
115+
return null;
116+
}).when(chain).proceed(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
117+
118+
final HttpRequest request = BasicRequestBuilder.get("http://foo/blah/a").build();
119+
120+
final CancellableDependency dependency = Mockito.mock(CancellableDependency.class);
121+
final AsyncExecChain.Scope scope = new AsyncExecChain.Scope(
122+
"test",
123+
route,
124+
request,
125+
dependency,
126+
context,
127+
execRuntime,
128+
null,
129+
new AtomicInteger(1));
130+
131+
final AsyncExecCallback asyncCallback = new AsyncExecCallback() {
132+
@Override
133+
public AsyncDataConsumer handleResponse(final HttpResponse response, final EntityDetails entityDetails)
134+
throws IOException {
135+
return Mockito.mock(AsyncDataConsumer.class);
136+
}
137+
138+
@Override
139+
public void handleInformationResponse(final HttpResponse response) {
140+
}
141+
142+
@Override
143+
public void completed() {
144+
}
145+
146+
@Override
147+
public void failed(final Exception cause) {
148+
Assertions.fail(cause);
149+
}
150+
};
151+
152+
protocolExec.execute(request, (AsyncEntityProducer) null, scope, chain, asyncCallback);
153+
154+
Assertions.assertEquals(2, proceedCount.get());
155+
156+
final AuthExchange authExchange = context.getAuthExchange(target);
157+
Assertions.assertEquals("/blah/", authExchange.getPathPrefix());
158+
}
159+
}

httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestProtocolExec.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,37 @@ void testExecEntityEnclosingRequest() throws Exception {
276276
Assertions.assertEquals(401, response.getCode());
277277
}
278278

279+
@Test
280+
void testAuthExchangePathPrefixRestoredAfterChallenge() throws Exception {
281+
final HttpRoute route = new HttpRoute(target);
282+
final ClassicHttpRequest request = new HttpGet("http://foo/blah/a");
283+
final HttpClientContext context = HttpClientContext.create();
284+
285+
context.setCredentialsProvider(CredentialsProviderBuilder.create()
286+
.add(new AuthScope(target), "user", "pass".toCharArray())
287+
.build());
288+
289+
final ClassicHttpResponse response1 = new BasicClassicHttpResponse(401, "Huh?");
290+
response1.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=test");
291+
final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK");
292+
293+
Mockito.when(chain.proceed(Mockito.same(request), Mockito.any()))
294+
.thenReturn(response1, response2);
295+
296+
Mockito.when(targetAuthStrategy.select(
297+
Mockito.eq(ChallengeType.TARGET),
298+
Mockito.any(),
299+
Mockito.<HttpClientContext>any()))
300+
.thenReturn(Collections.singletonList(new BasicScheme()));
301+
302+
Mockito.when(execRuntime.isConnectionReusable()).thenReturn(true);
303+
304+
final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
305+
final ClassicHttpResponse finalResponse = protocolExec.execute(request, scope, chain);
306+
307+
Assertions.assertEquals(200, finalResponse.getCode());
308+
309+
final AuthExchange authExchange = context.getAuthExchange(target);
310+
Assertions.assertEquals("/blah/", authExchange.getPathPrefix());
311+
}
279312
}

0 commit comments

Comments
 (0)