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.io.UnsupportedEncodingException;
30 import java.net.URI;
31 import java.net.URISyntaxException;
32 import java.net.URLEncoder;
33 import java.nio.charset.StandardCharsets;
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.Iterator;
37 import java.util.List;
38
39 import org.apache.hc.client5.http.cache.HeaderConstants;
40 import org.apache.hc.client5.http.cache.HttpCacheEntry;
41 import org.apache.hc.core5.annotation.Contract;
42 import org.apache.hc.core5.annotation.ThreadingBehavior;
43 import org.apache.hc.core5.function.Resolver;
44 import org.apache.hc.core5.http.Header;
45 import org.apache.hc.core5.http.HeaderElement;
46 import org.apache.hc.core5.http.HttpHost;
47 import org.apache.hc.core5.http.HttpRequest;
48 import org.apache.hc.core5.http.message.MessageSupport;
49
50
51
52
53 @Contract(threading = ThreadingBehavior.STATELESS)
54 public class CacheKeyGenerator implements Resolver<URI, String> {
55
56 public static final CacheKeyGenerator INSTANCE = new CacheKeyGenerator();
57
58 @Override
59 public String resolve(final URI uri) {
60 return generateKey(uri);
61 }
62
63
64
65
66
67
68
69
70
71 public String generateKey(final URI requestUri) {
72 try {
73 final URI normalizeRequestUri = HttpCacheSupport.normalize(requestUri);
74 return normalizeRequestUri.toASCIIString();
75 } catch (final URISyntaxException ex) {
76 return requestUri.toASCIIString();
77 }
78 }
79
80
81
82
83
84
85
86
87
88 public String generateKey(final HttpHost host, final HttpRequest request) {
89 final String s = HttpCacheSupport.getRequestUri(request, host);
90 try {
91 return generateKey(new URI(s));
92 } catch (final URISyntaxException ex) {
93 return s;
94 }
95 }
96
97 private String getFullHeaderValue(final Header[] headers) {
98 if (headers == null) {
99 return "";
100 }
101 final StringBuilder buf = new StringBuilder();
102 for (int i = 0; i < headers.length; i++) {
103 final Header hdr = headers[i];
104 if (i > 0) {
105 buf.append(", ");
106 }
107 buf.append(hdr.getValue().trim());
108 }
109 return buf.toString();
110 }
111
112
113
114
115
116
117
118
119
120
121
122 public String generateKey(final HttpHost host, final HttpRequest request, final HttpCacheEntry entry) {
123 if (!entry.hasVariants()) {
124 return generateKey(host, request);
125 }
126 return generateVariantKey(request, entry) + generateKey(host, request);
127 }
128
129
130
131
132
133
134
135
136
137
138 public String generateVariantKey(final HttpRequest req, final HttpCacheEntry entry) {
139 final List<String> variantHeaderNames = new ArrayList<>();
140 final Iterator<HeaderElement> it = MessageSupport.iterate(entry, HeaderConstants.VARY);
141 while (it.hasNext()) {
142 final HeaderElement elt = it.next();
143 variantHeaderNames.add(elt.getName());
144 }
145 Collections.sort(variantHeaderNames);
146
147 final StringBuilder buf;
148 try {
149 buf = new StringBuilder("{");
150 boolean first = true;
151 for (final String headerName : variantHeaderNames) {
152 if (!first) {
153 buf.append("&");
154 }
155 buf.append(URLEncoder.encode(headerName, StandardCharsets.UTF_8.name()));
156 buf.append("=");
157 buf.append(URLEncoder.encode(getFullHeaderValue(req.getHeaders(headerName)),
158 StandardCharsets.UTF_8.name()));
159 first = false;
160 }
161 buf.append("}");
162 } catch (final UnsupportedEncodingException uee) {
163 throw new RuntimeException("couldn't encode to UTF-8", uee);
164 }
165 return buf.toString();
166 }
167
168 }