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