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