1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http;
17
18 import io.netty.handler.codec.CharSequenceValueConverter;
19 import io.netty.handler.codec.DateFormatter;
20 import io.netty.handler.codec.DefaultHeaders;
21 import io.netty.handler.codec.DefaultHeaders.NameValidator;
22 import io.netty.handler.codec.DefaultHeaders.ValueValidator;
23 import io.netty.handler.codec.DefaultHeadersImpl;
24 import io.netty.handler.codec.Headers;
25 import io.netty.handler.codec.HeadersUtils;
26 import io.netty.handler.codec.ValueConverter;
27
28 import java.util.ArrayList;
29 import java.util.Calendar;
30 import java.util.Collections;
31 import java.util.Date;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Map.Entry;
36 import java.util.Set;
37 import java.util.function.BiPredicate;
38
39 import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER;
40 import static io.netty.util.AsciiString.CASE_SENSITIVE_HASHER;
41
42
43
44
45 public class DefaultHttpHeaders extends HttpHeaders {
46 private static final BiPredicate<CharSequence, CharSequence> CASE_INSENSITIVE_CONTAINS =
47 (value, expected) ->
48 HttpHeaders.containsCommaSeparatedTrimmed(value, expected, true);
49 private static final BiPredicate<CharSequence, CharSequence> CASE_SENSITIVE_CONTAINS =
50 (value, expected) ->
51 HttpHeaders.containsCommaSeparatedTrimmed(value, expected, false);
52
53 private final DefaultHeaders<CharSequence, CharSequence, ?> headers;
54
55
56
57
58
59
60 public DefaultHttpHeaders() {
61 this(nameValidator(true), valueValidator(true));
62 }
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 @Deprecated
79 public DefaultHttpHeaders(boolean validate) {
80 this(nameValidator(validate), valueValidator(validate));
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100 protected DefaultHttpHeaders(boolean validateValues, NameValidator<CharSequence> nameValidator) {
101 this(nameValidator, valueValidator(validateValues));
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 protected DefaultHttpHeaders(
123 NameValidator<CharSequence> nameValidator,
124 ValueValidator<CharSequence> valueValidator) {
125 this(nameValidator, valueValidator, 16);
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147 protected DefaultHttpHeaders(
148 NameValidator<CharSequence> nameValidator,
149 ValueValidator<CharSequence> valueValidator,
150 int sizeHint) {
151 this(new DefaultHeadersImpl<CharSequence, CharSequence>(
152 CASE_INSENSITIVE_HASHER,
153 HeaderValueConverter.INSTANCE,
154 nameValidator,
155 sizeHint,
156 valueValidator));
157 }
158
159 protected DefaultHttpHeaders(DefaultHeaders<CharSequence, CharSequence, ?> headers) {
160 this.headers = headers;
161 }
162
163 public Headers<CharSequence, CharSequence, ?> unwrap() {
164 return headers;
165 }
166
167 @Override
168 public HttpHeaders add(HttpHeaders headers) {
169 if (headers instanceof DefaultHttpHeaders) {
170 this.headers.add(((DefaultHttpHeaders) headers).headers);
171 return this;
172 } else {
173 return super.add(headers);
174 }
175 }
176
177 @Override
178 public HttpHeaders set(HttpHeaders headers) {
179 if (headers instanceof DefaultHttpHeaders) {
180 this.headers.set(((DefaultHttpHeaders) headers).headers);
181 return this;
182 } else {
183 return super.set(headers);
184 }
185 }
186
187 @Override
188 public HttpHeaders add(String name, Object value) {
189 headers.addObject(name, value);
190 return this;
191 }
192
193 @Override
194 public HttpHeaders add(CharSequence name, Object value) {
195 headers.addObject(name, value);
196 return this;
197 }
198
199 @Override
200 public HttpHeaders add(String name, Iterable<?> values) {
201 headers.addObject(name, values);
202 return this;
203 }
204
205 @Override
206 public HttpHeaders add(CharSequence name, Iterable<?> values) {
207 headers.addObject(name, values);
208 return this;
209 }
210
211 @Override
212 public HttpHeaders addInt(CharSequence name, int value) {
213 headers.addInt(name, value);
214 return this;
215 }
216
217 @Override
218 public HttpHeaders addShort(CharSequence name, short value) {
219 headers.addShort(name, value);
220 return this;
221 }
222
223 @Override
224 public HttpHeaders remove(String name) {
225 headers.remove(name);
226 return this;
227 }
228
229 @Override
230 public HttpHeaders remove(CharSequence name) {
231 headers.remove(name);
232 return this;
233 }
234
235 @Override
236 public HttpHeaders set(String name, Object value) {
237 headers.setObject(name, value);
238 return this;
239 }
240
241 @Override
242 public HttpHeaders set(CharSequence name, Object value) {
243 headers.setObject(name, value);
244 return this;
245 }
246
247 @Override
248 public HttpHeaders set(String name, Iterable<?> values) {
249 headers.setObject(name, values);
250 return this;
251 }
252
253 @Override
254 public HttpHeaders set(CharSequence name, Iterable<?> values) {
255 headers.setObject(name, values);
256 return this;
257 }
258
259 @Override
260 public HttpHeaders setInt(CharSequence name, int value) {
261 headers.setInt(name, value);
262 return this;
263 }
264
265 @Override
266 public HttpHeaders setShort(CharSequence name, short value) {
267 headers.setShort(name, value);
268 return this;
269 }
270
271 @Override
272 public HttpHeaders clear() {
273 headers.clear();
274 return this;
275 }
276
277 @Override
278 public String get(String name) {
279 return get((CharSequence) name);
280 }
281
282 @Override
283 public String get(CharSequence name) {
284 return HeadersUtils.getAsString(headers, name);
285 }
286
287 @Override
288 public Integer getInt(CharSequence name) {
289 return headers.getInt(name);
290 }
291
292 @Override
293 public int getInt(CharSequence name, int defaultValue) {
294 return headers.getInt(name, defaultValue);
295 }
296
297 @Override
298 public Short getShort(CharSequence name) {
299 return headers.getShort(name);
300 }
301
302 @Override
303 public short getShort(CharSequence name, short defaultValue) {
304 return headers.getShort(name, defaultValue);
305 }
306
307 @Override
308 public Long getTimeMillis(CharSequence name) {
309 return headers.getTimeMillis(name);
310 }
311
312 @Override
313 public long getTimeMillis(CharSequence name, long defaultValue) {
314 return headers.getTimeMillis(name, defaultValue);
315 }
316
317 @Override
318 public List<String> getAll(String name) {
319 return getAll((CharSequence) name);
320 }
321
322 @Override
323 public List<String> getAll(CharSequence name) {
324 return HeadersUtils.getAllAsString(headers, name);
325 }
326
327 @Override
328 public List<Entry<String, String>> entries() {
329 if (isEmpty()) {
330 return Collections.emptyList();
331 }
332 List<Entry<String, String>> entriesConverted = new ArrayList<Entry<String, String>>(
333 headers.size());
334 for (Entry<String, String> entry : this) {
335 entriesConverted.add(entry);
336 }
337 return entriesConverted;
338 }
339
340 @Deprecated
341 @Override
342 public Iterator<Map.Entry<String, String>> iterator() {
343 return HeadersUtils.iteratorAsString(headers);
344 }
345
346 @Override
347 public Iterator<Entry<CharSequence, CharSequence>> iteratorCharSequence() {
348 return headers.iterator();
349 }
350
351 @Override
352 public Iterator<String> valueStringIterator(CharSequence name) {
353 final Iterator<CharSequence> itr = valueCharSequenceIterator(name);
354 return new Iterator<String>() {
355 @Override
356 public boolean hasNext() {
357 return itr.hasNext();
358 }
359
360 @Override
361 public String next() {
362 return itr.next().toString();
363 }
364
365 @Override
366 public void remove() {
367 itr.remove();
368 }
369 };
370 }
371
372 @Override
373 public Iterator<CharSequence> valueCharSequenceIterator(CharSequence name) {
374 return headers.valueIterator(name);
375 }
376
377 @Override
378 public boolean containsValue(CharSequence name, CharSequence value, boolean ignoreCase) {
379 return headers.containsAny(name, value, ignoreCase ? CASE_INSENSITIVE_CONTAINS : CASE_SENSITIVE_CONTAINS);
380 }
381
382 @Override
383 public boolean contains(String name) {
384 return contains((CharSequence) name);
385 }
386
387 @Override
388 public boolean contains(CharSequence name) {
389 return headers.contains(name);
390 }
391
392 @Override
393 public boolean isEmpty() {
394 return headers.isEmpty();
395 }
396
397 @Override
398 public int size() {
399 return headers.size();
400 }
401
402 @Override
403 public boolean contains(String name, String value, boolean ignoreCase) {
404 return contains((CharSequence) name, (CharSequence) value, ignoreCase);
405 }
406
407 @Override
408 public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) {
409 return headers.contains(name, value, ignoreCase ? CASE_INSENSITIVE_HASHER : CASE_SENSITIVE_HASHER);
410 }
411
412 @Override
413 public Set<String> names() {
414 return HeadersUtils.namesAsString(headers);
415 }
416
417 @Override
418 public boolean equals(Object o) {
419 return o instanceof DefaultHttpHeaders
420 && headers.equals(((DefaultHttpHeaders) o).headers, CASE_SENSITIVE_HASHER);
421 }
422
423 @Override
424 public int hashCode() {
425 return headers.hashCode(CASE_SENSITIVE_HASHER);
426 }
427
428 @Override
429 public HttpHeaders copy() {
430 return new DefaultHttpHeaders(headers.copy());
431 }
432
433 static ValueConverter<CharSequence> valueConverter() {
434 return HeaderValueConverter.INSTANCE;
435 }
436
437 static ValueValidator<CharSequence> valueValidator(boolean validate) {
438 return validate ? DefaultHttpHeadersFactory.headersFactory().getValueValidator() :
439 DefaultHttpHeadersFactory.headersFactory().withValidation(false).getValueValidator();
440 }
441
442 static NameValidator<CharSequence> nameValidator(boolean validate) {
443 return validate ? DefaultHttpHeadersFactory.headersFactory().getNameValidator() :
444 DefaultHttpHeadersFactory.headersFactory().withNameValidation(false).getNameValidator();
445 }
446
447 private static class HeaderValueConverter extends CharSequenceValueConverter {
448 static final HeaderValueConverter INSTANCE = new HeaderValueConverter();
449
450 @Override
451 public CharSequence convertObject(Object value) {
452 if (value instanceof CharSequence) {
453 return (CharSequence) value;
454 }
455 if (value instanceof Date) {
456 return DateFormatter.format((Date) value);
457 }
458 if (value instanceof Calendar) {
459 return DateFormatter.format(((Calendar) value).getTime());
460 }
461 return value.toString();
462 }
463 }
464 }