1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http.cookie;
17
18 import static io.netty.handler.codec.http.cookie.CookieUtil.add;
19 import static io.netty.handler.codec.http.cookie.CookieUtil.addQuoted;
20 import static io.netty.handler.codec.http.cookie.CookieUtil.stringBuilder;
21 import static io.netty.handler.codec.http.cookie.CookieUtil.stripTrailingSeparator;
22 import static io.netty.util.internal.ObjectUtil.checkNotNull;
23
24 import io.netty.handler.codec.http.HttpHeaderDateFormat;
25 import io.netty.handler.codec.http.HttpResponse;
26
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.Date;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public final class ServerCookieEncoder extends CookieEncoder {
53
54
55
56
57
58
59
60 public static final ServerCookieEncoder STRICT = new ServerCookieEncoder(true);
61
62
63
64
65
66 public static final ServerCookieEncoder LAX = new ServerCookieEncoder(false);
67
68 private ServerCookieEncoder(boolean strict) {
69 super(strict);
70 }
71
72
73
74
75
76
77
78
79 public String encode(String name, String value) {
80 return encode(new DefaultCookie(name, value));
81 }
82
83
84
85
86
87
88
89 public String encode(Cookie cookie) {
90 final String name = checkNotNull(cookie, "cookie").name();
91 final String value = cookie.value() != null ? cookie.value() : "";
92
93 validateCookie(name, value);
94
95 StringBuilder buf = stringBuilder();
96
97 if (cookie.wrap()) {
98 addQuoted(buf, name, value);
99 } else {
100 add(buf, name, value);
101 }
102
103 if (cookie.maxAge() != Long.MIN_VALUE) {
104 add(buf, CookieHeaderNames.MAX_AGE, cookie.maxAge());
105 Date expires = new Date(cookie.maxAge() * 1000 + System.currentTimeMillis());
106 add(buf, CookieHeaderNames.EXPIRES, HttpHeaderDateFormat.get().format(expires));
107 }
108
109 if (cookie.path() != null) {
110 add(buf, CookieHeaderNames.PATH, cookie.path());
111 }
112
113 if (cookie.domain() != null) {
114 add(buf, CookieHeaderNames.DOMAIN, cookie.domain());
115 }
116 if (cookie.isSecure()) {
117 add(buf, CookieHeaderNames.SECURE);
118 }
119 if (cookie.isHttpOnly()) {
120 add(buf, CookieHeaderNames.HTTPONLY);
121 }
122
123 return stripTrailingSeparator(buf);
124 }
125
126
127
128
129
130
131
132 private static List<String> dedup(List<String> encoded, Map<String, Integer> nameToLastIndex) {
133 boolean[] isLastInstance = new boolean[encoded.size()];
134 for (int idx : nameToLastIndex.values()) {
135 isLastInstance[idx] = true;
136 }
137 List<String> dedupd = new ArrayList<String>(nameToLastIndex.size());
138 for (int i = 0, n = encoded.size(); i < n; i++) {
139 if (isLastInstance[i]) {
140 dedupd.add(encoded.get(i));
141 }
142 }
143 return dedupd;
144 }
145
146
147
148
149
150
151
152 public List<String> encode(Cookie... cookies) {
153 if (checkNotNull(cookies, "cookies").length == 0) {
154 return Collections.emptyList();
155 }
156
157 List<String> encoded = new ArrayList<String>(cookies.length);
158 Map<String, Integer> nameToIndex = strict && cookies.length > 1 ? new HashMap<String, Integer>() : null;
159 boolean hasDupdName = false;
160 for (int i = 0; i < cookies.length; i++) {
161 Cookie c = cookies[i];
162 encoded.add(encode(c));
163 if (nameToIndex != null) {
164 hasDupdName |= nameToIndex.put(c.name(), i) != null;
165 }
166 }
167 return hasDupdName ? dedup(encoded, nameToIndex) : encoded;
168 }
169
170
171
172
173
174
175
176 public List<String> encode(Collection<? extends Cookie> cookies) {
177 if (checkNotNull(cookies, "cookies").isEmpty()) {
178 return Collections.emptyList();
179 }
180
181 List<String> encoded = new ArrayList<String>(cookies.size());
182 Map<String, Integer> nameToIndex = strict && cookies.size() > 1 ? new HashMap<String, Integer>() : null;
183 int i = 0;
184 boolean hasDupdName = false;
185 for (Cookie c : cookies) {
186 encoded.add(encode(c));
187 if (nameToIndex != null) {
188 hasDupdName |= nameToIndex.put(c.name(), i++) != null;
189 }
190 }
191 return hasDupdName ? dedup(encoded, nameToIndex) : encoded;
192 }
193
194
195
196
197
198
199
200 public List<String> encode(Iterable<? extends Cookie> cookies) {
201 Iterator<? extends Cookie> cookiesIt = checkNotNull(cookies, "cookies").iterator();
202 if (!cookiesIt.hasNext()) {
203 return Collections.emptyList();
204 }
205
206 List<String> encoded = new ArrayList<String>();
207 Cookie firstCookie = cookiesIt.next();
208 Map<String, Integer> nameToIndex = strict && cookiesIt.hasNext() ? new HashMap<String, Integer>() : null;
209 int i = 0;
210 encoded.add(encode(firstCookie));
211 boolean hasDupdName = nameToIndex != null ? nameToIndex.put(firstCookie.name(), i++) != null : false;
212 while (cookiesIt.hasNext()) {
213 Cookie c = cookiesIt.next();
214 encoded.add(encode(c));
215 if (nameToIndex != null) {
216 hasDupdName |= nameToIndex.put(c.name(), i++) != null;
217 }
218 }
219 return hasDupdName ? dedup(encoded, nameToIndex) : encoded;
220 }
221 }