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.netty.handler.codec.http;
17  
18  import io.netty.buffer.ByteBuf;
19  import io.netty.buffer.ByteBufUtil;
20  import io.netty.handler.codec.DateFormatter;
21  import io.netty.handler.codec.Headers;
22  import io.netty.handler.codec.HeadersUtils;
23  import io.netty.util.AsciiString;
24  import io.netty.util.CharsetUtil;
25  import io.netty.util.internal.ObjectUtil;
26  
27  import java.text.ParseException;
28  import java.util.Calendar;
29  import java.util.Date;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Map.Entry;
34  import java.util.Set;
35  
36  import static io.netty.util.AsciiString.contentEquals;
37  import static io.netty.util.AsciiString.contentEqualsIgnoreCase;
38  import static io.netty.util.AsciiString.trim;
39  import static io.netty.util.internal.ObjectUtil.checkNotNull;
40  
41  /**
42   * Provides the constants for the standard HTTP header names and values and
43   * commonly used utility methods that accesses an {@link HttpMessage}.
44   */
45  public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>> {
46      /**
47       * @deprecated Use {@link EmptyHttpHeaders#INSTANCE}.
48       * <p>
49       * The instance is instantiated here to break the cyclic static initialization between {@link EmptyHttpHeaders} and
50       * {@link HttpHeaders}. The issue is that if someone accesses {@link EmptyHttpHeaders#INSTANCE} before
51       * {@link HttpHeaders#EMPTY_HEADERS} then {@link HttpHeaders#EMPTY_HEADERS} will be {@code null}.
52       */
53      @Deprecated
54      public static final HttpHeaders EMPTY_HEADERS = EmptyHttpHeaders.instance();
55  
56      /**
57       * @deprecated Use {@link HttpHeaderNames} instead.
58       *
59       * Standard HTTP header names.
60       */
61      @Deprecated
62      public static final class Names {
63          /**
64           * {@code "Accept"}
65           */
66          public static final String ACCEPT = "Accept";
67          /**
68           * {@code "Accept-Charset"}
69           */
70          public static final String ACCEPT_CHARSET = "Accept-Charset";
71          /**
72           * {@code "Accept-Encoding"}
73           */
74          public static final String ACCEPT_ENCODING = "Accept-Encoding";
75          /**
76           * {@code "Accept-Language"}
77           */
78          public static final String ACCEPT_LANGUAGE = "Accept-Language";
79          /**
80           * {@code "Accept-Ranges"}
81           */
82          public static final String ACCEPT_RANGES = "Accept-Ranges";
83          /**
84           * {@code "Accept-Patch"}
85           */
86          public static final String ACCEPT_PATCH = "Accept-Patch";
87          /**
88           * {@code "Access-Control-Allow-Credentials"}
89           */
90          public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
91          /**
92           * {@code "Access-Control-Allow-Headers"}
93           */
94          public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
95          /**
96           * {@code "Access-Control-Allow-Methods"}
97           */
98          public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
99          /**
100          * {@code "Access-Control-Allow-Origin"}
101          */
102         public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
103         /**
104          * {@code "Access-Control-Expose-Headers"}
105          */
106         public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
107         /**
108          * {@code "Access-Control-Max-Age"}
109          */
110         public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
111         /**
112          * {@code "Access-Control-Request-Headers"}
113          */
114         public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
115         /**
116          * {@code "Access-Control-Request-Method"}
117          */
118         public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
119         /**
120          * {@code "Age"}
121          */
122         public static final String AGE = "Age";
123         /**
124          * {@code "Allow"}
125          */
126         public static final String ALLOW = "Allow";
127         /**
128          * {@code "Authorization"}
129          */
130         public static final String AUTHORIZATION = "Authorization";
131         /**
132          * {@code "Cache-Control"}
133          */
134         public static final String CACHE_CONTROL = "Cache-Control";
135         /**
136          * {@code "Connection"}
137          */
138         public static final String CONNECTION = "Connection";
139         /**
140          * {@code "Content-Base"}
141          */
142         public static final String CONTENT_BASE = "Content-Base";
143         /**
144          * {@code "Content-Encoding"}
145          */
146         public static final String CONTENT_ENCODING = "Content-Encoding";
147         /**
148          * {@code "Content-Language"}
149          */
150         public static final String CONTENT_LANGUAGE = "Content-Language";
151         /**
152          * {@code "Content-Length"}
153          */
154         public static final String CONTENT_LENGTH = "Content-Length";
155         /**
156          * {@code "Content-Location"}
157          */
158         public static final String CONTENT_LOCATION = "Content-Location";
159         /**
160          * {@code "Content-Transfer-Encoding"}
161          */
162         public static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
163         /**
164          * {@code "Content-MD5"}
165          */
166         public static final String CONTENT_MD5 = "Content-MD5";
167         /**
168          * {@code "Content-Range"}
169          */
170         public static final String CONTENT_RANGE = "Content-Range";
171         /**
172          * {@code "Content-Type"}
173          */
174         public static final String CONTENT_TYPE = "Content-Type";
175         /**
176          * {@code "Cookie"}
177          */
178         public static final String COOKIE = "Cookie";
179         /**
180          * {@code "Date"}
181          */
182         public static final String DATE = "Date";
183         /**
184          * {@code "ETag"}
185          */
186         public static final String ETAG = "ETag";
187         /**
188          * {@code "Expect"}
189          */
190         public static final String EXPECT = "Expect";
191         /**
192          * {@code "Expires"}
193          */
194         public static final String EXPIRES = "Expires";
195         /**
196          * {@code "From"}
197          */
198         public static final String FROM = "From";
199         /**
200          * {@code "Host"}
201          */
202         public static final String HOST = "Host";
203         /**
204          * {@code "If-Match"}
205          */
206         public static final String IF_MATCH = "If-Match";
207         /**
208          * {@code "If-Modified-Since"}
209          */
210         public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
211         /**
212          * {@code "If-None-Match"}
213          */
214         public static final String IF_NONE_MATCH = "If-None-Match";
215         /**
216          * {@code "If-Range"}
217          */
218         public static final String IF_RANGE = "If-Range";
219         /**
220          * {@code "If-Unmodified-Since"}
221          */
222         public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
223         /**
224          * {@code "Last-Modified"}
225          */
226         public static final String LAST_MODIFIED = "Last-Modified";
227         /**
228          * {@code "Location"}
229          */
230         public static final String LOCATION = "Location";
231         /**
232          * {@code "Max-Forwards"}
233          */
234         public static final String MAX_FORWARDS = "Max-Forwards";
235         /**
236          * {@code "Origin"}
237          */
238         public static final String ORIGIN = "Origin";
239         /**
240          * {@code "Pragma"}
241          */
242         public static final String PRAGMA = "Pragma";
243         /**
244          * {@code "Proxy-Authenticate"}
245          */
246         public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
247         /**
248          * {@code "Proxy-Authorization"}
249          */
250         public static final String PROXY_AUTHORIZATION = "Proxy-Authorization";
251         /**
252          * {@code "Range"}
253          */
254         public static final String RANGE = "Range";
255         /**
256          * {@code "Referer"}
257          */
258         public static final String REFERER = "Referer";
259         /**
260          * {@code "Retry-After"}
261          */
262         public static final String RETRY_AFTER = "Retry-After";
263         /**
264          * {@code "Sec-WebSocket-Key1"}
265          */
266         public static final String SEC_WEBSOCKET_KEY1 = "Sec-WebSocket-Key1";
267         /**
268          * {@code "Sec-WebSocket-Key2"}
269          */
270         public static final String SEC_WEBSOCKET_KEY2 = "Sec-WebSocket-Key2";
271         /**
272          * {@code "Sec-WebSocket-Location"}
273          */
274         public static final String SEC_WEBSOCKET_LOCATION = "Sec-WebSocket-Location";
275         /**
276          * {@code "Sec-WebSocket-Origin"}
277          */
278         public static final String SEC_WEBSOCKET_ORIGIN = "Sec-WebSocket-Origin";
279         /**
280          * {@code "Sec-WebSocket-Protocol"}
281          */
282         public static final String SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol";
283         /**
284          * {@code "Sec-WebSocket-Version"}
285          */
286         public static final String SEC_WEBSOCKET_VERSION = "Sec-WebSocket-Version";
287         /**
288          * {@code "Sec-WebSocket-Key"}
289          */
290         public static final String SEC_WEBSOCKET_KEY = "Sec-WebSocket-Key";
291         /**
292          * {@code "Sec-WebSocket-Accept"}
293          */
294         public static final String SEC_WEBSOCKET_ACCEPT = "Sec-WebSocket-Accept";
295         /**
296          * {@code "Server"}
297          */
298         public static final String SERVER = "Server";
299         /**
300          * {@code "Set-Cookie"}
301          */
302         public static final String SET_COOKIE = "Set-Cookie";
303         /**
304          * {@code "Set-Cookie2"}
305          */
306         public static final String SET_COOKIE2 = "Set-Cookie2";
307         /**
308          * {@code "TE"}
309          */
310         public static final String TE = "TE";
311         /**
312          * {@code "Trailer"}
313          */
314         public static final String TRAILER = "Trailer";
315         /**
316          * {@code "Transfer-Encoding"}
317          */
318         public static final String TRANSFER_ENCODING = "Transfer-Encoding";
319         /**
320          * {@code "Upgrade"}
321          */
322         public static final String UPGRADE = "Upgrade";
323         /**
324          * {@code "User-Agent"}
325          */
326         public static final String USER_AGENT = "User-Agent";
327         /**
328          * {@code "Vary"}
329          */
330         public static final String VARY = "Vary";
331         /**
332          * {@code "Via"}
333          */
334         public static final String VIA = "Via";
335         /**
336          * {@code "Warning"}
337          */
338         public static final String WARNING = "Warning";
339         /**
340          * {@code "WebSocket-Location"}
341          */
342         public static final String WEBSOCKET_LOCATION = "WebSocket-Location";
343         /**
344          * {@code "WebSocket-Origin"}
345          */
346         public static final String WEBSOCKET_ORIGIN = "WebSocket-Origin";
347         /**
348          * {@code "WebSocket-Protocol"}
349          */
350         public static final String WEBSOCKET_PROTOCOL = "WebSocket-Protocol";
351         /**
352          * {@code "WWW-Authenticate"}
353          */
354         public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
355 
356         private Names() {
357         }
358     }
359 
360     /**
361      * @deprecated Use {@link HttpHeaderValues} instead.
362      *
363      * Standard HTTP header values.
364      */
365     @Deprecated
366     public static final class Values {
367         /**
368          * {@code "application/json"}
369          */
370         public static final String APPLICATION_JSON = "application/json";
371         /**
372          * {@code "application/x-www-form-urlencoded"}
373          */
374         public static final String APPLICATION_X_WWW_FORM_URLENCODED =
375             "application/x-www-form-urlencoded";
376         /**
377          * {@code "base64"}
378          */
379         public static final String BASE64 = "base64";
380         /**
381          * {@code "binary"}
382          */
383         public static final String BINARY = "binary";
384         /**
385          * {@code "boundary"}
386          */
387         public static final String BOUNDARY = "boundary";
388         /**
389          * {@code "bytes"}
390          */
391         public static final String BYTES = "bytes";
392         /**
393          * {@code "charset"}
394          */
395         public static final String CHARSET = "charset";
396         /**
397          * {@code "chunked"}
398          */
399         public static final String CHUNKED = "chunked";
400         /**
401          * {@code "close"}
402          */
403         public static final String CLOSE = "close";
404         /**
405          * {@code "compress"}
406          */
407         public static final String COMPRESS = "compress";
408         /**
409          * {@code "100-continue"}
410          */
411         public static final String CONTINUE =  "100-continue";
412         /**
413          * {@code "deflate"}
414          */
415         public static final String DEFLATE = "deflate";
416         /**
417          * {@code "gzip"}
418          */
419         public static final String GZIP = "gzip";
420         /**
421          * {@code "gzip,deflate"}
422          */
423         public static final String GZIP_DEFLATE = "gzip,deflate";
424         /**
425          * {@code "identity"}
426          */
427         public static final String IDENTITY = "identity";
428         /**
429          * {@code "keep-alive"}
430          */
431         public static final String KEEP_ALIVE = "keep-alive";
432         /**
433          * {@code "max-age"}
434          */
435         public static final String MAX_AGE = "max-age";
436         /**
437          * {@code "max-stale"}
438          */
439         public static final String MAX_STALE = "max-stale";
440         /**
441          * {@code "min-fresh"}
442          */
443         public static final String MIN_FRESH = "min-fresh";
444         /**
445          * {@code "multipart/form-data"}
446          */
447         public static final String MULTIPART_FORM_DATA = "multipart/form-data";
448         /**
449          * {@code "must-revalidate"}
450          */
451         public static final String MUST_REVALIDATE = "must-revalidate";
452         /**
453          * {@code "no-cache"}
454          */
455         public static final String NO_CACHE = "no-cache";
456         /**
457          * {@code "no-store"}
458          */
459         public static final String NO_STORE = "no-store";
460         /**
461          * {@code "no-transform"}
462          */
463         public static final String NO_TRANSFORM = "no-transform";
464         /**
465          * {@code "none"}
466          */
467         public static final String NONE = "none";
468         /**
469          * {@code "only-if-cached"}
470          */
471         public static final String ONLY_IF_CACHED = "only-if-cached";
472         /**
473          * {@code "private"}
474          */
475         public static final String PRIVATE = "private";
476         /**
477          * {@code "proxy-revalidate"}
478          */
479         public static final String PROXY_REVALIDATE = "proxy-revalidate";
480         /**
481          * {@code "public"}
482          */
483         public static final String PUBLIC = "public";
484         /**
485          * {@code "quoted-printable"}
486          */
487         public static final String QUOTED_PRINTABLE = "quoted-printable";
488         /**
489          * {@code "s-maxage"}
490          */
491         public static final String S_MAXAGE = "s-maxage";
492         /**
493          * {@code "trailers"}
494          */
495         public static final String TRAILERS = "trailers";
496         /**
497          * {@code "Upgrade"}
498          */
499         public static final String UPGRADE = "Upgrade";
500         /**
501          * {@code "WebSocket"}
502          */
503         public static final String WEBSOCKET = "WebSocket";
504 
505         private Values() {
506         }
507     }
508 
509     /**
510      * @deprecated Use {@link HttpUtil#isKeepAlive(HttpMessage)} instead.
511      *
512      * Returns {@code true} if and only if the connection can remain open and
513      * thus 'kept alive'.  This methods respects the value of the
514      * {@code "Connection"} header first and then the return value of
515      * {@link HttpVersion#isKeepAliveDefault()}.
516      */
517     @Deprecated
518     public static boolean isKeepAlive(HttpMessage message) {
519         return HttpUtil.isKeepAlive(message);
520     }
521 
522     /**
523      * @deprecated Use {@link HttpUtil#setKeepAlive(HttpMessage, boolean)} instead.
524      *
525      * Sets the value of the {@code "Connection"} header depending on the
526      * protocol version of the specified message.  This getMethod sets or removes
527      * the {@code "Connection"} header depending on what the default keep alive
528      * mode of the message's protocol version is, as specified by
529      * {@link HttpVersion#isKeepAliveDefault()}.
530      * <ul>
531      * <li>If the connection is kept alive by default:
532      *     <ul>
533      *     <li>set to {@code "close"} if {@code keepAlive} is {@code false}.</li>
534      *     <li>remove otherwise.</li>
535      *     </ul></li>
536      * <li>If the connection is closed by default:
537      *     <ul>
538      *     <li>set to {@code "keep-alive"} if {@code keepAlive} is {@code true}.</li>
539      *     <li>remove otherwise.</li>
540      *     </ul></li>
541      * </ul>
542      */
543     @Deprecated
544     public static void setKeepAlive(HttpMessage message, boolean keepAlive) {
545         HttpUtil.setKeepAlive(message, keepAlive);
546     }
547 
548     /**
549      * @deprecated Use {@link #get(CharSequence)} instead.
550      */
551     @Deprecated
552     public static String getHeader(HttpMessage message, String name) {
553         return message.headers().get(name);
554     }
555 
556     /**
557      * @deprecated Use {@link #get(CharSequence)} instead.
558      *
559      * Returns the header value with the specified header name.  If there are
560      * more than one header value for the specified header name, the first
561      * value is returned.
562      *
563      * @return the header value or {@code null} if there is no such header
564      */
565     @Deprecated
566     public static String getHeader(HttpMessage message, CharSequence name) {
567         return message.headers().get(name);
568     }
569 
570     /**
571      * @deprecated Use {@link #get(CharSequence, String)} instead.
572      *
573      * @see #getHeader(HttpMessage, CharSequence, String)
574      */
575     @Deprecated
576     public static String getHeader(HttpMessage message, String name, String defaultValue) {
577         return message.headers().get(name, defaultValue);
578     }
579 
580     /**
581      * @deprecated Use {@link #get(CharSequence, String)} instead.
582      *
583      * Returns the header value with the specified header name.  If there are
584      * more than one header value for the specified header name, the first
585      * value is returned.
586      *
587      * @return the header value or the {@code defaultValue} if there is no such
588      *         header
589      */
590     @Deprecated
591     public static String getHeader(HttpMessage message, CharSequence name, String defaultValue) {
592         return message.headers().get(name, defaultValue);
593     }
594 
595     /**
596      * @deprecated Use {@link #set(CharSequence, Object)} instead.
597      *
598      * @see #setHeader(HttpMessage, CharSequence, Object)
599      */
600     @Deprecated
601     public static void setHeader(HttpMessage message, String name, Object value) {
602         message.headers().set(name, value);
603     }
604 
605     /**
606      * @deprecated Use {@link #set(CharSequence, Object)} instead.
607      *
608      * Sets a new header with the specified name and value.  If there is an
609      * existing header with the same name, the existing header is removed.
610      * If the specified value is not a {@link String}, it is converted into a
611      * {@link String} by {@link Object#toString()}, except for {@link Date}
612      * and {@link Calendar} which are formatted to the date format defined in
613      * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
614      */
615     @Deprecated
616     public static void setHeader(HttpMessage message, CharSequence name, Object value) {
617         message.headers().set(name, value);
618     }
619 
620     /**
621      * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
622      *
623      * @see #setHeader(HttpMessage, CharSequence, Iterable)
624      */
625     @Deprecated
626     public static void setHeader(HttpMessage message, String name, Iterable<?> values) {
627         message.headers().set(name, values);
628     }
629 
630     /**
631      * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
632      *
633      * Sets a new header with the specified name and values.  If there is an
634      * existing header with the same name, the existing header is removed.
635      * This getMethod can be represented approximately as the following code:
636      * <pre>
637      * removeHeader(message, name);
638      * for (Object v: values) {
639      *     if (v == null) {
640      *         break;
641      *     }
642      *     addHeader(message, name, v);
643      * }
644      * </pre>
645      */
646     @Deprecated
647     public static void setHeader(HttpMessage message, CharSequence name, Iterable<?> values) {
648         message.headers().set(name, values);
649     }
650 
651     /**
652      * @deprecated Use {@link #add(CharSequence, Object)} instead.
653      *
654      * @see #addHeader(HttpMessage, CharSequence, Object)
655      */
656     @Deprecated
657     public static void addHeader(HttpMessage message, String name, Object value) {
658         message.headers().add(name, value);
659     }
660 
661     /**
662      * @deprecated Use {@link #add(CharSequence, Object)} instead.
663      *
664      * Adds a new header with the specified name and value.
665      * If the specified value is not a {@link String}, it is converted into a
666      * {@link String} by {@link Object#toString()}, except for {@link Date}
667      * and {@link Calendar} which are formatted to the date format defined in
668      * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
669      */
670     @Deprecated
671     public static void addHeader(HttpMessage message, CharSequence name, Object value) {
672         message.headers().add(name, value);
673     }
674 
675     /**
676      * @deprecated Use {@link #remove(CharSequence)} instead.
677      *
678      * @see #removeHeader(HttpMessage, CharSequence)
679      */
680     @Deprecated
681     public static void removeHeader(HttpMessage message, String name) {
682         message.headers().remove(name);
683     }
684 
685     /**
686      * @deprecated Use {@link #remove(CharSequence)} instead.
687      *
688      * Removes the header with the specified name.
689      */
690     @Deprecated
691     public static void removeHeader(HttpMessage message, CharSequence name) {
692         message.headers().remove(name);
693     }
694 
695     /**
696      * @deprecated Use {@link #clear()} instead.
697      *
698      * Removes all headers from the specified message.
699      */
700     @Deprecated
701     public static void clearHeaders(HttpMessage message) {
702         message.headers().clear();
703     }
704 
705     /**
706      * @deprecated Use {@link #getInt(CharSequence)} instead.
707      *
708      * @see #getIntHeader(HttpMessage, CharSequence)
709      */
710     @Deprecated
711     public static int getIntHeader(HttpMessage message, String name) {
712         return getIntHeader(message, (CharSequence) name);
713     }
714 
715     /**
716      * @deprecated Use {@link #getInt(CharSequence)} instead.
717      *
718      * Returns the integer header value with the specified header name.  If
719      * there are more than one header value for the specified header name, the
720      * first value is returned.
721      *
722      * @return the header value
723      * @throws NumberFormatException
724      *         if there is no such header or the header value is not a number
725      */
726     @Deprecated
727     public static int getIntHeader(HttpMessage message, CharSequence name) {
728         String value = message.headers().get(name);
729         if (value == null) {
730             throw new NumberFormatException("header not found: " + name);
731         }
732         return Integer.parseInt(value);
733     }
734 
735     /**
736      * @deprecated Use {@link #getInt(CharSequence, int)} instead.
737      *
738      * @see #getIntHeader(HttpMessage, CharSequence, int)
739      */
740     @Deprecated
741     public static int getIntHeader(HttpMessage message, String name, int defaultValue) {
742         return message.headers().getInt(name, defaultValue);
743     }
744 
745     /**
746      * @deprecated Use {@link #getInt(CharSequence, int)} instead.
747      *
748      * Returns the integer header value with the specified header name.  If
749      * there are more than one header value for the specified header name, the
750      * first value is returned.
751      *
752      * @return the header value or the {@code defaultValue} if there is no such
753      *         header or the header value is not a number
754      */
755     @Deprecated
756     public static int getIntHeader(HttpMessage message, CharSequence name, int defaultValue) {
757         return message.headers().getInt(name, defaultValue);
758     }
759 
760     /**
761      * @deprecated Use {@link #setInt(CharSequence, int)} instead.
762      *
763      * @see #setIntHeader(HttpMessage, CharSequence, int)
764      */
765     @Deprecated
766     public static void setIntHeader(HttpMessage message, String name, int value) {
767         message.headers().setInt(name, value);
768     }
769 
770     /**
771      * @deprecated Use {@link #setInt(CharSequence, int)} instead.
772      *
773      * Sets a new integer header with the specified name and value.  If there
774      * is an existing header with the same name, the existing header is removed.
775      */
776     @Deprecated
777     public static void setIntHeader(HttpMessage message, CharSequence name, int value) {
778         message.headers().setInt(name, value);
779     }
780 
781     /**
782      * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
783      *
784      * @see #setIntHeader(HttpMessage, CharSequence, Iterable)
785      */
786     @Deprecated
787     public static void setIntHeader(HttpMessage message, String name, Iterable<Integer> values) {
788         message.headers().set(name, values);
789     }
790 
791     /**
792      * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
793      *
794      * Sets a new integer header with the specified name and values.  If there
795      * is an existing header with the same name, the existing header is removed.
796      */
797     @Deprecated
798     public static void setIntHeader(HttpMessage message, CharSequence name, Iterable<Integer> values) {
799         message.headers().set(name, values);
800     }
801 
802     /**
803      * @deprecated Use {@link #add(CharSequence, Iterable)} instead.
804      *
805      * @see #addIntHeader(HttpMessage, CharSequence, int)
806      */
807     @Deprecated
808     public static void addIntHeader(HttpMessage message, String name, int value) {
809         message.headers().add(name, value);
810     }
811 
812     /**
813      * @deprecated Use {@link #addInt(CharSequence, int)} instead.
814      *
815      * Adds a new integer header with the specified name and value.
816      */
817     @Deprecated
818     public static void addIntHeader(HttpMessage message, CharSequence name, int value) {
819         message.headers().addInt(name, value);
820     }
821 
822     /**
823      * @deprecated Use {@link #getTimeMillis(CharSequence)} instead.
824      *
825      * @see #getDateHeader(HttpMessage, CharSequence)
826      */
827     @Deprecated
828     public static Date getDateHeader(HttpMessage message, String name) throws ParseException {
829         return getDateHeader(message, (CharSequence) name);
830     }
831 
832     /**
833      * @deprecated Use {@link #getTimeMillis(CharSequence)} instead.
834      *
835      * Returns the date header value with the specified header name.  If
836      * there are more than one header value for the specified header name, the
837      * first value is returned.
838      *
839      * @return the header value
840      * @throws ParseException
841      *         if there is no such header or the header value is not a formatted date
842      */
843     @Deprecated
844     public static Date getDateHeader(HttpMessage message, CharSequence name) throws ParseException {
845         String value = message.headers().get(name);
846         if (value == null) {
847             throw new ParseException("header not found: " + name, 0);
848         }
849         Date date = DateFormatter.parseHttpDate(value);
850         if (date == null) {
851             throw new ParseException("header can't be parsed into a Date: " + value, 0);
852         }
853         return date;
854     }
855 
856     /**
857      * @deprecated Use {@link #getTimeMillis(CharSequence, long)} instead.
858      *
859      * @see #getDateHeader(HttpMessage, CharSequence, Date)
860      */
861     @Deprecated
862     public static Date getDateHeader(HttpMessage message, String name, Date defaultValue) {
863         return getDateHeader(message, (CharSequence) name, defaultValue);
864     }
865 
866     /**
867      * @deprecated Use {@link #getTimeMillis(CharSequence, long)} instead.
868      *
869      * Returns the date header value with the specified header name.  If
870      * there are more than one header value for the specified header name, the
871      * first value is returned.
872      *
873      * @return the header value or the {@code defaultValue} if there is no such
874      *         header or the header value is not a formatted date
875      */
876     @Deprecated
877     public static Date getDateHeader(HttpMessage message, CharSequence name, Date defaultValue) {
878         final String value = getHeader(message, name);
879         Date date = DateFormatter.parseHttpDate(value);
880         return date != null ? date : defaultValue;
881     }
882 
883     /**
884      * @deprecated Use {@link #set(CharSequence, Object)} instead.
885      *
886      * @see #setDateHeader(HttpMessage, CharSequence, Date)
887      */
888     @Deprecated
889     public static void setDateHeader(HttpMessage message, String name, Date value) {
890         setDateHeader(message, (CharSequence) name, value);
891     }
892 
893     /**
894      * @deprecated Use {@link #set(CharSequence, Object)} instead.
895      *
896      * Sets a new date header with the specified name and value.  If there
897      * is an existing header with the same name, the existing header is removed.
898      * The specified value is formatted as defined in
899      * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>
900      */
901     @Deprecated
902     public static void setDateHeader(HttpMessage message, CharSequence name, Date value) {
903         if (value != null) {
904             message.headers().set(name, DateFormatter.format(value));
905         } else {
906             message.headers().set(name, null);
907         }
908     }
909 
910     /**
911      * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
912      *
913      * @see #setDateHeader(HttpMessage, CharSequence, Iterable)
914      */
915     @Deprecated
916     public static void setDateHeader(HttpMessage message, String name, Iterable<Date> values) {
917         message.headers().set(name, values);
918     }
919 
920     /**
921      * @deprecated Use {@link #set(CharSequence, Iterable)} instead.
922      *
923      * Sets a new date header with the specified name and values.  If there
924      * is an existing header with the same name, the existing header is removed.
925      * The specified values are formatted as defined in
926      * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>
927      */
928     @Deprecated
929     public static void setDateHeader(HttpMessage message, CharSequence name, Iterable<Date> values) {
930         message.headers().set(name, values);
931     }
932 
933     /**
934      * @deprecated Use {@link #add(CharSequence, Object)} instead.
935      *
936      * @see #addDateHeader(HttpMessage, CharSequence, Date)
937      */
938     @Deprecated
939     public static void addDateHeader(HttpMessage message, String name, Date value) {
940         message.headers().add(name, value);
941     }
942 
943     /**
944      * @deprecated Use {@link #add(CharSequence, Object)} instead.
945      *
946      * Adds a new date header with the specified name and value.  The specified
947      * value is formatted as defined in
948      * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>
949      */
950     @Deprecated
951     public static void addDateHeader(HttpMessage message, CharSequence name, Date value) {
952         message.headers().add(name, value);
953     }
954 
955     /**
956      * @deprecated Use {@link HttpUtil#getContentLength(HttpMessage)} instead.
957      *
958      * Returns the length of the content.  Please note that this value is
959      * not retrieved from {@link HttpContent#content()} but from the
960      * {@code "Content-Length"} header, and thus they are independent from each
961      * other.
962      *
963      * @return the content length
964      *
965      * @throws NumberFormatException
966      *         if the message does not have the {@code "Content-Length"} header
967      *         or its value is not a number
968      */
969     @Deprecated
970     public static long getContentLength(HttpMessage message) {
971         return HttpUtil.getContentLength(message);
972     }
973 
974     /**
975      * @deprecated Use {@link HttpUtil#getContentLength(HttpMessage, long)} instead.
976      *
977      * Returns the length of the content.  Please note that this value is
978      * not retrieved from {@link HttpContent#content()} but from the
979      * {@code "Content-Length"} header, and thus they are independent from each
980      * other.
981      *
982      * @return the content length or {@code defaultValue} if this message does
983      *         not have the {@code "Content-Length"} header or its value is not
984      *         a number
985      */
986     @Deprecated
987     public static long getContentLength(HttpMessage message, long defaultValue) {
988         return HttpUtil.getContentLength(message, defaultValue);
989     }
990 
991     /**
992      * @deprecated Use {@link HttpUtil#setContentLength(HttpMessage, long)} instead.
993      */
994     @Deprecated
995     public static void setContentLength(HttpMessage message, long length) {
996         HttpUtil.setContentLength(message, length);
997     }
998 
999     /**
1000      * @deprecated Use {@link #get(CharSequence)} instead.
1001      *
1002      * Returns the value of the {@code "Host"} header.
1003      */
1004     @Deprecated
1005     public static String getHost(HttpMessage message) {
1006         return message.headers().get(HttpHeaderNames.HOST);
1007     }
1008 
1009     /**
1010      * @deprecated Use {@link #get(CharSequence, String)} instead.
1011      *
1012      * Returns the value of the {@code "Host"} header.  If there is no such
1013      * header, the {@code defaultValue} is returned.
1014      */
1015     @Deprecated
1016     public static String getHost(HttpMessage message, String defaultValue) {
1017         return message.headers().get(HttpHeaderNames.HOST, defaultValue);
1018     }
1019 
1020     /**
1021      * @deprecated Use {@link #set(CharSequence, Object)} instead.
1022      *
1023      * @see #setHost(HttpMessage, CharSequence)
1024      */
1025     @Deprecated
1026     public static void setHost(HttpMessage message, String value) {
1027         message.headers().set(HttpHeaderNames.HOST, value);
1028     }
1029 
1030     /**
1031      * @deprecated Use {@link #set(CharSequence, Object)} instead.
1032      *
1033      * Sets the {@code "Host"} header.
1034      */
1035     @Deprecated
1036     public static void setHost(HttpMessage message, CharSequence value) {
1037         message.headers().set(HttpHeaderNames.HOST, value);
1038     }
1039 
1040     /**
1041      * @deprecated Use {@link #getTimeMillis(CharSequence)} instead.
1042      *
1043      * Returns the value of the {@code "Date"} header.
1044      *
1045      * @throws ParseException
1046      *         if there is no such header or the header value is not a formatted date
1047      */
1048     @Deprecated
1049     public static Date getDate(HttpMessage message) throws ParseException {
1050         return getDateHeader(message, HttpHeaderNames.DATE);
1051     }
1052 
1053     /**
1054      * @deprecated Use {@link #getTimeMillis(CharSequence, long)} instead.
1055      *
1056      * Returns the value of the {@code "Date"} header. If there is no such
1057      * header or the header is not a formatted date, the {@code defaultValue}
1058      * is returned.
1059      */
1060     @Deprecated
1061     public static Date getDate(HttpMessage message, Date defaultValue) {
1062         return getDateHeader(message, HttpHeaderNames.DATE, defaultValue);
1063     }
1064 
1065     /**
1066      * @deprecated Use {@link #set(CharSequence, Object)} instead.
1067      *
1068      * Sets the {@code "Date"} header.
1069      */
1070     @Deprecated
1071     public static void setDate(HttpMessage message, Date value) {
1072         message.headers().set(HttpHeaderNames.DATE, value);
1073     }
1074 
1075     /**
1076      * @deprecated Use {@link HttpUtil#is100ContinueExpected(HttpMessage)} instead.
1077      *
1078      * Returns {@code true} if and only if the specified message contains the
1079      * {@code "Expect: 100-continue"} header.
1080      */
1081     @Deprecated
1082     public static boolean is100ContinueExpected(HttpMessage message) {
1083         return HttpUtil.is100ContinueExpected(message);
1084     }
1085 
1086     /**
1087      * @deprecated Use {@link HttpUtil#set100ContinueExpected(HttpMessage, boolean)} instead.
1088      *
1089      * Sets the {@code "Expect: 100-continue"} header to the specified message.
1090      * If there is any existing {@code "Expect"} header, they are replaced with
1091      * the new one.
1092      */
1093     @Deprecated
1094     public static void set100ContinueExpected(HttpMessage message) {
1095         HttpUtil.set100ContinueExpected(message, true);
1096     }
1097 
1098     /**
1099      * @deprecated Use {@link HttpUtil#set100ContinueExpected(HttpMessage, boolean)} instead.
1100      *
1101      * Sets or removes the {@code "Expect: 100-continue"} header to / from the
1102      * specified message.  If {@code set} is {@code true},
1103      * the {@code "Expect: 100-continue"} header is set and all other previous
1104      * {@code "Expect"} headers are removed.  Otherwise, all {@code "Expect"}
1105      * headers are removed completely.
1106      */
1107     @Deprecated
1108     public static void set100ContinueExpected(HttpMessage message, boolean set) {
1109         HttpUtil.set100ContinueExpected(message, set);
1110     }
1111 
1112     /**
1113      * @deprecated Use {@link HttpUtil#isTransferEncodingChunked(HttpMessage)} instead.
1114      *
1115      * Checks to see if the transfer encoding in a specified {@link HttpMessage} is chunked
1116      *
1117      * @param message The message to check
1118      * @return True if transfer encoding is chunked, otherwise false
1119      */
1120     @Deprecated
1121     public static boolean isTransferEncodingChunked(HttpMessage message) {
1122         return HttpUtil.isTransferEncodingChunked(message);
1123     }
1124 
1125     /**
1126      * @deprecated Use {@link HttpUtil#setTransferEncodingChunked(HttpMessage, boolean)} instead.
1127      */
1128     @Deprecated
1129     public static void removeTransferEncodingChunked(HttpMessage m) {
1130         HttpUtil.setTransferEncodingChunked(m, false);
1131     }
1132 
1133     /**
1134      * @deprecated Use {@link HttpUtil#setTransferEncodingChunked(HttpMessage, boolean)} instead.
1135      */
1136     @Deprecated
1137     public static void setTransferEncodingChunked(HttpMessage m) {
1138         HttpUtil.setTransferEncodingChunked(m, true);
1139     }
1140 
1141     /**
1142      * @deprecated Use {@link HttpUtil#isContentLengthSet(HttpMessage)} instead.
1143      */
1144     @Deprecated
1145     public static boolean isContentLengthSet(HttpMessage m) {
1146         return HttpUtil.isContentLengthSet(m);
1147     }
1148 
1149     /**
1150      * @deprecated Use {@link AsciiString#contentEqualsIgnoreCase(CharSequence, CharSequence)} instead.
1151      */
1152     @Deprecated
1153     public static boolean equalsIgnoreCase(CharSequence name1, CharSequence name2) {
1154         return contentEqualsIgnoreCase(name1, name2);
1155     }
1156 
1157     @Deprecated
1158     public static void encodeAscii(CharSequence seq, ByteBuf buf) {
1159         if (seq instanceof AsciiString) {
1160             ByteBufUtil.copy((AsciiString) seq, 0, buf, seq.length());
1161         } else {
1162             buf.writeCharSequence(seq, CharsetUtil.US_ASCII);
1163         }
1164     }
1165 
1166     /**
1167      * @deprecated Use {@link AsciiString} instead.
1168      * <p>
1169      * Create a new {@link CharSequence} which is optimized for reuse as {@link HttpHeaders} name or value.
1170      * So if you have a Header name or value that you want to reuse you should make use of this.
1171      */
1172     @Deprecated
1173     public static CharSequence newEntity(String name) {
1174         return new AsciiString(name);
1175     }
1176 
1177     protected HttpHeaders() { }
1178 
1179     /**
1180      * @see #get(CharSequence)
1181      */
1182     public abstract String get(String name);
1183 
1184     /**
1185      * Returns the value of a header with the specified name.  If there are
1186      * more than one values for the specified name, the first value is returned.
1187      *
1188      * @param name The name of the header to search
1189      * @return The first header value or {@code null} if there is no such header
1190      * @see #getAsString(CharSequence)
1191      */
1192     public String get(CharSequence name) {
1193         return get(name.toString());
1194     }
1195 
1196     /**
1197      * Returns the value of a header with the specified name.  If there are
1198      * more than one values for the specified name, the first value is returned.
1199      *
1200      * @param name The name of the header to search
1201      * @return The first header value or {@code defaultValue} if there is no such header
1202      */
1203     public String get(CharSequence name, String defaultValue) {
1204         String value = get(name);
1205         if (value == null) {
1206             return defaultValue;
1207         }
1208         return value;
1209     }
1210 
1211     /**
1212      * Returns the integer value of a header with the specified name. If there are more than one values for the
1213      * specified name, the first value is returned.
1214      *
1215      * @param name the name of the header to search
1216      * @return the first header value if the header is found and its value is an integer. {@code null} if there's no
1217      *         such header or its value is not an integer.
1218      */
1219     public abstract Integer getInt(CharSequence name);
1220 
1221     /**
1222      * Returns the integer value of a header with the specified name. If there are more than one values for the
1223      * specified name, the first value is returned.
1224      *
1225      * @param name the name of the header to search
1226      * @param defaultValue the default value
1227      * @return the first header value if the header is found and its value is an integer. {@code defaultValue} if
1228      *         there's no such header or its value is not an integer.
1229      */
1230     public abstract int getInt(CharSequence name, int defaultValue);
1231 
1232     /**
1233      * Returns the short value of a header with the specified name. If there are more than one values for the
1234      * specified name, the first value is returned.
1235      *
1236      * @param name the name of the header to search
1237      * @return the first header value if the header is found and its value is a short. {@code null} if there's no
1238      *         such header or its value is not a short.
1239      */
1240     public abstract Short getShort(CharSequence name);
1241 
1242     /**
1243      * Returns the short value of a header with the specified name. If there are more than one values for the
1244      * specified name, the first value is returned.
1245      *
1246      * @param name the name of the header to search
1247      * @param defaultValue the default value
1248      * @return the first header value if the header is found and its value is a short. {@code defaultValue} if
1249      *         there's no such header or its value is not a short.
1250      */
1251     public abstract short getShort(CharSequence name, short defaultValue);
1252 
1253     /**
1254      * Returns the date value of a header with the specified name. If there are more than one values for the
1255      * specified name, the first value is returned.
1256      *
1257      * @param name the name of the header to search
1258      * @return the first header value if the header is found and its value is a date. {@code null} if there's no
1259      *         such header or its value is not a date.
1260      */
1261     public abstract Long getTimeMillis(CharSequence name);
1262 
1263     /**
1264      * Returns the date value of a header with the specified name. If there are more than one values for the
1265      * specified name, the first value is returned.
1266      *
1267      * @param name the name of the header to search
1268      * @param defaultValue the default value
1269      * @return the first header value if the header is found and its value is a date. {@code defaultValue} if
1270      *         there's no such header or its value is not a date.
1271      */
1272     public abstract long getTimeMillis(CharSequence name, long defaultValue);
1273 
1274     /**
1275      * @see #getAll(CharSequence)
1276      */
1277     public abstract List<String> getAll(String name);
1278 
1279     /**
1280      * Returns the values of headers with the specified name
1281      *
1282      * @param name The name of the headers to search
1283      * @return A {@link List} of header values which will be empty if no values
1284      *         are found
1285      * @see #getAllAsString(CharSequence)
1286      */
1287     public List<String> getAll(CharSequence name) {
1288         return getAll(name.toString());
1289     }
1290 
1291     /**
1292      * Returns a new {@link List} that contains all headers in this object.  Note that modifying the
1293      * returned {@link List} will not affect the state of this object.  If you intend to enumerate over the header
1294      * entries only, use {@link #iterator()} instead, which has much less overhead.
1295      * @see #iteratorCharSequence()
1296      */
1297     public abstract List<Map.Entry<String, String>> entries();
1298 
1299     /**
1300      * @see #contains(CharSequence)
1301      */
1302     public abstract boolean contains(String name);
1303 
1304     /**
1305      * @deprecated It is preferred to use {@link #iteratorCharSequence()} unless you need {@link String}.
1306      * If {@link String} is required then use {@link #iteratorAsString()}.
1307      */
1308     @Deprecated
1309     @Override
1310     public abstract Iterator<Entry<String, String>> iterator();
1311 
1312     /**
1313      * @return Iterator over the name/value header pairs.
1314      */
1315     public abstract Iterator<Entry<CharSequence, CharSequence>> iteratorCharSequence();
1316 
1317     /**
1318      * Equivalent to {@link #getAll(String)} but it is possible that no intermediate list is generated.
1319      * @param name the name of the header to retrieve
1320      * @return an {@link Iterator} of header values corresponding to {@code name}.
1321      */
1322     public Iterator<String> valueStringIterator(CharSequence name) {
1323         return getAll(name).iterator();
1324     }
1325 
1326     /**
1327      * Equivalent to {@link #getAll(String)} but it is possible that no intermediate list is generated.
1328      * @param name the name of the header to retrieve
1329      * @return an {@link Iterator} of header values corresponding to {@code name}.
1330      */
1331     public Iterator<? extends CharSequence> valueCharSequenceIterator(CharSequence name) {
1332         return valueStringIterator(name);
1333     }
1334 
1335     /**
1336      * Checks to see if there is a header with the specified name
1337      *
1338      * @param name The name of the header to search for
1339      * @return True if at least one header is found
1340      */
1341     public boolean contains(CharSequence name) {
1342         return contains(name.toString());
1343     }
1344 
1345     /**
1346      * Checks if no header exists.
1347      */
1348     public abstract boolean isEmpty();
1349 
1350     /**
1351      * Returns the number of headers in this object.
1352      */
1353     public abstract int size();
1354 
1355     /**
1356      * Returns a new {@link Set} that contains the names of all headers in this object.  Note that modifying the
1357      * returned {@link Set} will not affect the state of this object.  If you intend to enumerate over the header
1358      * entries only, use {@link #iterator()} instead, which has much less overhead.
1359      */
1360     public abstract Set<String> names();
1361 
1362     /**
1363      * @see #add(CharSequence, Object)
1364      */
1365     public abstract HttpHeaders add(String name, Object value);
1366 
1367     /**
1368      * Adds a new header with the specified name and value.
1369      *
1370      * If the specified value is not a {@link String}, it is converted
1371      * into a {@link String} by {@link Object#toString()}, except in the cases
1372      * of {@link Date} and {@link Calendar}, which are formatted to the date
1373      * format defined in <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
1374      *
1375      * @param name The name of the header being added
1376      * @param value The value of the header being added
1377      *
1378      * @return {@code this}
1379      */
1380     public HttpHeaders add(CharSequence name, Object value) {
1381         return add(name.toString(), value);
1382     }
1383 
1384     /**
1385      * @see #add(CharSequence, Iterable)
1386      */
1387     public abstract HttpHeaders add(String name, Iterable<?> values);
1388 
1389     /**
1390      * Adds a new header with the specified name and values.
1391      *
1392      * This getMethod can be represented approximately as the following code:
1393      * <pre>
1394      * for (Object v: values) {
1395      *     if (v == null) {
1396      *         break;
1397      *     }
1398      *     headers.add(name, v);
1399      * }
1400      * </pre>
1401      *
1402      * @param name The name of the headers being set
1403      * @param values The values of the headers being set
1404      * @return {@code this}
1405      */
1406     public HttpHeaders add(CharSequence name, Iterable<?> values) {
1407         return add(name.toString(), values);
1408     }
1409 
1410     /**
1411      * Adds all header entries of the specified {@code headers}.
1412      *
1413      * @return {@code this}
1414      */
1415     public HttpHeaders add(HttpHeaders headers) {
1416         ObjectUtil.checkNotNull(headers, "headers");
1417         for (Map.Entry<String, String> e: headers) {
1418             add(e.getKey(), e.getValue());
1419         }
1420         return this;
1421     }
1422 
1423     /**
1424      * Add the {@code name} to {@code value}.
1425      * @param name The name to modify
1426      * @param value The value
1427      * @return {@code this}
1428      */
1429     public abstract HttpHeaders addInt(CharSequence name, int value);
1430 
1431     /**
1432      * Add the {@code name} to {@code value}.
1433      * @param name The name to modify
1434      * @param value The value
1435      * @return {@code this}
1436      */
1437     public abstract HttpHeaders addShort(CharSequence name, short value);
1438 
1439     /**
1440      * @see #set(CharSequence, Object)
1441      */
1442     public abstract HttpHeaders set(String name, Object value);
1443 
1444     /**
1445      * Sets a header with the specified name and value.
1446      *
1447      * If there is an existing header with the same name, it is removed.
1448      * If the specified value is not a {@link String}, it is converted into a
1449      * {@link String} by {@link Object#toString()}, except for {@link Date}
1450      * and {@link Calendar}, which are formatted to the date format defined in
1451      * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
1452      *
1453      * @param name The name of the header being set
1454      * @param value The value of the header being set
1455      * @return {@code this}
1456      */
1457     public HttpHeaders set(CharSequence name, Object value) {
1458         return set(name.toString(), value);
1459     }
1460 
1461     /**
1462      * @see #set(CharSequence, Iterable)
1463      */
1464     public abstract HttpHeaders set(String name, Iterable<?> values);
1465 
1466     /**
1467      * Sets a header with the specified name and values.
1468      *
1469      * If there is an existing header with the same name, it is removed.
1470      * This getMethod can be represented approximately as the following code:
1471      * <pre>
1472      * headers.remove(name);
1473      * for (Object v: values) {
1474      *     if (v == null) {
1475      *         break;
1476      *     }
1477      *     headers.add(name, v);
1478      * }
1479      * </pre>
1480      *
1481      * @param name The name of the headers being set
1482      * @param values The values of the headers being set
1483      * @return {@code this}
1484      */
1485     public HttpHeaders set(CharSequence name, Iterable<?> values) {
1486         return set(name.toString(), values);
1487     }
1488 
1489     /**
1490      * Cleans the current header entries and copies all header entries of the specified {@code headers}.
1491      *
1492      * @return {@code this}
1493      */
1494     public HttpHeaders set(HttpHeaders headers) {
1495         checkNotNull(headers, "headers");
1496 
1497         clear();
1498 
1499         if (headers.isEmpty()) {
1500             return this;
1501         }
1502 
1503         for (Entry<String, String> entry : headers) {
1504             add(entry.getKey(), entry.getValue());
1505         }
1506         return this;
1507     }
1508 
1509     /**
1510      * Retains all current headers but calls {@link #set(String, Object)} for each entry in {@code headers}
1511      *
1512      * @param headers The headers used to {@link #set(String, Object)} values in this instance
1513      * @return {@code this}
1514      */
1515     public HttpHeaders setAll(HttpHeaders headers) {
1516         checkNotNull(headers, "headers");
1517 
1518         if (headers.isEmpty()) {
1519             return this;
1520         }
1521 
1522         for (Entry<String, String> entry : headers) {
1523             set(entry.getKey(), entry.getValue());
1524         }
1525         return this;
1526     }
1527 
1528     /**
1529      * Set the {@code name} to {@code value}. This will remove all previous values associated with {@code name}.
1530      * @param name The name to modify
1531      * @param value The value
1532      * @return {@code this}
1533      */
1534     public abstract HttpHeaders setInt(CharSequence name, int value);
1535 
1536     /**
1537      * Set the {@code name} to {@code value}. This will remove all previous values associated with {@code name}.
1538      * @param name The name to modify
1539      * @param value The value
1540      * @return {@code this}
1541      */
1542     public abstract HttpHeaders setShort(CharSequence name, short value);
1543 
1544     /**
1545      * @see #remove(CharSequence)
1546      */
1547     public abstract HttpHeaders remove(String name);
1548 
1549     /**
1550      * Removes the header with the specified name.
1551      *
1552      * @param name The name of the header to remove
1553      * @return {@code this}
1554      */
1555     public HttpHeaders remove(CharSequence name) {
1556         return remove(name.toString());
1557     }
1558 
1559     /**
1560      * Removes all headers from this {@link HttpMessage}.
1561      *
1562      * @return {@code this}
1563      */
1564     public abstract HttpHeaders clear();
1565 
1566     /**
1567      * @see #contains(CharSequence, CharSequence, boolean)
1568      */
1569     public boolean contains(String name, String value, boolean ignoreCase) {
1570         Iterator<String> valueIterator = valueStringIterator(name);
1571         if (ignoreCase) {
1572             while (valueIterator.hasNext()) {
1573                 if (valueIterator.next().equalsIgnoreCase(value)) {
1574                     return true;
1575                 }
1576             }
1577         } else {
1578             while (valueIterator.hasNext()) {
1579                 if (valueIterator.next().equals(value)) {
1580                     return true;
1581                 }
1582             }
1583         }
1584         return false;
1585     }
1586 
1587     /**
1588      * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise.
1589      * This also handles multiple values that are separated with a {@code ,}.
1590      * <p>
1591      * If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value.
1592      * @param name the name of the header to find
1593      * @param value the value of the header to find
1594      * @param ignoreCase {@code true} then a case insensitive compare is run to compare values.
1595      * otherwise a case sensitive compare is run to compare values.
1596      */
1597     public boolean containsValue(CharSequence name, CharSequence value, boolean ignoreCase) {
1598         Iterator<? extends CharSequence> itr = valueCharSequenceIterator(name);
1599         while (itr.hasNext()) {
1600             if (containsCommaSeparatedTrimmed(itr.next(), value, ignoreCase)) {
1601                 return true;
1602             }
1603         }
1604         return false;
1605     }
1606 
1607     private static boolean containsCommaSeparatedTrimmed(CharSequence rawNext, CharSequence expected,
1608                                                          boolean ignoreCase) {
1609         int begin = 0;
1610         int end;
1611         if (ignoreCase) {
1612             if ((end = AsciiString.indexOf(rawNext, ',', begin)) == -1) {
1613                 if (contentEqualsIgnoreCase(trim(rawNext), expected)) {
1614                     return true;
1615                 }
1616             } else {
1617                 do {
1618                     if (contentEqualsIgnoreCase(trim(rawNext.subSequence(begin, end)), expected)) {
1619                         return true;
1620                     }
1621                     begin = end + 1;
1622                 } while ((end = AsciiString.indexOf(rawNext, ',', begin)) != -1);
1623 
1624                 if (begin < rawNext.length()) {
1625                     if (contentEqualsIgnoreCase(trim(rawNext.subSequence(begin, rawNext.length())), expected)) {
1626                         return true;
1627                     }
1628                 }
1629             }
1630         } else {
1631             if ((end = AsciiString.indexOf(rawNext, ',', begin)) == -1) {
1632                 if (contentEquals(trim(rawNext), expected)) {
1633                     return true;
1634                 }
1635             } else {
1636                 do {
1637                     if (contentEquals(trim(rawNext.subSequence(begin, end)), expected)) {
1638                         return true;
1639                     }
1640                     begin = end + 1;
1641                 } while ((end = AsciiString.indexOf(rawNext, ',', begin)) != -1);
1642 
1643                 if (begin < rawNext.length()) {
1644                     if (contentEquals(trim(rawNext.subSequence(begin, rawNext.length())), expected)) {
1645                         return true;
1646                     }
1647                 }
1648             }
1649         }
1650         return false;
1651     }
1652 
1653     /**
1654      * {@link Headers#get(Object)} and convert the result to a {@link String}.
1655      * @param name the name of the header to retrieve
1656      * @return the first header value if the header is found. {@code null} if there's no such header.
1657      */
1658     public final String getAsString(CharSequence name) {
1659         return get(name);
1660     }
1661 
1662     /**
1663      * {@link Headers#getAll(Object)} and convert each element of {@link List} to a {@link String}.
1664      * @param name the name of the header to retrieve
1665      * @return a {@link List} of header values or an empty {@link List} if no values are found.
1666      */
1667     public final List<String> getAllAsString(CharSequence name) {
1668         return getAll(name);
1669     }
1670 
1671     /**
1672      * {@link Iterator} that converts each {@link Entry}'s key and value to a {@link String}.
1673      */
1674     public final Iterator<Entry<String, String>> iteratorAsString() {
1675         return iterator();
1676     }
1677 
1678     /**
1679      * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise.
1680      * <p>
1681      * If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value.
1682      * @param name the name of the header to find
1683      * @param value the value of the header to find
1684      * @param ignoreCase {@code true} then a case insensitive compare is run to compare values.
1685      * otherwise a case sensitive compare is run to compare values.
1686      */
1687     public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) {
1688         return contains(name.toString(), value.toString(), ignoreCase);
1689     }
1690 
1691     @Override
1692     public String toString() {
1693         return HeadersUtils.toString(getClass(), iteratorCharSequence(), size());
1694     }
1695 
1696     /**
1697      * Returns a deep copy of the passed in {@link HttpHeaders}.
1698      */
1699     public HttpHeaders copy() {
1700         return new DefaultHttpHeaders().set(this);
1701     }
1702 }