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 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.Map;
33
34 import org.apache.hc.client5.http.cache.HeaderConstants;
35 import org.apache.hc.client5.http.cache.HttpCacheEntry;
36 import org.apache.hc.client5.http.cache.Resource;
37 import org.apache.hc.client5.http.cache.ResourceFactory;
38 import org.apache.hc.client5.http.cache.ResourceIOException;
39 import org.apache.hc.core5.http.Header;
40 import org.apache.hc.core5.http.HttpHeaders;
41 import org.apache.hc.core5.http.HttpRequest;
42 import org.apache.hc.core5.http.HttpResponse;
43 import org.apache.hc.core5.http.HttpStatus;
44 import org.apache.hc.core5.http.message.HeaderGroup;
45 import org.apache.hc.core5.util.Args;
46 import org.apache.hc.core5.util.ByteArrayBuffer;
47
48
49
50
51
52 class CacheUpdateHandler {
53
54 private final ResourceFactory resourceFactory;
55
56 CacheUpdateHandler() {
57 this(new HeapResourceFactory());
58 }
59
60 CacheUpdateHandler(final ResourceFactory resourceFactory) {
61 super();
62 this.resourceFactory = resourceFactory;
63 }
64
65
66
67
68 public HttpCacheEntry createCacheEntry(
69 final HttpRequest request,
70 final HttpResponse originResponse,
71 final ByteArrayBuffer content,
72 final Instant requestSent,
73 final Instant responseReceived) throws ResourceIOException {
74 return new HttpCacheEntry(
75 requestSent,
76 responseReceived,
77 originResponse.getCode(),
78 originResponse.getHeaders(),
79 content != null ? resourceFactory.generate(request.getRequestUri(), content.array(), 0, content.length()) : null);
80 }
81
82
83
84
85
86 public HttpCacheEntry updateCacheEntry(
87 final String requestId,
88 final HttpCacheEntry entry,
89 final Instant requestDate,
90 final Instant responseDate,
91 final HttpResponse response) throws ResourceIOException {
92 Args.check(response.getCode() == HttpStatus.SC_NOT_MODIFIED,
93 "Response must have 304 status code");
94 final Header[] mergedHeaders = mergeHeaders(entry, response);
95 Resource resource = null;
96 if (entry.getResource() != null) {
97 resource = resourceFactory.copy(requestId, entry.getResource());
98 }
99 return new HttpCacheEntry(
100 requestDate,
101 responseDate,
102 entry.getStatus(),
103 mergedHeaders,
104 resource);
105 }
106 @SuppressWarnings("deprecation")
107 public HttpCacheEntry updateParentCacheEntry(
108 final String requestId,
109 final HttpCacheEntry existing,
110 final HttpCacheEntry entry,
111 final String variantKey,
112 final String variantCacheKey) throws ResourceIOException {
113 HttpCacheEntry src = existing;
114 if (src == null) {
115 src = entry;
116 }
117
118 Resource resource = null;
119 if (src.getResource() != null) {
120 resource = resourceFactory.copy(requestId, src.getResource());
121 }
122 final Map<String,String> variantMap = new HashMap<>(src.getVariantMap());
123 variantMap.put(variantKey, variantCacheKey);
124 return new HttpCacheEntry(
125 src.getRequestInstant(),
126 src.getResponseInstant(),
127 src.getStatus(),
128 src.getHeaders(),
129 resource,
130 variantMap);
131 }
132
133 private Header[] mergeHeaders(final HttpCacheEntry entry, final HttpResponse response) {
134 if (DateSupport.isAfter(entry, response, HttpHeaders.DATE)) {
135 return entry.getHeaders();
136 }
137 final HeaderGroup headerGroup = new HeaderGroup();
138 headerGroup.setHeaders(entry.getHeaders());
139
140 for (final Iterator<Header> it = response.headerIterator(); it.hasNext(); ) {
141 final Header responseHeader = it.next();
142
143 if (HttpHeaders.CONTENT_ENCODING.equals(responseHeader.getName())
144 || HttpHeaders.CONTENT_LENGTH.equals(responseHeader.getName())) {
145 continue;
146 }
147 headerGroup.removeHeaders(responseHeader.getName());
148 }
149
150 for (final Iterator<Header> it = headerGroup.headerIterator(); it.hasNext(); ) {
151 final Header cacheHeader = it.next();
152 if (HeaderConstants.WARNING.equalsIgnoreCase(cacheHeader.getName())) {
153 final String warningValue = cacheHeader.getValue();
154 if (warningValue != null && warningValue.startsWith("1")) {
155 it.remove();
156 }
157 }
158 }
159 for (final Iterator<Header> it = response.headerIterator(); it.hasNext(); ) {
160 final Header responseHeader = it.next();
161
162 if (HttpHeaders.CONTENT_ENCODING.equals(responseHeader.getName())
163 || HttpHeaders.CONTENT_LENGTH.equals(responseHeader.getName())) {
164 continue;
165 }
166 headerGroup.addHeader(responseHeader);
167 }
168 return headerGroup.getHeaders();
169 }
170
171 }