1 /*
2 * Copyright 2012 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package io.netty5.handler.codec.http;
17
18 import io.netty5.handler.codec.DateFormatter;
19 import io.netty5.handler.codec.Headers;
20 import io.netty5.handler.codec.HeadersUtils;
21 import io.netty5.util.AsciiString;
22
23 import java.text.ParseException;
24 import java.util.Calendar;
25 import java.util.Date;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Map.Entry;
30 import java.util.Set;
31
32 import static io.netty5.util.AsciiString.contentEquals;
33 import static io.netty5.util.AsciiString.contentEqualsIgnoreCase;
34 import static io.netty5.util.AsciiString.trim;
35 import static java.util.Objects.requireNonNull;
36
37 /**
38 * Provides the constants for the standard HTTP header names and values and
39 * commonly used utility methods that accesses an {@link HttpMessage}.
40 */
41 public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>> {
42
43 /**
44 * @deprecated Use {@link HttpUtil#isKeepAlive(HttpMessage)} instead.
45 *
46 * Returns {@code true} if and only if the connection can remain open and
47 * thus 'kept alive'. This methods respects the value of the
48 * {@code "Connection"} header first and then the return value of
49 * {@link HttpVersion#isKeepAliveDefault()}.
50 */
51 @Deprecated
52 public static boolean isKeepAlive(HttpMessage message) {
53 return HttpUtil.isKeepAlive(message);
54 }
55
56 /**
57 * @deprecated Use {@link HttpUtil#setKeepAlive(HttpMessage, boolean)} instead.
58 *
59 * Sets the value of the {@code "Connection"} header depending on the
60 * protocol version of the specified message. This getMethod sets or removes
61 * the {@code "Connection"} header depending on what the default keep alive
62 * mode of the message's protocol version is, as specified by
63 * {@link HttpVersion#isKeepAliveDefault()}.
64 * <ul>
65 * <li>If the connection is kept alive by default:
66 * <ul>
67 * <li>set to {@code "close"} if {@code keepAlive} is {@code false}.</li>
68 * <li>remove otherwise.</li>
69 * </ul></li>
70 * <li>If the connection is closed by default:
71 * <ul>
72 * <li>set to {@code "keep-alive"} if {@code keepAlive} is {@code true}.</li>
73 * <li>remove otherwise.</li>
74 * </ul></li>
75 * </ul>
76 */
77 @Deprecated
78 public static void setKeepAlive(HttpMessage message, boolean keepAlive) {
79 HttpUtil.setKeepAlive(message, keepAlive);
80 }
81
82 /**
83 * @deprecated Use {@link #get(CharSequence)} instead.
84 */
85 @Deprecated
86 public static String getHeader(HttpMessage message, String name) {
87 return message.headers().get(name);
88 }
89
90 /**
91 * @deprecated Use {@link #get(CharSequence)} instead.
92 *
93 * Returns the header value with the specified header name. If there are
94 * more than one header value for the specified header name, the first
95 * value is returned.
96 *
97 * @return the header value or {@code null} if there is no such header
98 */
99 @Deprecated
100 public static String getHeader(HttpMessage message, CharSequence name) {
101 return message.headers().get(name);
102 }
103
104 /**
105 * @deprecated Use {@link #get(CharSequence, String)} instead.
106 *
107 * @see #getHeader(HttpMessage, CharSequence, String)
108 */
109 @Deprecated
110 public static String getHeader(HttpMessage message, String name, String defaultValue) {
111 return message.headers().get(name, defaultValue);
112 }
113
114 /**
115 * @deprecated Use {@link #get(CharSequence, String)} instead.
116 *
117 * Returns the header value with the specified header name. If there are
118 * more than one header value for the specified header name, the first
119 * value is returned.
120 *
121 * @return the header value or the {@code defaultValue} if there is no such
122 * header
123 */
124 @Deprecated
125 public static String getHeader(HttpMessage message, CharSequence name, String defaultValue) {
126 return message.headers().get(name, defaultValue);
127 }
128
129 /**
130 * @deprecated Use {@link #set(CharSequence, Object)} instead.
131 *
132 * @see #setHeader(HttpMessage, CharSequence, Object)
133 */
134 @Deprecated
135 public static void setHeader(HttpMessage message, String name, Object value) {
136 message.headers().set(name, value);
137 }
138
139 /**
140 * @deprecated Use {@link #set(CharSequence, Object)} instead.
141 *
142 * Sets a new header with the specified name and value. If there is an
143 * existing header with the same name, the existing header is removed.
144 * If the specified value is not a {@link String}, it is converted into a
145 * {@link String} by {@link Object#toString()}, except for {@link Date}
146 * and {@link Calendar} which are formatted to the date format defined in
147 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
148 */
149 @Deprecated
150 public static void setHeader(HttpMessage message, CharSequence name, Object value) {
151 message.headers().set(name, value);
152 }
153
154 /**
155 * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
156 *
157 * @see #setHeader(HttpMessage, CharSequence, Iterable)
158 */
159 @Deprecated
160 public static void setHeader(HttpMessage message, String name, Iterable<?> values) {
161 message.headers().set(name, values);
162 }
163
164 /**
165 * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
166 *
167 * Sets a new header with the specified name and values. If there is an
168 * existing header with the same name, the existing header is removed.
169 * This getMethod can be represented approximately as the following code:
170 * <pre>
171 * removeHeader(message, name);
172 * for (Object v: values) {
173 * if (v == null) {
174 * break;
175 * }
176 * addHeader(message, name, v);
177 * }
178 * </pre>
179 */
180 @Deprecated
181 public static void setHeader(HttpMessage message, CharSequence name, Iterable<?> values) {
182 message.headers().set(name, values);
183 }
184
185 /**
186 * @deprecated Use {@link #add(CharSequence, Object)} instead.
187 *
188 * @see #addHeader(HttpMessage, CharSequence, Object)
189 */
190 @Deprecated
191 public static void addHeader(HttpMessage message, String name, Object value) {
192 message.headers().add(name, value);
193 }
194
195 /**
196 * @deprecated Use {@link #add(CharSequence, Object)} instead.
197 *
198 * Adds a new header with the specified name and value.
199 * If the specified value is not a {@link String}, it is converted into a
200 * {@link String} by {@link Object#toString()}, except for {@link Date}
201 * and {@link Calendar} which are formatted to the date format defined in
202 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
203 */
204 @Deprecated
205 public static void addHeader(HttpMessage message, CharSequence name, Object value) {
206 message.headers().add(name, value);
207 }
208
209 /**
210 * @deprecated Use {@link #remove(CharSequence)} instead.
211 *
212 * @see #removeHeader(HttpMessage, CharSequence)
213 */
214 @Deprecated
215 public static void removeHeader(HttpMessage message, String name) {
216 message.headers().remove(name);
217 }
218
219 /**
220 * @deprecated Use {@link #remove(CharSequence)} instead.
221 *
222 * Removes the header with the specified name.
223 */
224 @Deprecated
225 public static void removeHeader(HttpMessage message, CharSequence name) {
226 message.headers().remove(name);
227 }
228
229 /**
230 * @deprecated Use {@link #clear()} instead.
231 *
232 * Removes all headers from the specified message.
233 */
234 @Deprecated
235 public static void clearHeaders(HttpMessage message) {
236 message.headers().clear();
237 }
238
239 /**
240 * @deprecated Use {@link #getInt(CharSequence)} instead.
241 *
242 * @see #getIntHeader(HttpMessage, CharSequence)
243 */
244 @Deprecated
245 public static int getIntHeader(HttpMessage message, String name) {
246 return getIntHeader(message, (CharSequence) name);
247 }
248
249 /**
250 * @deprecated Use {@link #getInt(CharSequence)} instead.
251 *
252 * Returns the integer header value with the specified header name. If
253 * there are more than one header value for the specified header name, the
254 * first value is returned.
255 *
256 * @return the header value
257 * @throws NumberFormatException
258 * if there is no such header or the header value is not a number
259 */
260 @Deprecated
261 public static int getIntHeader(HttpMessage message, CharSequence name) {
262 String value = message.headers().get(name);
263 if (value == null) {
264 throw new NumberFormatException("header not found: " + name);
265 }
266 return Integer.parseInt(value);
267 }
268
269 /**
270 * @deprecated Use {@link #getInt(CharSequence, int)} instead.
271 *
272 * @see #getIntHeader(HttpMessage, CharSequence, int)
273 */
274 @Deprecated
275 public static int getIntHeader(HttpMessage message, String name, int defaultValue) {
276 return message.headers().getInt(name, defaultValue);
277 }
278
279 /**
280 * @deprecated Use {@link #getInt(CharSequence, int)} instead.
281 *
282 * Returns the integer header value with the specified header name. If
283 * there are more than one header value for the specified header name, the
284 * first value is returned.
285 *
286 * @return the header value or the {@code defaultValue} if there is no such
287 * header or the header value is not a number
288 */
289 @Deprecated
290 public static int getIntHeader(HttpMessage message, CharSequence name, int defaultValue) {
291 return message.headers().getInt(name, defaultValue);
292 }
293
294 /**
295 * @deprecated Use {@link #setInt(CharSequence, int)} instead.
296 *
297 * @see #setIntHeader(HttpMessage, CharSequence, int)
298 */
299 @Deprecated
300 public static void setIntHeader(HttpMessage message, String name, int value) {
301 message.headers().setInt(name, value);
302 }
303
304 /**
305 * @deprecated Use {@link #setInt(CharSequence, int)} instead.
306 *
307 * Sets a new integer header with the specified name and value. If there
308 * is an existing header with the same name, the existing header is removed.
309 */
310 @Deprecated
311 public static void setIntHeader(HttpMessage message, CharSequence name, int value) {
312 message.headers().setInt(name, value);
313 }
314
315 /**
316 * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
317 *
318 * @see #setIntHeader(HttpMessage, CharSequence, Iterable)
319 */
320 @Deprecated
321 public static void setIntHeader(HttpMessage message, String name, Iterable<Integer> values) {
322 message.headers().set(name, values);
323 }
324
325 /**
326 * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
327 *
328 * Sets a new integer header with the specified name and values. If there
329 * is an existing header with the same name, the existing header is removed.
330 */
331 @Deprecated
332 public static void setIntHeader(HttpMessage message, CharSequence name, Iterable<Integer> values) {
333 message.headers().set(name, values);
334 }
335
336 /**
337 * @deprecated Use {@link #add(CharSequence, Iterable)} instead.
338 *
339 * @see #addIntHeader(HttpMessage, CharSequence, int)
340 */
341 @Deprecated
342 public static void addIntHeader(HttpMessage message, String name, int value) {
343 message.headers().add(name, value);
344 }
345
346 /**
347 * @deprecated Use {@link #addInt(CharSequence, int)} instead.
348 *
349 * Adds a new integer header with the specified name and value.
350 */
351 @Deprecated
352 public static void addIntHeader(HttpMessage message, CharSequence name, int value) {
353 message.headers().addInt(name, value);
354 }
355
356 /**
357 * @deprecated Use {@link #getTimeMillis(CharSequence)} instead.
358 *
359 * @see #getDateHeader(HttpMessage, CharSequence)
360 */
361 @Deprecated
362 public static Date getDateHeader(HttpMessage message, String name) throws ParseException {
363 return getDateHeader(message, (CharSequence) name);
364 }
365
366 /**
367 * @deprecated Use {@link #getTimeMillis(CharSequence)} instead.
368 *
369 * Returns the date header value with the specified header name. If
370 * there are more than one header value for the specified header name, the
371 * first value is returned.
372 *
373 * @return the header value
374 * @throws ParseException
375 * if there is no such header or the header value is not a formatted date
376 */
377 @Deprecated
378 public static Date getDateHeader(HttpMessage message, CharSequence name) throws ParseException {
379 String value = message.headers().get(name);
380 if (value == null) {
381 throw new ParseException("header not found: " + name, 0);
382 }
383 Date date = DateFormatter.parseHttpDate(value);
384 if (date == null) {
385 throw new ParseException("header can't be parsed into a Date: " + value, 0);
386 }
387 return date;
388 }
389
390 /**
391 * @deprecated Use {@link #getTimeMillis(CharSequence, long)} instead.
392 *
393 * @see #getDateHeader(HttpMessage, CharSequence, Date)
394 */
395 @Deprecated
396 public static Date getDateHeader(HttpMessage message, String name, Date defaultValue) {
397 return getDateHeader(message, (CharSequence) name, defaultValue);
398 }
399
400 /**
401 * @deprecated Use {@link #getTimeMillis(CharSequence, long)} instead.
402 *
403 * Returns the date header value with the specified header name. If
404 * there are more than one header value for the specified header name, the
405 * first value is returned.
406 *
407 * @return the header value or the {@code defaultValue} if there is no such
408 * header or the header value is not a formatted date
409 */
410 @Deprecated
411 public static Date getDateHeader(HttpMessage message, CharSequence name, Date defaultValue) {
412 final String value = getHeader(message, name);
413 Date date = DateFormatter.parseHttpDate(value);
414 return date != null ? date : defaultValue;
415 }
416
417 /**
418 * @deprecated Use {@link #set(CharSequence, Object)} instead.
419 *
420 * @see #setDateHeader(HttpMessage, CharSequence, Date)
421 */
422 @Deprecated
423 public static void setDateHeader(HttpMessage message, String name, Date value) {
424 setDateHeader(message, (CharSequence) name, value);
425 }
426
427 /**
428 * @deprecated Use {@link #set(CharSequence, Object)} instead.
429 *
430 * Sets a new date header with the specified name and value. If there
431 * is an existing header with the same name, the existing header is removed.
432 * The specified value is formatted as defined in
433 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>
434 */
435 @Deprecated
436 public static void setDateHeader(HttpMessage message, CharSequence name, Date value) {
437 if (value != null) {
438 message.headers().set(name, DateFormatter.format(value));
439 } else {
440 message.headers().set(name, null);
441 }
442 }
443
444 /**
445 * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
446 *
447 * @see #setDateHeader(HttpMessage, CharSequence, Iterable)
448 */
449 @Deprecated
450 public static void setDateHeader(HttpMessage message, String name, Iterable<Date> values) {
451 message.headers().set(name, values);
452 }
453
454 /**
455 * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
456 *
457 * Sets a new date header with the specified name and values. If there
458 * is an existing header with the same name, the existing header is removed.
459 * The specified values are formatted as defined in
460 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>
461 */
462 @Deprecated
463 public static void setDateHeader(HttpMessage message, CharSequence name, Iterable<Date> values) {
464 message.headers().set(name, values);
465 }
466
467 /**
468 * @deprecated Use {@link #add(CharSequence, Object)} instead.
469 *
470 * @see #addDateHeader(HttpMessage, CharSequence, Date)
471 */
472 @Deprecated
473 public static void addDateHeader(HttpMessage message, String name, Date value) {
474 message.headers().add(name, value);
475 }
476
477 /**
478 * @deprecated Use {@link #add(CharSequence, Object)} instead.
479 *
480 * Adds a new date header with the specified name and value. The specified
481 * value is formatted as defined in
482 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>
483 */
484 @Deprecated
485 public static void addDateHeader(HttpMessage message, CharSequence name, Date value) {
486 message.headers().add(name, value);
487 }
488
489 /**
490 * @deprecated Use {@link HttpUtil#getContentLength(HttpMessage)} instead.
491 *
492 * Returns the length of the content. Please note that this value is
493 * not retrieved from {@link HttpContent#payload()} but from the
494 * {@code "Content-Length"} header, and thus they are independent from each
495 * other.
496 *
497 * @return the content length
498 *
499 * @throws NumberFormatException
500 * if the message does not have the {@code "Content-Length"} header
501 * or its value is not a number
502 */
503 @Deprecated
504 public static long getContentLength(HttpMessage message) {
505 return HttpUtil.getContentLength(message);
506 }
507
508 /**
509 * @deprecated Use {@link HttpUtil#getContentLength(HttpMessage, long)} instead.
510 *
511 * Returns the length of the content. Please note that this value is
512 * not retrieved from {@link HttpContent#payload()} but from the
513 * {@code "Content-Length"} header, and thus they are independent from each
514 * other.
515 *
516 * @return the content length or {@code defaultValue} if this message does
517 * not have the {@code "Content-Length"} header or its value is not
518 * a number
519 */
520 @Deprecated
521 public static long getContentLength(HttpMessage message, long defaultValue) {
522 return HttpUtil.getContentLength(message, defaultValue);
523 }
524
525 /**
526 * @deprecated Use {@link HttpUtil#setContentLength(HttpMessage, long)} instead.
527 */
528 @Deprecated
529 public static void setContentLength(HttpMessage message, long length) {
530 HttpUtil.setContentLength(message, length);
531 }
532
533 /**
534 * @deprecated Use {@link #get(CharSequence)} instead.
535 *
536 * Returns the value of the {@code "Host"} header.
537 */
538 @Deprecated
539 public static String getHost(HttpMessage message) {
540 return message.headers().get(HttpHeaderNames.HOST);
541 }
542
543 /**
544 * @deprecated Use {@link #get(CharSequence, String)} instead.
545 *
546 * Returns the value of the {@code "Host"} header. If there is no such
547 * header, the {@code defaultValue} is returned.
548 */
549 @Deprecated
550 public static String getHost(HttpMessage message, String defaultValue) {
551 return message.headers().get(HttpHeaderNames.HOST, defaultValue);
552 }
553
554 /**
555 * @deprecated Use {@link #set(CharSequence, Object)} instead.
556 *
557 * @see #setHost(HttpMessage, CharSequence)
558 */
559 @Deprecated
560 public static void setHost(HttpMessage message, String value) {
561 message.headers().set(HttpHeaderNames.HOST, value);
562 }
563
564 /**
565 * @deprecated Use {@link #set(CharSequence, Object)} instead.
566 *
567 * Sets the {@code "Host"} header.
568 */
569 @Deprecated
570 public static void setHost(HttpMessage message, CharSequence value) {
571 message.headers().set(HttpHeaderNames.HOST, value);
572 }
573
574 /**
575 * @deprecated Use {@link #getTimeMillis(CharSequence)} instead.
576 *
577 * Returns the value of the {@code "Date"} header.
578 *
579 * @throws ParseException
580 * if there is no such header or the header value is not a formatted date
581 */
582 @Deprecated
583 public static Date getDate(HttpMessage message) throws ParseException {
584 return getDateHeader(message, HttpHeaderNames.DATE);
585 }
586
587 /**
588 * @deprecated Use {@link #getTimeMillis(CharSequence, long)} instead.
589 *
590 * Returns the value of the {@code "Date"} header. If there is no such
591 * header or the header is not a formatted date, the {@code defaultValue}
592 * is returned.
593 */
594 @Deprecated
595 public static Date getDate(HttpMessage message, Date defaultValue) {
596 return getDateHeader(message, HttpHeaderNames.DATE, defaultValue);
597 }
598
599 /**
600 * @deprecated Use {@link #set(CharSequence, Object)} instead.
601 *
602 * Sets the {@code "Date"} header.
603 */
604 @Deprecated
605 public static void setDate(HttpMessage message, Date value) {
606 message.headers().set(HttpHeaderNames.DATE, value);
607 }
608
609 /**
610 * @deprecated Use {@link HttpUtil#is100ContinueExpected(HttpMessage)} instead.
611 *
612 * Returns {@code true} if and only if the specified message contains the
613 * {@code "Expect: 100-continue"} header.
614 */
615 @Deprecated
616 public static boolean is100ContinueExpected(HttpMessage message) {
617 return HttpUtil.is100ContinueExpected(message);
618 }
619
620 /**
621 * @deprecated Use {@link HttpUtil#set100ContinueExpected(HttpMessage, boolean)} instead.
622 *
623 * Sets the {@code "Expect: 100-continue"} header to the specified message.
624 * If there is any existing {@code "Expect"} header, they are replaced with
625 * the new one.
626 */
627 @Deprecated
628 public static void set100ContinueExpected(HttpMessage message) {
629 HttpUtil.set100ContinueExpected(message, true);
630 }
631
632 /**
633 * @deprecated Use {@link HttpUtil#set100ContinueExpected(HttpMessage, boolean)} instead.
634 *
635 * Sets or removes the {@code "Expect: 100-continue"} header to / from the
636 * specified message. If {@code set} is {@code true},
637 * the {@code "Expect: 100-continue"} header is set and all other previous
638 * {@code "Expect"} headers are removed. Otherwise, all {@code "Expect"}
639 * headers are removed completely.
640 */
641 @Deprecated
642 public static void set100ContinueExpected(HttpMessage message, boolean set) {
643 HttpUtil.set100ContinueExpected(message, set);
644 }
645
646 /**
647 * @deprecated Use {@link HttpUtil#isTransferEncodingChunked(HttpMessage)} instead.
648 *
649 * Checks to see if the transfer encoding in a specified {@link HttpMessage} is chunked
650 *
651 * @param message The message to check
652 * @return True if transfer encoding is chunked, otherwise false
653 */
654 @Deprecated
655 public static boolean isTransferEncodingChunked(HttpMessage message) {
656 return HttpUtil.isTransferEncodingChunked(message);
657 }
658
659 /**
660 * @deprecated Use {@link HttpUtil#setTransferEncodingChunked(HttpMessage, boolean)} instead.
661 */
662 @Deprecated
663 public static void removeTransferEncodingChunked(HttpMessage m) {
664 HttpUtil.setTransferEncodingChunked(m, false);
665 }
666
667 /**
668 * @deprecated Use {@link HttpUtil#setTransferEncodingChunked(HttpMessage, boolean)} instead.
669 */
670 @Deprecated
671 public static void setTransferEncodingChunked(HttpMessage m) {
672 HttpUtil.setTransferEncodingChunked(m, true);
673 }
674
675 /**
676 * @deprecated Use {@link HttpUtil#isContentLengthSet(HttpMessage)} instead.
677 */
678 @Deprecated
679 public static boolean isContentLengthSet(HttpMessage m) {
680 return HttpUtil.isContentLengthSet(m);
681 }
682
683 /**
684 * @deprecated Use {@link AsciiString#contentEqualsIgnoreCase(CharSequence, CharSequence)} instead.
685 */
686 @Deprecated
687 public static boolean equalsIgnoreCase(CharSequence name1, CharSequence name2) {
688 return contentEqualsIgnoreCase(name1, name2);
689 }
690
691 /**
692 * @deprecated Use {@link AsciiString} instead.
693 * <p>
694 * Create a new {@link CharSequence} which is optimized for reuse as {@link HttpHeaders} name or value.
695 * So if you have a Header name or value that you want to reuse you should make use of this.
696 */
697 @Deprecated
698 public static CharSequence newEntity(String name) {
699 return new AsciiString(name);
700 }
701
702 protected HttpHeaders() { }
703
704 /**
705 * @see #get(CharSequence)
706 */
707 public abstract String get(String name);
708
709 /**
710 * Returns the value of a header with the specified name. If there are
711 * more than one values for the specified name, the first value is returned.
712 *
713 * @param name The name of the header to search
714 * @return The first header value or {@code null} if there is no such header
715 * @see #getAsString(CharSequence)
716 */
717 public String get(CharSequence name) {
718 return get(name.toString());
719 }
720
721 /**
722 * Returns the value of a header with the specified name. If there are
723 * more than one values for the specified name, the first value is returned.
724 *
725 * @param name The name of the header to search
726 * @return The first header value or {@code defaultValue} if there is no such header
727 */
728 public String get(CharSequence name, String defaultValue) {
729 String value = get(name);
730 if (value == null) {
731 return defaultValue;
732 }
733 return value;
734 }
735
736 /**
737 * Returns the integer value of a header with the specified name. If there are more than one values for the
738 * specified name, the first value is returned.
739 *
740 * @param name the name of the header to search
741 * @return the first header value if the header is found and its value is an integer. {@code null} if there's no
742 * such header or its value is not an integer.
743 */
744 public abstract Integer getInt(CharSequence name);
745
746 /**
747 * Returns the integer value of a header with the specified name. If there are more than one values for the
748 * specified name, the first value is returned.
749 *
750 * @param name the name of the header to search
751 * @param defaultValue the default value
752 * @return the first header value if the header is found and its value is an integer. {@code defaultValue} if
753 * there's no such header or its value is not an integer.
754 */
755 public abstract int getInt(CharSequence name, int defaultValue);
756
757 /**
758 * Returns the short value of a header with the specified name. If there are more than one values for the
759 * specified name, the first value is returned.
760 *
761 * @param name the name of the header to search
762 * @return the first header value if the header is found and its value is a short. {@code null} if there's no
763 * such header or its value is not a short.
764 */
765 public abstract Short getShort(CharSequence name);
766
767 /**
768 * Returns the short value of a header with the specified name. If there are more than one values for the
769 * specified name, the first value is returned.
770 *
771 * @param name the name of the header to search
772 * @param defaultValue the default value
773 * @return the first header value if the header is found and its value is a short. {@code defaultValue} if
774 * there's no such header or its value is not a short.
775 */
776 public abstract short getShort(CharSequence name, short defaultValue);
777
778 /**
779 * Returns the date value of a header with the specified name. If there are more than one values for the
780 * specified name, the first value is returned.
781 *
782 * @param name the name of the header to search
783 * @return the first header value if the header is found and its value is a date. {@code null} if there's no
784 * such header or its value is not a date.
785 */
786 public abstract Long getTimeMillis(CharSequence name);
787
788 /**
789 * Returns the date value of a header with the specified name. If there are more than one values for the
790 * specified name, the first value is returned.
791 *
792 * @param name the name of the header to search
793 * @param defaultValue the default value
794 * @return the first header value if the header is found and its value is a date. {@code defaultValue} if
795 * there's no such header or its value is not a date.
796 */
797 public abstract long getTimeMillis(CharSequence name, long defaultValue);
798
799 /**
800 * @see #getAll(CharSequence)
801 */
802 public abstract List<String> getAll(String name);
803
804 /**
805 * Returns the values of headers with the specified name
806 *
807 * @param name The name of the headers to search
808 * @return A {@link List} of header values which will be empty if no values
809 * are found
810 * @see #getAllAsString(CharSequence)
811 */
812 public List<String> getAll(CharSequence name) {
813 return getAll(name.toString());
814 }
815
816 /**
817 * Returns a new {@link List} that contains all headers in this object. Note that modifying the
818 * returned {@link List} will not affect the state of this object. If you intend to enumerate over the header
819 * entries only, use {@link #iterator()} instead, which has much less overhead.
820 * @see #iteratorCharSequence()
821 */
822 public abstract List<Map.Entry<String, String>> entries();
823
824 /**
825 * @see #contains(CharSequence)
826 */
827 public abstract boolean contains(String name);
828
829 /**
830 * @deprecated It is preferred to use {@link #iteratorCharSequence()} unless you need {@link String}.
831 * If {@link String} is required then use {@link #iteratorAsString()}.
832 */
833 @Deprecated
834 @Override
835 public abstract Iterator<Entry<String, String>> iterator();
836
837 /**
838 * @return Iterator over the name/value header pairs.
839 */
840 public abstract Iterator<Entry<CharSequence, CharSequence>> iteratorCharSequence();
841
842 /**
843 * Equivalent to {@link #getAll(String)} but it is possible that no intermediate list is generated.
844 * @param name the name of the header to retrieve
845 * @return an {@link Iterator} of header values corresponding to {@code name}.
846 */
847 public Iterator<String> valueStringIterator(CharSequence name) {
848 return getAll(name).iterator();
849 }
850
851 /**
852 * Equivalent to {@link #getAll(String)} but it is possible that no intermediate list is generated.
853 * @param name the name of the header to retrieve
854 * @return an {@link Iterator} of header values corresponding to {@code name}.
855 */
856 public Iterator<? extends CharSequence> valueCharSequenceIterator(CharSequence name) {
857 return valueStringIterator(name);
858 }
859
860 /**
861 * Checks to see if there is a header with the specified name
862 *
863 * @param name The name of the header to search for
864 * @return True if at least one header is found
865 */
866 public boolean contains(CharSequence name) {
867 return contains(name.toString());
868 }
869
870 /**
871 * Checks if no header exists.
872 */
873 public abstract boolean isEmpty();
874
875 /**
876 * Returns the number of headers in this object.
877 */
878 public abstract int size();
879
880 /**
881 * Returns a new {@link Set} that contains the names of all headers in this object. Note that modifying the
882 * returned {@link Set} will not affect the state of this object. If you intend to enumerate over the header
883 * entries only, use {@link #iterator()} instead, which has much less overhead.
884 */
885 public abstract Set<String> names();
886
887 /**
888 * @see #add(CharSequence, Object)
889 */
890 public abstract HttpHeaders add(String name, Object value);
891
892 /**
893 * Adds a new header with the specified name and value.
894 *
895 * If the specified value is not a {@link String}, it is converted
896 * into a {@link String} by {@link Object#toString()}, except in the cases
897 * of {@link Date} and {@link Calendar}, which are formatted to the date
898 * format defined in <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
899 *
900 * @param name The name of the header being added
901 * @param value The value of the header being added
902 *
903 * @return {@code this}
904 */
905 public HttpHeaders add(CharSequence name, Object value) {
906 return add(name.toString(), value);
907 }
908
909 /**
910 * @see #add(CharSequence, Iterable)
911 */
912 public abstract HttpHeaders add(String name, Iterable<?> values);
913
914 /**
915 * Adds a new header with the specified name and values.
916 *
917 * This getMethod can be represented approximately as the following code:
918 * <pre>
919 * for (Object v: values) {
920 * if (v == null) {
921 * break;
922 * }
923 * headers.add(name, v);
924 * }
925 * </pre>
926 *
927 * @param name The name of the headers being set
928 * @param values The values of the headers being set
929 * @return {@code this}
930 */
931 public HttpHeaders add(CharSequence name, Iterable<?> values) {
932 return add(name.toString(), values);
933 }
934
935 /**
936 * Adds all header entries of the specified {@code headers}.
937 *
938 * @return {@code this}
939 */
940 public HttpHeaders add(HttpHeaders headers) {
941 requireNonNull(headers, "headers");
942 for (Map.Entry<String, String> e: headers) {
943 add(e.getKey(), e.getValue());
944 }
945 return this;
946 }
947
948 /**
949 * Add the {@code name} to {@code value}.
950 * @param name The name to modify
951 * @param value The value
952 * @return {@code this}
953 */
954 public abstract HttpHeaders addInt(CharSequence name, int value);
955
956 /**
957 * Add the {@code name} to {@code value}.
958 * @param name The name to modify
959 * @param value The value
960 * @return {@code this}
961 */
962 public abstract HttpHeaders addShort(CharSequence name, short value);
963
964 /**
965 * @see #set(CharSequence, Object)
966 */
967 public abstract HttpHeaders set(String name, Object value);
968
969 /**
970 * Sets a header with the specified name and value.
971 *
972 * If there is an existing header with the same name, it is removed.
973 * If the specified value is not a {@link String}, it is converted into a
974 * {@link String} by {@link Object#toString()}, except for {@link Date}
975 * and {@link Calendar}, which are formatted to the date format defined in
976 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
977 *
978 * @param name The name of the header being set
979 * @param value The value of the header being set
980 * @return {@code this}
981 */
982 public HttpHeaders set(CharSequence name, Object value) {
983 return set(name.toString(), value);
984 }
985
986 /**
987 * @see #set(CharSequence, Iterable)
988 */
989 public abstract HttpHeaders set(String name, Iterable<?> values);
990
991 /**
992 * Sets a header with the specified name and values.
993 *
994 * If there is an existing header with the same name, it is removed.
995 * This getMethod can be represented approximately as the following code:
996 * <pre>
997 * headers.remove(name);
998 * for (Object v: values) {
999 * if (v == null) {
1000 * break;
1001 * }
1002 * headers.add(name, v);
1003 * }
1004 * </pre>
1005 *
1006 * @param name The name of the headers being set
1007 * @param values The values of the headers being set
1008 * @return {@code this}
1009 */
1010 public HttpHeaders set(CharSequence name, Iterable<?> values) {
1011 return set(name.toString(), values);
1012 }
1013
1014 /**
1015 * Cleans the current header entries and copies all header entries of the specified {@code headers}.
1016 *
1017 * @return {@code this}
1018 */
1019 public HttpHeaders set(HttpHeaders headers) {
1020 requireNonNull(headers, "headers");
1021
1022 clear();
1023
1024 if (headers.isEmpty()) {
1025 return this;
1026 }
1027
1028 for (Entry<String, String> entry : headers) {
1029 add(entry.getKey(), entry.getValue());
1030 }
1031 return this;
1032 }
1033
1034 /**
1035 * Retains all current headers but calls {@link #set(String, Object)} for each entry in {@code headers}
1036 *
1037 * @param headers The headers used to {@link #set(String, Object)} values in this instance
1038 * @return {@code this}
1039 */
1040 public HttpHeaders setAll(HttpHeaders headers) {
1041 requireNonNull(headers, "headers");
1042
1043 if (headers.isEmpty()) {
1044 return this;
1045 }
1046
1047 for (Entry<String, String> entry : headers) {
1048 set(entry.getKey(), entry.getValue());
1049 }
1050 return this;
1051 }
1052
1053 /**
1054 * Set the {@code name} to {@code value}. This will remove all previous values associated with {@code name}.
1055 * @param name The name to modify
1056 * @param value The value
1057 * @return {@code this}
1058 */
1059 public abstract HttpHeaders setInt(CharSequence name, int value);
1060
1061 /**
1062 * Set the {@code name} to {@code value}. This will remove all previous values associated with {@code name}.
1063 * @param name The name to modify
1064 * @param value The value
1065 * @return {@code this}
1066 */
1067 public abstract HttpHeaders setShort(CharSequence name, short value);
1068
1069 /**
1070 * @see #remove(CharSequence)
1071 */
1072 public abstract HttpHeaders remove(String name);
1073
1074 /**
1075 * Removes the header with the specified name.
1076 *
1077 * @param name The name of the header to remove
1078 * @return {@code this}
1079 */
1080 public HttpHeaders remove(CharSequence name) {
1081 return remove(name.toString());
1082 }
1083
1084 /**
1085 * Removes all headers from this {@link HttpMessage}.
1086 *
1087 * @return {@code this}
1088 */
1089 public abstract HttpHeaders clear();
1090
1091 /**
1092 * @see #contains(CharSequence, CharSequence, boolean)
1093 */
1094 public boolean contains(String name, String value, boolean ignoreCase) {
1095 Iterator<String> valueIterator = valueStringIterator(name);
1096 if (ignoreCase) {
1097 while (valueIterator.hasNext()) {
1098 if (valueIterator.next().equalsIgnoreCase(value)) {
1099 return true;
1100 }
1101 }
1102 } else {
1103 while (valueIterator.hasNext()) {
1104 if (valueIterator.next().equals(value)) {
1105 return true;
1106 }
1107 }
1108 }
1109 return false;
1110 }
1111
1112 /**
1113 * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise.
1114 * This also handles multiple values that are separated with a {@code ,}.
1115 * <p>
1116 * If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value.
1117 * @param name the name of the header to find
1118 * @param value the value of the header to find
1119 * @param ignoreCase {@code true} then a case insensitive compare is run to compare values.
1120 * otherwise a case sensitive compare is run to compare values.
1121 */
1122 public boolean containsValue(CharSequence name, CharSequence value, boolean ignoreCase) {
1123 Iterator<? extends CharSequence> itr = valueCharSequenceIterator(name);
1124 while (itr.hasNext()) {
1125 if (containsCommaSeparatedTrimmed(itr.next(), value, ignoreCase)) {
1126 return true;
1127 }
1128 }
1129 return false;
1130 }
1131
1132 private static boolean containsCommaSeparatedTrimmed(CharSequence rawNext, CharSequence expected,
1133 boolean ignoreCase) {
1134 int begin = 0;
1135 int end;
1136 if (ignoreCase) {
1137 if ((end = AsciiString.indexOf(rawNext, ',', begin)) == -1) {
1138 return contentEqualsIgnoreCase(trim(rawNext), expected);
1139 } else {
1140 do {
1141 if (contentEqualsIgnoreCase(trim(rawNext.subSequence(begin, end)), expected)) {
1142 return true;
1143 }
1144 begin = end + 1;
1145 } while ((end = AsciiString.indexOf(rawNext, ',', begin)) != -1);
1146
1147 if (begin < rawNext.length()) {
1148 return contentEqualsIgnoreCase(trim(rawNext.subSequence(begin, rawNext.length())), expected);
1149 }
1150 }
1151 } else {
1152 if ((end = AsciiString.indexOf(rawNext, ',', begin)) == -1) {
1153 return contentEquals(trim(rawNext), expected);
1154 } else {
1155 do {
1156 if (contentEquals(trim(rawNext.subSequence(begin, end)), expected)) {
1157 return true;
1158 }
1159 begin = end + 1;
1160 } while ((end = AsciiString.indexOf(rawNext, ',', begin)) != -1);
1161
1162 if (begin < rawNext.length()) {
1163 return contentEquals(trim(rawNext.subSequence(begin, rawNext.length())), expected);
1164 }
1165 }
1166 }
1167 return false;
1168 }
1169
1170 /**
1171 * {@link Headers#get(Object)} and convert the result to a {@link String}.
1172 * @param name the name of the header to retrieve
1173 * @return the first header value if the header is found. {@code null} if there's no such header.
1174 */
1175 public final String getAsString(CharSequence name) {
1176 return get(name);
1177 }
1178
1179 /**
1180 * {@link Headers#getAll(Object)} and convert each element of {@link List} to a {@link String}.
1181 * @param name the name of the header to retrieve
1182 * @return a {@link List} of header values or an empty {@link List} if no values are found.
1183 */
1184 public final List<String> getAllAsString(CharSequence name) {
1185 return getAll(name);
1186 }
1187
1188 /**
1189 * {@link Iterator} that converts each {@link Entry}'s key and value to a {@link String}.
1190 */
1191 public final Iterator<Entry<String, String>> iteratorAsString() {
1192 return iterator();
1193 }
1194
1195 /**
1196 * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise.
1197 * <p>
1198 * If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value.
1199 * @param name the name of the header to find
1200 * @param value the value of the header to find
1201 * @param ignoreCase {@code true} then a case insensitive compare is run to compare values.
1202 * otherwise a case sensitive compare is run to compare values.
1203 */
1204 public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) {
1205 return contains(name.toString(), value.toString(), ignoreCase);
1206 }
1207
1208 @Override
1209 public String toString() {
1210 return HeadersUtils.toString(getClass(), iteratorCharSequence(), size());
1211 }
1212
1213 /**
1214 * Returns a deep copy of the passed in {@link HttpHeaders}.
1215 */
1216 public HttpHeaders copy() {
1217 return new DefaultHttpHeaders().set(this);
1218 }
1219 }