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