-
Notifications
You must be signed in to change notification settings - Fork 10
/
AcceptEncoding.java
75 lines (60 loc) · 2.43 KB
/
AcceptEncoding.java
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package com.vtence.molecule.http;
import com.vtence.molecule.Request;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import static com.vtence.molecule.http.HeaderNames.ACCEPT_ENCODING;
import static java.util.stream.Collectors.toList;
public class AcceptEncoding {
private final List<Header.Value> values = new ArrayList<>();
public static AcceptEncoding of(Request request) {
String header = request.header(ACCEPT_ENCODING);
return parse(header != null ? header : "");
}
public static AcceptEncoding parse(String header) {
return from(new Header(header));
}
public static AcceptEncoding from(Header header) {
var accept = new AcceptEncoding();
accept.values.addAll(header.all());
return accept;
}
public String selectBestEncoding(String... candidates) {
return selectBestEncoding(Arrays.asList(candidates));
}
public String selectBestEncoding(Collection<String> candidates) {
List<Header.Value> contentCodings = explicitContentCodings(candidates);
List<String> acceptableEncodings = filterAcceptable(contentCodings);
for (String acceptable : acceptableEncodings) {
if (candidates.contains(acceptable)) return acceptable;
}
return null;
}
private List<Header.Value> explicitContentCodings(Collection<String> availableEncodings) {
var codings = new ArrayList<Header.Value>();
for (Header.Value accept: values) {
if (accept.is("*")) {
List<String> others = new ArrayList<>(availableEncodings);
others.removeAll(listValues(values));
for (String other : others) {
codings.add(new Header.Value(other, accept.parameters()));
}
} else {
codings.add(accept);
}
}
return codings;
}
private List<String> filterAcceptable(List<Header.Value> encodings) {
List<String> candidates = listValues(encodings);
if (!candidates.contains("identity")) candidates.add("identity");
for (var encoding : encodings) {
if (!encoding.acceptable()) candidates.remove(encoding.value());
}
return candidates;
}
private List<String> listValues(List<Header.Value> entries) {
return entries.stream().map(Header.Value::value).collect(toList());
}
}