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