View Javadoc
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 }