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.http.impl.client.cache;
28
29 import java.util.Date;
30 import java.util.HashMap;
31 import java.util.Map;
32
33 import org.apache.http.Header;
34 import org.apache.http.HeaderElement;
35 import org.apache.http.HttpRequest;
36 import org.apache.http.HttpVersion;
37 import org.apache.http.ProtocolException;
38 import org.apache.http.client.cache.HeaderConstants;
39 import org.apache.http.client.cache.HttpCacheEntry;
40 import org.apache.http.client.methods.HttpRequestWrapper;
41 import org.apache.http.client.utils.DateUtils;
42 import org.apache.http.message.BasicHeader;
43 import org.apache.http.message.BasicHttpRequest;
44 import org.junit.Assert;
45 import org.junit.Before;
46 import org.junit.Test;
47
48 public class TestConditionalRequestBuilder {
49
50 private ConditionalRequestBuilder impl;
51 private HttpRequestWrapper request;
52 private HttpCacheEntry entry;
53
54 @Before
55 public void setUp() throws Exception {
56 impl = new ConditionalRequestBuilder();
57 request = HttpRequestWrapper.wrap(
58 new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1));
59 entry = HttpTestUtils.makeCacheEntry();
60 }
61
62 @Test
63 public void testBuildConditionalRequestWithLastModified() throws ProtocolException {
64 final String theMethod = "GET";
65 final String theUri = "/theuri";
66 final String lastModified = "this is my last modified date";
67
68 final HttpRequest basicRequest = new BasicHttpRequest(theMethod, theUri);
69 basicRequest.addHeader("Accept-Encoding", "gzip");
70 final HttpRequestWrapper requestWrapper = HttpRequestWrapper.wrap(basicRequest);
71
72 final Header[] headers = new Header[] {
73 new BasicHeader("Date", DateUtils.formatDate(new Date())),
74 new BasicHeader("Last-Modified", lastModified) };
75
76 final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(headers);
77 final HttpRequestWrapper newRequest = impl.buildConditionalRequest(requestWrapper, cacheEntry);
78
79 Assert.assertNotSame(basicRequest, newRequest);
80
81 Assert.assertEquals(theMethod, newRequest.getRequestLine().getMethod());
82 Assert.assertEquals(theUri, newRequest.getRequestLine().getUri());
83 Assert.assertEquals(basicRequest.getRequestLine().getProtocolVersion(), newRequest
84 .getRequestLine().getProtocolVersion());
85 Assert.assertEquals(2, newRequest.getAllHeaders().length);
86
87 Assert.assertEquals("Accept-Encoding", newRequest.getAllHeaders()[0].getName());
88 Assert.assertEquals("gzip", newRequest.getAllHeaders()[0].getValue());
89
90 Assert.assertEquals("If-Modified-Since", newRequest.getAllHeaders()[1].getName());
91 Assert.assertEquals(lastModified, newRequest.getAllHeaders()[1].getValue());
92 }
93
94 @Test
95 public void testConditionalRequestForEntryWithLastModifiedAndEtagIncludesBothAsValidators()
96 throws Exception {
97 final Date now = new Date();
98 final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
99 final Date twentySecondsAgo = new Date(now.getTime() - 20 * 1000L);
100 final String lmDate = DateUtils.formatDate(twentySecondsAgo);
101 final String etag = "\"etag\"";
102 final Header[] headers = {
103 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
104 new BasicHeader("Last-Modified", lmDate),
105 new BasicHeader("ETag", etag)
106 };
107 final HttpRequest basicRequest = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
108 final HttpRequestWrapper requestWrapper = HttpRequestWrapper.wrap(basicRequest);
109 final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(headers);
110 final HttpRequest result = impl.buildConditionalRequest(requestWrapper, cacheEntry);
111 Assert.assertEquals(lmDate,
112 result.getFirstHeader("If-Modified-Since").getValue());
113 Assert.assertEquals(etag,
114 result.getFirstHeader("If-None-Match").getValue());
115 }
116
117 @Test
118 public void testBuildConditionalRequestWithETag() throws ProtocolException {
119 final String theMethod = "GET";
120 final String theUri = "/theuri";
121 final String theETag = "this is my eTag";
122
123 final HttpRequest basicRequest = new BasicHttpRequest(theMethod, theUri);
124 basicRequest.addHeader("Accept-Encoding", "gzip");
125 final HttpRequestWrapper requestWrapper = HttpRequestWrapper.wrap(basicRequest);
126
127 final Header[] headers = new Header[] {
128 new BasicHeader("Date", DateUtils.formatDate(new Date())),
129 new BasicHeader("Last-Modified", DateUtils.formatDate(new Date())),
130 new BasicHeader("ETag", theETag) };
131
132 final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(headers);
133
134 final HttpRequest newRequest = impl.buildConditionalRequest(requestWrapper, cacheEntry);
135
136 Assert.assertNotSame(basicRequest, newRequest);
137
138 Assert.assertEquals(theMethod, newRequest.getRequestLine().getMethod());
139 Assert.assertEquals(theUri, newRequest.getRequestLine().getUri());
140 Assert.assertEquals(basicRequest.getRequestLine().getProtocolVersion(), newRequest
141 .getRequestLine().getProtocolVersion());
142
143 Assert.assertEquals(3, newRequest.getAllHeaders().length);
144
145 Assert.assertEquals("Accept-Encoding", newRequest.getAllHeaders()[0].getName());
146 Assert.assertEquals("gzip", newRequest.getAllHeaders()[0].getValue());
147
148 Assert.assertEquals("If-None-Match", newRequest.getAllHeaders()[1].getName());
149 Assert.assertEquals(theETag, newRequest.getAllHeaders()[1].getValue());
150 }
151
152 @Test
153 public void testCacheEntryWithMustRevalidateDoesEndToEndRevalidation() throws Exception {
154 final HttpRequest basicRequest = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
155 final HttpRequestWrapper requestWrapper = HttpRequestWrapper.wrap(basicRequest);
156 final Date now = new Date();
157 final Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L);
158 final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
159 final Date nineSecondsAgo = new Date(now.getTime() - 9 * 1000L);
160
161 final Header[] cacheEntryHeaders = new Header[] {
162 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
163 new BasicHeader("ETag", "\"etag\""),
164 new BasicHeader("Cache-Control","max-age=5, must-revalidate") };
165 final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(elevenSecondsAgo, nineSecondsAgo, cacheEntryHeaders);
166
167 final HttpRequest result = impl.buildConditionalRequest(requestWrapper, cacheEntry);
168
169 boolean foundMaxAge0 = false;
170 for(final Header h : result.getHeaders("Cache-Control")) {
171 for(final HeaderElement elt : h.getElements()) {
172 if ("max-age".equalsIgnoreCase(elt.getName())
173 && "0".equals(elt.getValue())) {
174 foundMaxAge0 = true;
175 }
176 }
177 }
178 Assert.assertTrue(foundMaxAge0);
179 }
180
181 @Test
182 public void testCacheEntryWithProxyRevalidateDoesEndToEndRevalidation() throws Exception {
183 final HttpRequest basicRequest = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
184 final HttpRequestWrapper requestWrapper = HttpRequestWrapper.wrap(basicRequest);
185 final Date now = new Date();
186 final Date elevenSecondsAgo = new Date(now.getTime() - 11 * 1000L);
187 final Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
188 final Date nineSecondsAgo = new Date(now.getTime() - 9 * 1000L);
189
190 final Header[] cacheEntryHeaders = new Header[] {
191 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
192 new BasicHeader("ETag", "\"etag\""),
193 new BasicHeader("Cache-Control","max-age=5, proxy-revalidate") };
194 final HttpCacheEntry cacheEntry = HttpTestUtils.makeCacheEntry(elevenSecondsAgo, nineSecondsAgo, cacheEntryHeaders);
195
196 final HttpRequest result = impl.buildConditionalRequest(requestWrapper, cacheEntry);
197
198 boolean foundMaxAge0 = false;
199 for(final Header h : result.getHeaders("Cache-Control")) {
200 for(final HeaderElement elt : h.getElements()) {
201 if ("max-age".equalsIgnoreCase(elt.getName())
202 && "0".equals(elt.getValue())) {
203 foundMaxAge0 = true;
204 }
205 }
206 }
207 Assert.assertTrue(foundMaxAge0);
208 }
209
210 @Test
211 public void testBuildUnconditionalRequestUsesGETMethod()
212 throws Exception {
213 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
214 Assert.assertEquals("GET", result.getRequestLine().getMethod());
215 }
216
217 @Test
218 public void testBuildUnconditionalRequestUsesRequestUri()
219 throws Exception {
220 final String uri = "/theURI";
221 request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", uri, HttpVersion.HTTP_1_1));
222 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
223 Assert.assertEquals(uri, result.getRequestLine().getUri());
224 }
225
226 @Test
227 public void testBuildUnconditionalRequestUsesHTTP_1_1()
228 throws Exception {
229 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
230 Assert.assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion());
231 }
232
233 @Test
234 public void testBuildUnconditionalRequestAddsCacheControlNoCache()
235 throws Exception {
236 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
237 boolean ccNoCacheFound = false;
238 for(final Header h : result.getHeaders("Cache-Control")) {
239 for(final HeaderElement elt : h.getElements()) {
240 if ("no-cache".equals(elt.getName())) {
241 ccNoCacheFound = true;
242 }
243 }
244 }
245 Assert.assertTrue(ccNoCacheFound);
246 }
247
248 @Test
249 public void testBuildUnconditionalRequestAddsPragmaNoCache()
250 throws Exception {
251 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
252 boolean ccNoCacheFound = false;
253 for(final Header h : result.getHeaders("Pragma")) {
254 for(final HeaderElement elt : h.getElements()) {
255 if ("no-cache".equals(elt.getName())) {
256 ccNoCacheFound = true;
257 }
258 }
259 }
260 Assert.assertTrue(ccNoCacheFound);
261 }
262
263 @Test
264 public void testBuildUnconditionalRequestDoesNotUseIfRange()
265 throws Exception {
266 request.addHeader("If-Range","\"etag\"");
267 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
268 Assert.assertNull(result.getFirstHeader("If-Range"));
269 }
270
271 @Test
272 public void testBuildUnconditionalRequestDoesNotUseIfMatch()
273 throws Exception {
274 request.addHeader("If-Match","\"etag\"");
275 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
276 Assert.assertNull(result.getFirstHeader("If-Match"));
277 }
278
279 @Test
280 public void testBuildUnconditionalRequestDoesNotUseIfNoneMatch()
281 throws Exception {
282 request.addHeader("If-None-Match","\"etag\"");
283 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
284 Assert.assertNull(result.getFirstHeader("If-None-Match"));
285 }
286
287 @Test
288 public void testBuildUnconditionalRequestDoesNotUseIfUnmodifiedSince()
289 throws Exception {
290 request.addHeader("If-Unmodified-Since", DateUtils.formatDate(new Date()));
291 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
292 Assert.assertNull(result.getFirstHeader("If-Unmodified-Since"));
293 }
294
295 @Test
296 public void testBuildUnconditionalRequestDoesNotUseIfModifiedSince()
297 throws Exception {
298 request.addHeader("If-Modified-Since", DateUtils.formatDate(new Date()));
299 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
300 Assert.assertNull(result.getFirstHeader("If-Modified-Since"));
301 }
302
303 @Test
304 public void testBuildUnconditionalRequestCarriesOtherRequestHeaders()
305 throws Exception {
306 request.addHeader("User-Agent","MyBrowser/1.0");
307 final HttpRequest result = impl.buildUnconditionalRequest(request, entry);
308 Assert.assertEquals("MyBrowser/1.0",
309 result.getFirstHeader("User-Agent").getValue());
310 }
311
312 @Test
313 public void testBuildConditionalRequestFromVariants() throws Exception {
314 final String etag1 = "\"123\"";
315 final String etag2 = "\"456\"";
316 final String etag3 = "\"789\"";
317
318 final Map<String,Variant> variantEntries = new HashMap<String,Variant>();
319 variantEntries.put(etag1, new Variant("A","B",HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag1) })));
320 variantEntries.put(etag2, new Variant("C","D",HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag2) })));
321 variantEntries.put(etag3, new Variant("E","F",HttpTestUtils.makeCacheEntry(new Header[] { new BasicHeader("ETag", etag3) })));
322
323 final HttpRequest conditional = impl.buildConditionalRequestFromVariants(request, variantEntries);
324
325
326 String ifNoneMatch = conditional.getFirstHeader(HeaderConstants.IF_NONE_MATCH).getValue();
327 Assert.assertTrue(ifNoneMatch.contains(etag1));
328 Assert.assertTrue(ifNoneMatch.contains(etag2));
329 Assert.assertTrue(ifNoneMatch.contains(etag3));
330 ifNoneMatch = ifNoneMatch.replace(etag1, "");
331 ifNoneMatch = ifNoneMatch.replace(etag2, "");
332 ifNoneMatch = ifNoneMatch.replace(etag3, "");
333 ifNoneMatch = ifNoneMatch.replace(",","");
334 ifNoneMatch = ifNoneMatch.replace(" ", "");
335 Assert.assertEquals(ifNoneMatch, "");
336 }
337
338 }