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 }