Skip to content

Commit 3d438e9

Browse files
committed
issue #363 support multiple interceptors
1 parent 6eff9ed commit 3d438e9

File tree

4 files changed

+245
-8
lines changed

4 files changed

+245
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/**
2+
* The MIT License
3+
*
4+
* Copyright for portions of unirest-java are held by Kong Inc (c) 2013.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining
7+
* a copy of this software and associated documentation files (the
8+
* "Software"), to deal in the Software without restriction, including
9+
* without limitation the rights to use, copy, modify, merge, publish,
10+
* distribute, sublicense, and/or sell copies of the Software, and to
11+
* permit persons to whom the Software is furnished to do so, subject to
12+
* the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be
15+
* included in all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
package kong.unirest;
27+
28+
import java.util.*;
29+
30+
class CompoundInterceptor implements Interceptor {
31+
private List<Interceptor> interceptors;
32+
33+
CompoundInterceptor() {
34+
this(Collections.singletonList(new DefaultInterceptor()));
35+
}
36+
37+
CompoundInterceptor(List<Interceptor> interceptors) {
38+
this.interceptors = interceptors;
39+
}
40+
41+
@Override
42+
public void onRequest(HttpRequest<?> request, Config config) {
43+
interceptors.forEach(i -> i.onRequest(request, config));
44+
}
45+
46+
@Override
47+
public void onResponse(HttpResponse<?> response, HttpRequestSummary request, Config config) {
48+
interceptors.forEach(i -> i.onResponse(response, request, config));
49+
}
50+
51+
@Override
52+
public HttpResponse<?> onFail(Exception e, HttpRequestSummary request, Config config) throws UnirestException {
53+
return interceptors.stream()
54+
.map(i -> Optional.ofNullable(i.onFail(e, request, config)))
55+
.flatMap(Util::stream)
56+
.findFirst()
57+
.orElseThrow(() -> new UnirestException(e));
58+
}
59+
60+
int size() {
61+
return interceptors.size();
62+
}
63+
64+
List<Interceptor> getInterceptors() {
65+
return new ArrayList<>(interceptors);
66+
}
67+
68+
void register(Interceptor t1) {
69+
if(interceptors.stream().anyMatch(i -> i instanceof DefaultInterceptor)){
70+
interceptors = new ArrayList<>();
71+
}
72+
if(!interceptors.contains(t1)){
73+
interceptors.add(t1);
74+
}
75+
}
76+
}

unirest/src/main/java/kong/unirest/Config.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@
4848
import java.util.stream.Collectors;
4949
import java.util.stream.Stream;
5050

51-
import static kong.unirest.Util.tryCast;
52-
5351
public class Config {
5452
public static final int DEFAULT_CONNECTION_TIMEOUT = 10000;
5553
public static final int DEFAULT_MAX_CONNECTIONS = 200;
@@ -84,7 +82,7 @@ public class Config {
8482
private UniMetric metrics = new NoopMetric();
8583
private long ttl = -1;
8684
private SSLContext sslContext;
87-
private Interceptor interceptor = new DefaultInterceptor();
85+
private CompoundInterceptor interceptor = new CompoundInterceptor();
8886
private HostnameVerifier hostnameVerifier;
8987
private String defaultBaseUrl;
9088
private CacheManager cache;
@@ -110,7 +108,7 @@ private void setDefaults() {
110108
keystore = null;
111109
keystorePassword = null;
112110
sslContext = null;
113-
interceptor = new DefaultInterceptor();
111+
interceptor = new CompoundInterceptor();
114112
this.objectMapper = Optional.of(new JsonObjectMapper());
115113
try {
116114
asyncBuilder = ApacheAsyncClient::new;
@@ -431,7 +429,7 @@ public Config errorHandler(Consumer<HttpResponse<?>> consumer) {
431429
*/
432430
public Config interceptor(Interceptor value) {
433431
Objects.requireNonNull(value, "Interceptor may not be null");
434-
this.interceptor = value;
432+
this.interceptor.register(value);
435433
return this;
436434
}
437435

@@ -891,7 +889,10 @@ public SSLContext getSslContext() {
891889
}
892890

893891
private Optional<DefaultInterceptor> getDefaultInterceptor() {
894-
return tryCast(getUniInterceptor(), DefaultInterceptor.class);
892+
return interceptor.getInterceptors().stream()
893+
.filter(i -> i instanceof DefaultInterceptor)
894+
.map(i -> (DefaultInterceptor)i)
895+
.findFirst();
895896
}
896897

897898
public HostnameVerifier getHostnameVerifier() {

unirest/src/test/java/BehaviorTests/InterceptorTest.java

+20-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.junit.jupiter.api.Test;
3535

3636
import java.io.IOException;
37+
import java.util.Arrays;
3738
import java.util.concurrent.ExecutionException;
3839

3940
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -49,7 +50,7 @@ public class InterceptorTest extends BddTest {
4950
@BeforeEach
5051
public void setUp() {
5152
super.setUp();
52-
interceptor = new UniInterceptor();
53+
interceptor = new UniInterceptor("x-custom", "foo");
5354
}
5455

5556
@Test
@@ -61,6 +62,16 @@ public void canAddInterceptor() {
6162
assertEquals(MockServer.GET, interceptor.reqSum.getUrl());
6263
}
6364

65+
@Test
66+
public void canAddTwoInterceptor() {
67+
Unirest.config().interceptor(interceptor);
68+
Unirest.config().interceptor(new UniInterceptor("fruit", "grapes"));
69+
Unirest.get(MockServer.GET).asObject(RequestCapture.class);
70+
71+
interceptor.cap.assertHeader("x-custom", "foo");
72+
interceptor.cap.assertHeader("fruit", "grapes");
73+
}
74+
6475
@Test
6576
public void canAddInterceptorToAsync() throws ExecutionException, InterruptedException {
6677
Unirest.config().interceptor(interceptor);
@@ -154,10 +165,17 @@ private class UniInterceptor implements Interceptor {
154165
RequestCapture cap;
155166
HttpRequestSummary reqSum;
156167
boolean failResponse;
168+
private String name;
169+
private String value;
170+
171+
public UniInterceptor(String name, String value){
172+
this.name = name;
173+
this.value = value;
174+
}
157175

158176
@Override
159177
public void onRequest(HttpRequest<?> request, Config config) {
160-
request.header("x-custom", "foo");
178+
request.header(name, value);
161179
}
162180

163181
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/**
2+
* The MIT License
3+
*
4+
* Copyright for portions of unirest-java are held by Kong Inc (c) 2013.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining
7+
* a copy of this software and associated documentation files (the
8+
* "Software"), to deal in the Software without restriction, including
9+
* without limitation the rights to use, copy, modify, merge, publish,
10+
* distribute, sublicense, and/or sell copies of the Software, and to
11+
* permit persons to whom the Software is furnished to do so, subject to
12+
* the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be
15+
* included in all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
package kong.unirest;
27+
28+
import org.junit.jupiter.api.Test;
29+
import org.junit.jupiter.api.extension.ExtendWith;
30+
import org.mockito.Mock;
31+
import org.mockito.junit.jupiter.MockitoExtension;
32+
33+
import java.util.Arrays;
34+
import java.util.Collections;
35+
36+
import static org.junit.jupiter.api.Assertions.*;
37+
import static org.mockito.Mockito.*;
38+
39+
@ExtendWith(MockitoExtension.class)
40+
class CompoundInterceptorTest {
41+
@Mock
42+
Interceptor t1;
43+
@Mock
44+
Interceptor t2;
45+
@Mock
46+
HttpRequest<?> request;
47+
@Mock
48+
Config config;
49+
MockResponse<?> response = new MockResponse<>();
50+
@Mock
51+
HttpRequestSummary summary;
52+
53+
54+
@Test
55+
void willExecuteAllOnBefore() {
56+
CompoundInterceptor compound = new CompoundInterceptor(
57+
Arrays.asList(t1, t2)
58+
);
59+
60+
compound.onRequest(request, config);
61+
62+
verify(t1).onRequest(request, config);
63+
verify(t2).onRequest(request, config);
64+
verifyNoMoreInteractions(t1);
65+
verifyNoMoreInteractions(t2);
66+
}
67+
68+
@Test
69+
void willExecuteAllOnAfter() {
70+
CompoundInterceptor compound = new CompoundInterceptor(
71+
Arrays.asList(t1, t2)
72+
);
73+
74+
compound.onResponse(response, summary, config);
75+
76+
verify(t1).onResponse(response, summary, config);
77+
verify(t2).onResponse(response, summary, config);
78+
verifyNoMoreInteractions(t1);
79+
verifyNoMoreInteractions(t2);
80+
}
81+
82+
@Test
83+
void exceptionsStopsArFirstOne() {
84+
CompoundInterceptor compound = new CompoundInterceptor(
85+
Arrays.asList(t1, t2)
86+
);
87+
RuntimeException e = new RuntimeException();
88+
when(t2.onFail(e, summary, config)).thenReturn(new MockResponse<>());
89+
HttpResponse r = compound.onFail(e, summary, config);
90+
assertTrue(r instanceof MockResponse);
91+
92+
verify(t1).onFail(e, summary, config);
93+
verify(t2).onFail(e, summary, config);
94+
verifyNoMoreInteractions(t1);
95+
verifyNoMoreInteractions(t2);
96+
}
97+
98+
@Test
99+
void willThrowIfNothingElse() {
100+
CompoundInterceptor compound = new CompoundInterceptor(
101+
Arrays.asList()
102+
);
103+
104+
RuntimeException e = new RuntimeException();
105+
UnirestException u = assertThrows(UnirestException.class,
106+
() -> compound.onFail(e, summary, config));
107+
108+
assertSame(e, u.getCause());
109+
}
110+
111+
@Test
112+
void theDefaultInterceptorIsTheDefault() {
113+
CompoundInterceptor compound = new CompoundInterceptor();
114+
assertEquals(1, compound.size());
115+
assertTrue(compound.getInterceptors().get(0) instanceof DefaultInterceptor);
116+
}
117+
118+
@Test
119+
void buildingWithCollectionDoesNotIncludeDefault() {
120+
CompoundInterceptor compound = new CompoundInterceptor(Collections.emptyList());
121+
assertEquals(0, compound.size());
122+
}
123+
124+
@Test
125+
void canReplaceDefault() {
126+
CompoundInterceptor compound = new CompoundInterceptor();
127+
compound.register(t1);
128+
compound.register(t2);
129+
assertEquals(2, compound.size());
130+
assertSame(t1, compound.getInterceptors().get(0));
131+
assertSame(t2, compound.getInterceptors().get(1));
132+
}
133+
134+
@Test
135+
void cantAddTheSameOneTwice() {
136+
CompoundInterceptor compound = new CompoundInterceptor();
137+
compound.register(t1);
138+
compound.register(t1);
139+
140+
assertEquals(1, compound.size());
141+
}
142+
}

0 commit comments

Comments
 (0)