1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.client5.http.impl.cache;
28
29 import java.io.IOException;
30 import java.net.SocketTimeoutException;
31 import java.time.Instant;
32
33 import org.apache.hc.client5.http.HttpRoute;
34 import org.apache.hc.client5.http.classic.ExecChain;
35 import org.apache.hc.client5.http.classic.ExecRuntime;
36 import org.apache.hc.client5.http.protocol.HttpClientContext;
37 import org.apache.hc.client5.http.utils.DateUtils;
38 import org.apache.hc.core5.http.ClassicHttpRequest;
39 import org.apache.hc.core5.http.ClassicHttpResponse;
40 import org.apache.hc.core5.http.HttpException;
41 import org.apache.hc.core5.http.HttpHost;
42 import org.apache.hc.core5.http.HttpResponse;
43 import org.apache.hc.core5.http.HttpStatus;
44 import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
45 import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
46 import org.junit.jupiter.api.Assertions;
47 import org.junit.jupiter.api.BeforeEach;
48 import org.junit.jupiter.api.Test;
49 import org.mockito.Mock;
50 import org.mockito.Mockito;
51 import org.mockito.MockitoAnnotations;
52
53
54
55
56
57 public class TestProtocolAllowedBehavior {
58
59 static final int MAX_BYTES = 1024;
60 static final int MAX_ENTRIES = 100;
61 static final int ENTITY_LENGTH = 128;
62
63 HttpHost host;
64 HttpRoute route;
65 HttpClientContext context;
66 @Mock
67 ExecChain mockExecChain;
68 @Mock
69 ExecRuntime mockExecRuntime;
70 @Mock
71 HttpCache mockCache;
72 ClassicHttpRequest request;
73 ClassicHttpResponse originResponse;
74 CacheConfig config;
75 CachingExec impl;
76 HttpCache cache;
77
78 @BeforeEach
79 public void setUp() throws Exception {
80 MockitoAnnotations.openMocks(this);
81 host = new HttpHost("foo.example.com", 80);
82
83 route = new HttpRoute(host);
84
85 request = new BasicClassicHttpRequest("GET", "/foo");
86
87 context = HttpClientContext.create();
88
89 originResponse = HttpTestUtils.make200Response();
90
91 config = CacheConfig.custom()
92 .setMaxCacheEntries(MAX_ENTRIES)
93 .setMaxObjectSize(MAX_BYTES)
94 .setSharedCache(false)
95 .build();
96
97 cache = new BasicHttpCache(config);
98 impl = new CachingExec(cache, null, config);
99
100 Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse);
101 }
102
103 public ClassicHttpResponse execute(final ClassicHttpRequest request) throws IOException, HttpException {
104 return impl.execute(
105 ClassicRequestBuilder.copy(request).build(),
106 new ExecChain.Scope("test", route, request, mockExecRuntime, context),
107 mockExecChain);
108 }
109
110 @Test
111 public void testNonSharedCacheReturnsStaleResponseWhenRevalidationFailsForProxyRevalidate() throws Exception {
112 final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET","/");
113 final Instant now = Instant.now();
114 final Instant tenSecondsAgo = now.minusSeconds(10);
115 originResponse.setHeader("Date", DateUtils.formatStandardDate(tenSecondsAgo));
116 originResponse.setHeader("Cache-Control","max-age=5,proxy-revalidate");
117 originResponse.setHeader("Etag","\"etag\"");
118
119 final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET","/");
120
121 Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse);
122
123 execute(req1);
124
125 Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenThrow(new SocketTimeoutException());
126
127 final HttpResponse result = execute(req2);
128 Assertions.assertEquals(HttpStatus.SC_OK, result.getCode());
129
130 Mockito.verifyNoInteractions(mockCache);
131 }
132
133 @Test
134 public void testNonSharedCacheMayCacheResponsesWithCacheControlPrivate() throws Exception {
135 final ClassicHttpRequest req1 = new BasicClassicHttpRequest("GET","/");
136 originResponse.setHeader("Cache-Control","private,max-age=3600");
137
138 final ClassicHttpRequest req2 = new BasicClassicHttpRequest("GET","/");
139
140 Mockito.when(mockExecChain.proceed(Mockito.any(), Mockito.any())).thenReturn(originResponse);
141
142 execute(req1);
143 final HttpResponse result = execute(req2);
144 Assertions.assertEquals(HttpStatus.SC_OK, result.getCode());
145
146 Mockito.verifyNoInteractions(mockCache);
147 }
148 }