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.time.Instant;
30
31 import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
32 import org.apache.hc.client5.http.cache.HttpCacheEntry;
33 import org.apache.hc.client5.http.cache.Resource;
34 import org.apache.hc.client5.http.cache.ResourceIOException;
35 import org.apache.hc.client5.http.utils.DateUtils;
36 import org.apache.hc.core5.http.ContentType;
37 import org.apache.hc.core5.http.Header;
38 import org.apache.hc.core5.http.HttpHeaders;
39 import org.apache.hc.core5.http.HttpRequest;
40 import org.apache.hc.core5.http.HttpResponse;
41 import org.apache.hc.core5.http.HttpStatus;
42 import org.apache.hc.core5.http.Method;
43 import org.apache.hc.core5.http.message.BasicHeader;
44 import org.apache.hc.core5.util.TimeValue;
45
46
47
48
49 class CachedHttpResponseGenerator {
50
51 private final CacheValidityPolicy validityStrategy;
52
53 CachedHttpResponseGenerator(final CacheValidityPolicy validityStrategy) {
54 super();
55 this.validityStrategy = validityStrategy;
56 }
57
58
59
60
61
62
63
64
65 SimpleHttpResponse generateResponse(final HttpRequest request, final HttpCacheEntry entry) throws ResourceIOException {
66 final Instant now = Instant.now();
67 final SimpleHttpResponse response = new SimpleHttpResponse(entry.getStatus());
68
69 response.setHeaders(entry.getHeaders());
70
71 if (responseShouldContainEntity(request, entry)) {
72 final Resource resource = entry.getResource();
73 final Header h = entry.getFirstHeader(HttpHeaders.CONTENT_TYPE);
74 final ContentType contentType = h != null ? ContentType.parse(h.getValue()) : null;
75 final byte[] content = resource.get();
76 generateContentLength(response, content);
77 response.setBody(content, contentType);
78 }
79
80 final TimeValue age = this.validityStrategy.getCurrentAge(entry, now);
81 if (TimeValue.isPositive(age)) {
82 if (age.compareTo(CacheSupport.MAX_AGE) >= 0) {
83 response.setHeader(HttpHeaders.AGE, Long.toString(CacheSupport.MAX_AGE.toSeconds()));
84 } else {
85 response.setHeader(HttpHeaders.AGE, Long.toString(age.toSeconds()));
86 }
87 }
88
89 return response;
90 }
91
92
93
94
95
96 SimpleHttpResponse generateNotModifiedResponse(final HttpCacheEntry entry) {
97
98 final SimpleHttpResponse response = new SimpleHttpResponse(HttpStatus.SC_NOT_MODIFIED, "Not Modified");
99
100
101
102
103 Header dateHeader = entry.getFirstHeader(HttpHeaders.DATE);
104 if (dateHeader == null) {
105 dateHeader = new BasicHeader(HttpHeaders.DATE, DateUtils.formatStandardDate(Instant.now()));
106 }
107 response.addHeader(dateHeader);
108
109
110
111 final Header etagHeader = entry.getFirstHeader(HttpHeaders.ETAG);
112 if (etagHeader != null) {
113 response.addHeader(etagHeader);
114 }
115
116 final Header contentLocationHeader = entry.getFirstHeader(HttpHeaders.CONTENT_LOCATION);
117 if (contentLocationHeader != null) {
118 response.addHeader(contentLocationHeader);
119 }
120
121
122
123
124 final Header expiresHeader = entry.getFirstHeader(HttpHeaders.EXPIRES);
125 if (expiresHeader != null) {
126 response.addHeader(expiresHeader);
127 }
128
129 final Header cacheControlHeader = entry.getFirstHeader(HttpHeaders.CACHE_CONTROL);
130 if (cacheControlHeader != null) {
131 response.addHeader(cacheControlHeader);
132 }
133
134 final Header varyHeader = entry.getFirstHeader(HttpHeaders.VARY);
135 if (varyHeader != null) {
136 response.addHeader(varyHeader);
137 }
138
139
140
141
142
143
144
145 if (etagHeader == null) {
146 final Header lastModifiedHeader = entry.getFirstHeader(HttpHeaders.LAST_MODIFIED);
147 if (lastModifiedHeader != null) {
148 response.addHeader(lastModifiedHeader);
149 }
150 }
151 return response;
152 }
153
154 private void generateContentLength(final HttpResponse response, final byte[] body) {
155 response.removeHeaders(HttpHeaders.TRANSFER_ENCODING);
156 response.setHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(body.length));
157 }
158
159 private boolean responseShouldContainEntity(final HttpRequest request, final HttpCacheEntry cacheEntry) {
160 return Method.GET.isSame(request.getMethod()) && cacheEntry.getResource() != null;
161 }
162
163 }