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
31 import org.apache.http.Header;
32 import org.apache.http.HttpEntity;
33 import org.apache.http.HttpResponse;
34 import org.apache.http.HttpStatus;
35 import org.apache.http.HttpVersion;
36 import org.apache.http.annotation.Contract;
37 import org.apache.http.annotation.ThreadingBehavior;
38 import org.apache.http.client.cache.HeaderConstants;
39 import org.apache.http.client.cache.HttpCacheEntry;
40 import org.apache.http.client.methods.CloseableHttpResponse;
41 import org.apache.http.client.methods.HttpRequestWrapper;
42 import org.apache.http.client.utils.DateUtils;
43 import org.apache.http.message.BasicHeader;
44 import org.apache.http.message.BasicHttpResponse;
45 import org.apache.http.protocol.HTTP;
46
47
48
49
50
51
52 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
53 class CachedHttpResponseGenerator {
54
55 private final CacheValidityPolicy validityStrategy;
56
57 CachedHttpResponseGenerator(final CacheValidityPolicy validityStrategy) {
58 super();
59 this.validityStrategy = validityStrategy;
60 }
61
62 CachedHttpResponseGenerator() {
63 this(new CacheValidityPolicy());
64 }
65
66
67
68
69
70
71
72
73 CloseableHttpResponse generateResponse(final HttpRequestWrapper request, final HttpCacheEntry entry) {
74 final Date now = new Date();
75 final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, entry
76 .getStatusCode(), entry.getReasonPhrase());
77
78 response.setHeaders(entry.getAllHeaders());
79
80 if (responseShouldContainEntity(request, entry)) {
81 final HttpEntity entity = new CacheEntity(entry);
82 addMissingContentLengthHeader(response, entity);
83 response.setEntity(entity);
84 }
85
86 final long age = this.validityStrategy.getCurrentAgeSecs(entry, now);
87 if (age > 0) {
88 if (age >= Integer.MAX_VALUE) {
89 response.setHeader(HeaderConstants.AGE, "2147483648");
90 } else {
91 response.setHeader(HeaderConstants.AGE, "" + ((int) age));
92 }
93 }
94
95 return Proxies.enhanceResponse(response);
96 }
97
98
99
100
101
102 CloseableHttpResponse generateNotModifiedResponse(final HttpCacheEntry entry) {
103
104 final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
105 HttpStatus.SC_NOT_MODIFIED, "Not Modified");
106
107
108
109
110
111 Header dateHeader = entry.getFirstHeader(HTTP.DATE_HEADER);
112 if (dateHeader == null) {
113 dateHeader = new BasicHeader(HTTP.DATE_HEADER, DateUtils.formatDate(new Date()));
114 }
115 response.addHeader(dateHeader);
116
117
118
119 final Header etagHeader = entry.getFirstHeader(HeaderConstants.ETAG);
120 if (etagHeader != null) {
121 response.addHeader(etagHeader);
122 }
123
124 final Header contentLocationHeader = entry.getFirstHeader("Content-Location");
125 if (contentLocationHeader != null) {
126 response.addHeader(contentLocationHeader);
127 }
128
129
130
131
132 final Header expiresHeader = entry.getFirstHeader(HeaderConstants.EXPIRES);
133 if (expiresHeader != null) {
134 response.addHeader(expiresHeader);
135 }
136
137 final Header cacheControlHeader = entry.getFirstHeader(HeaderConstants.CACHE_CONTROL);
138 if (cacheControlHeader != null) {
139 response.addHeader(cacheControlHeader);
140 }
141
142 final Header varyHeader = entry.getFirstHeader(HeaderConstants.VARY);
143 if (varyHeader != null) {
144 response.addHeader(varyHeader);
145 }
146
147 return Proxies.enhanceResponse(response);
148 }
149
150 private void addMissingContentLengthHeader(final HttpResponse response, final HttpEntity entity) {
151 if (transferEncodingIsPresent(response)) {
152 return;
153 }
154
155
156 final Header contentLength = new BasicHeader(HTTP.CONTENT_LEN, Long.toString(entity.getContentLength()));
157 response.setHeader(contentLength);
158 }
159
160 private boolean transferEncodingIsPresent(final HttpResponse response) {
161 final Header hdr = response.getFirstHeader(HTTP.TRANSFER_ENCODING);
162 return hdr != null;
163 }
164
165 private boolean responseShouldContainEntity(final HttpRequestWrapper request, final HttpCacheEntry cacheEntry) {
166 return request.getRequestLine().getMethod().equals(HeaderConstants.GET_METHOD) &&
167 cacheEntry.getResource() != null;
168 }
169
170 }