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.netty5.handler.codec.http; 17 18 import io.netty5.handler.codec.DateFormatter; 19 import io.netty5.handler.codec.Headers; 20 import io.netty5.handler.codec.HeadersUtils; 21 import io.netty5.util.AsciiString; 22 23 import java.text.ParseException; 24 import java.util.Calendar; 25 import java.util.Date; 26 import java.util.Iterator; 27 import java.util.List; 28 import java.util.Map; 29 import java.util.Map.Entry; 30 import java.util.Set; 31 32 import static io.netty5.util.AsciiString.contentEquals; 33 import static io.netty5.util.AsciiString.contentEqualsIgnoreCase; 34 import static io.netty5.util.AsciiString.trim; 35 import static java.util.Objects.requireNonNull; 36 37 /** 38 * Provides the constants for the standard HTTP header names and values and 39 * commonly used utility methods that accesses an {@link HttpMessage}. 40 */ 41 public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>> { 42 43 /** 44 * @deprecated Use {@link HttpUtil#isKeepAlive(HttpMessage)} instead. 45 * 46 * Returns {@code true} if and only if the connection can remain open and 47 * thus 'kept alive'. This methods respects the value of the 48 * {@code "Connection"} header first and then the return value of 49 * {@link HttpVersion#isKeepAliveDefault()}. 50 */ 51 @Deprecated 52 public static boolean isKeepAlive(HttpMessage message) { 53 return HttpUtil.isKeepAlive(message); 54 } 55 56 /** 57 * @deprecated Use {@link HttpUtil#setKeepAlive(HttpMessage, boolean)} instead. 58 * 59 * Sets the value of the {@code "Connection"} header depending on the 60 * protocol version of the specified message. This getMethod sets or removes 61 * the {@code "Connection"} header depending on what the default keep alive 62 * mode of the message's protocol version is, as specified by 63 * {@link HttpVersion#isKeepAliveDefault()}. 64 * <ul> 65 * <li>If the connection is kept alive by default: 66 * <ul> 67 * <li>set to {@code "close"} if {@code keepAlive} is {@code false}.</li> 68 * <li>remove otherwise.</li> 69 * </ul></li> 70 * <li>If the connection is closed by default: 71 * <ul> 72 * <li>set to {@code "keep-alive"} if {@code keepAlive} is {@code true}.</li> 73 * <li>remove otherwise.</li> 74 * </ul></li> 75 * </ul> 76 */ 77 @Deprecated 78 public static void setKeepAlive(HttpMessage message, boolean keepAlive) { 79 HttpUtil.setKeepAlive(message, keepAlive); 80 } 81 82 /** 83 * @deprecated Use {@link #get(CharSequence)} instead. 84 */ 85 @Deprecated 86 public static String getHeader(HttpMessage message, String name) { 87 return message.headers().get(name); 88 } 89 90 /** 91 * @deprecated Use {@link #get(CharSequence)} instead. 92 * 93 * Returns the header value with the specified header name. If there are 94 * more than one header value for the specified header name, the first 95 * value is returned. 96 * 97 * @return the header value or {@code null} if there is no such header 98 */ 99 @Deprecated 100 public static String getHeader(HttpMessage message, CharSequence name) { 101 return message.headers().get(name); 102 } 103 104 /** 105 * @deprecated Use {@link #get(CharSequence, String)} instead. 106 * 107 * @see #getHeader(HttpMessage, CharSequence, String) 108 */ 109 @Deprecated 110 public static String getHeader(HttpMessage message, String name, String defaultValue) { 111 return message.headers().get(name, defaultValue); 112 } 113 114 /** 115 * @deprecated Use {@link #get(CharSequence, String)} instead. 116 * 117 * Returns the header value with the specified header name. If there are 118 * more than one header value for the specified header name, the first 119 * value is returned. 120 * 121 * @return the header value or the {@code defaultValue} if there is no such 122 * header 123 */ 124 @Deprecated 125 public static String getHeader(HttpMessage message, CharSequence name, String defaultValue) { 126 return message.headers().get(name, defaultValue); 127 } 128 129 /** 130 * @deprecated Use {@link #set(CharSequence, Object)} instead. 131 * 132 * @see #setHeader(HttpMessage, CharSequence, Object) 133 */ 134 @Deprecated 135 public static void setHeader(HttpMessage message, String name, Object value) { 136 message.headers().set(name, value); 137 } 138 139 /** 140 * @deprecated Use {@link #set(CharSequence, Object)} instead. 141 * 142 * Sets a new header with the specified name and value. If there is an 143 * existing header with the same name, the existing header is removed. 144 * If the specified value is not a {@link String}, it is converted into a 145 * {@link String} by {@link Object#toString()}, except for {@link Date} 146 * and {@link Calendar} which are formatted to the date format defined in 147 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>. 148 */ 149 @Deprecated 150 public static void setHeader(HttpMessage message, CharSequence name, Object value) { 151 message.headers().set(name, value); 152 } 153 154 /** 155 * @deprecated Use {@link #set(CharSequence, Iterable)} instead. 156 * 157 * @see #setHeader(HttpMessage, CharSequence, Iterable) 158 */ 159 @Deprecated 160 public static void setHeader(HttpMessage message, String name, Iterable<?> values) { 161 message.headers().set(name, values); 162 } 163 164 /** 165 * @deprecated Use {@link #set(CharSequence, Iterable)} instead. 166 * 167 * Sets a new header with the specified name and values. If there is an 168 * existing header with the same name, the existing header is removed. 169 * This getMethod can be represented approximately as the following code: 170 * <pre> 171 * removeHeader(message, name); 172 * for (Object v: values) { 173 * if (v == null) { 174 * break; 175 * } 176 * addHeader(message, name, v); 177 * } 178 * </pre> 179 */ 180 @Deprecated 181 public static void setHeader(HttpMessage message, CharSequence name, Iterable<?> values) { 182 message.headers().set(name, values); 183 } 184 185 /** 186 * @deprecated Use {@link #add(CharSequence, Object)} instead. 187 * 188 * @see #addHeader(HttpMessage, CharSequence, Object) 189 */ 190 @Deprecated 191 public static void addHeader(HttpMessage message, String name, Object value) { 192 message.headers().add(name, value); 193 } 194 195 /** 196 * @deprecated Use {@link #add(CharSequence, Object)} instead. 197 * 198 * Adds a new header with the specified name and value. 199 * If the specified value is not a {@link String}, it is converted into a 200 * {@link String} by {@link Object#toString()}, except for {@link Date} 201 * and {@link Calendar} which are formatted to the date format defined in 202 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>. 203 */ 204 @Deprecated 205 public static void addHeader(HttpMessage message, CharSequence name, Object value) { 206 message.headers().add(name, value); 207 } 208 209 /** 210 * @deprecated Use {@link #remove(CharSequence)} instead. 211 * 212 * @see #removeHeader(HttpMessage, CharSequence) 213 */ 214 @Deprecated 215 public static void removeHeader(HttpMessage message, String name) { 216 message.headers().remove(name); 217 } 218 219 /** 220 * @deprecated Use {@link #remove(CharSequence)} instead. 221 * 222 * Removes the header with the specified name. 223 */ 224 @Deprecated 225 public static void removeHeader(HttpMessage message, CharSequence name) { 226 message.headers().remove(name); 227 } 228 229 /** 230 * @deprecated Use {@link #clear()} instead. 231 * 232 * Removes all headers from the specified message. 233 */ 234 @Deprecated 235 public static void clearHeaders(HttpMessage message) { 236 message.headers().clear(); 237 } 238 239 /** 240 * @deprecated Use {@link #getInt(CharSequence)} instead. 241 * 242 * @see #getIntHeader(HttpMessage, CharSequence) 243 */ 244 @Deprecated 245 public static int getIntHeader(HttpMessage message, String name) { 246 return getIntHeader(message, (CharSequence) name); 247 } 248 249 /** 250 * @deprecated Use {@link #getInt(CharSequence)} instead. 251 * 252 * Returns the integer header value with the specified header name. If 253 * there are more than one header value for the specified header name, the 254 * first value is returned. 255 * 256 * @return the header value 257 * @throws NumberFormatException 258 * if there is no such header or the header value is not a number 259 */ 260 @Deprecated 261 public static int getIntHeader(HttpMessage message, CharSequence name) { 262 String value = message.headers().get(name); 263 if (value == null) { 264 throw new NumberFormatException("header not found: " + name); 265 } 266 return Integer.parseInt(value); 267 } 268 269 /** 270 * @deprecated Use {@link #getInt(CharSequence, int)} instead. 271 * 272 * @see #getIntHeader(HttpMessage, CharSequence, int) 273 */ 274 @Deprecated 275 public static int getIntHeader(HttpMessage message, String name, int defaultValue) { 276 return message.headers().getInt(name, defaultValue); 277 } 278 279 /** 280 * @deprecated Use {@link #getInt(CharSequence, int)} instead. 281 * 282 * Returns the integer header value with the specified header name. If 283 * there are more than one header value for the specified header name, the 284 * first value is returned. 285 * 286 * @return the header value or the {@code defaultValue} if there is no such 287 * header or the header value is not a number 288 */ 289 @Deprecated 290 public static int getIntHeader(HttpMessage message, CharSequence name, int defaultValue) { 291 return message.headers().getInt(name, defaultValue); 292 } 293 294 /** 295 * @deprecated Use {@link #setInt(CharSequence, int)} instead. 296 * 297 * @see #setIntHeader(HttpMessage, CharSequence, int) 298 */ 299 @Deprecated 300 public static void setIntHeader(HttpMessage message, String name, int value) { 301 message.headers().setInt(name, value); 302 } 303 304 /** 305 * @deprecated Use {@link #setInt(CharSequence, int)} instead. 306 * 307 * Sets a new integer header with the specified name and value. If there 308 * is an existing header with the same name, the existing header is removed. 309 */ 310 @Deprecated 311 public static void setIntHeader(HttpMessage message, CharSequence name, int value) { 312 message.headers().setInt(name, value); 313 } 314 315 /** 316 * @deprecated Use {@link #set(CharSequence, Iterable)} instead. 317 * 318 * @see #setIntHeader(HttpMessage, CharSequence, Iterable) 319 */ 320 @Deprecated 321 public static void setIntHeader(HttpMessage message, String name, Iterable<Integer> values) { 322 message.headers().set(name, values); 323 } 324 325 /** 326 * @deprecated Use {@link #set(CharSequence, Iterable)} instead. 327 * 328 * Sets a new integer header with the specified name and values. If there 329 * is an existing header with the same name, the existing header is removed. 330 */ 331 @Deprecated 332 public static void setIntHeader(HttpMessage message, CharSequence name, Iterable<Integer> values) { 333 message.headers().set(name, values); 334 } 335 336 /** 337 * @deprecated Use {@link #add(CharSequence, Iterable)} instead. 338 * 339 * @see #addIntHeader(HttpMessage, CharSequence, int) 340 */ 341 @Deprecated 342 public static void addIntHeader(HttpMessage message, String name, int value) { 343 message.headers().add(name, value); 344 } 345 346 /** 347 * @deprecated Use {@link #addInt(CharSequence, int)} instead. 348 * 349 * Adds a new integer header with the specified name and value. 350 */ 351 @Deprecated 352 public static void addIntHeader(HttpMessage message, CharSequence name, int value) { 353 message.headers().addInt(name, value); 354 } 355 356 /** 357 * @deprecated Use {@link #getTimeMillis(CharSequence)} instead. 358 * 359 * @see #getDateHeader(HttpMessage, CharSequence) 360 */ 361 @Deprecated 362 public static Date getDateHeader(HttpMessage message, String name) throws ParseException { 363 return getDateHeader(message, (CharSequence) name); 364 } 365 366 /** 367 * @deprecated Use {@link #getTimeMillis(CharSequence)} instead. 368 * 369 * Returns the date header value with the specified header name. If 370 * there are more than one header value for the specified header name, the 371 * first value is returned. 372 * 373 * @return the header value 374 * @throws ParseException 375 * if there is no such header or the header value is not a formatted date 376 */ 377 @Deprecated 378 public static Date getDateHeader(HttpMessage message, CharSequence name) throws ParseException { 379 String value = message.headers().get(name); 380 if (value == null) { 381 throw new ParseException("header not found: " + name, 0); 382 } 383 Date date = DateFormatter.parseHttpDate(value); 384 if (date == null) { 385 throw new ParseException("header can't be parsed into a Date: " + value, 0); 386 } 387 return date; 388 } 389 390 /** 391 * @deprecated Use {@link #getTimeMillis(CharSequence, long)} instead. 392 * 393 * @see #getDateHeader(HttpMessage, CharSequence, Date) 394 */ 395 @Deprecated 396 public static Date getDateHeader(HttpMessage message, String name, Date defaultValue) { 397 return getDateHeader(message, (CharSequence) name, defaultValue); 398 } 399 400 /** 401 * @deprecated Use {@link #getTimeMillis(CharSequence, long)} instead. 402 * 403 * Returns the date header value with the specified header name. If 404 * there are more than one header value for the specified header name, the 405 * first value is returned. 406 * 407 * @return the header value or the {@code defaultValue} if there is no such 408 * header or the header value is not a formatted date 409 */ 410 @Deprecated 411 public static Date getDateHeader(HttpMessage message, CharSequence name, Date defaultValue) { 412 final String value = getHeader(message, name); 413 Date date = DateFormatter.parseHttpDate(value); 414 return date != null ? date : defaultValue; 415 } 416 417 /** 418 * @deprecated Use {@link #set(CharSequence, Object)} instead. 419 * 420 * @see #setDateHeader(HttpMessage, CharSequence, Date) 421 */ 422 @Deprecated 423 public static void setDateHeader(HttpMessage message, String name, Date value) { 424 setDateHeader(message, (CharSequence) name, value); 425 } 426 427 /** 428 * @deprecated Use {@link #set(CharSequence, Object)} instead. 429 * 430 * Sets a new date header with the specified name and value. If there 431 * is an existing header with the same name, the existing header is removed. 432 * The specified value is formatted as defined in 433 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a> 434 */ 435 @Deprecated 436 public static void setDateHeader(HttpMessage message, CharSequence name, Date value) { 437 if (value != null) { 438 message.headers().set(name, DateFormatter.format(value)); 439 } else { 440 message.headers().set(name, null); 441 } 442 } 443 444 /** 445 * @deprecated Use {@link #set(CharSequence, Iterable)} instead. 446 * 447 * @see #setDateHeader(HttpMessage, CharSequence, Iterable) 448 */ 449 @Deprecated 450 public static void setDateHeader(HttpMessage message, String name, Iterable<Date> values) { 451 message.headers().set(name, values); 452 } 453 454 /** 455 * @deprecated Use {@link #set(CharSequence, Iterable)} instead. 456 * 457 * Sets a new date header with the specified name and values. If there 458 * is an existing header with the same name, the existing header is removed. 459 * The specified values are formatted as defined in 460 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a> 461 */ 462 @Deprecated 463 public static void setDateHeader(HttpMessage message, CharSequence name, Iterable<Date> values) { 464 message.headers().set(name, values); 465 } 466 467 /** 468 * @deprecated Use {@link #add(CharSequence, Object)} instead. 469 * 470 * @see #addDateHeader(HttpMessage, CharSequence, Date) 471 */ 472 @Deprecated 473 public static void addDateHeader(HttpMessage message, String name, Date value) { 474 message.headers().add(name, value); 475 } 476 477 /** 478 * @deprecated Use {@link #add(CharSequence, Object)} instead. 479 * 480 * Adds a new date header with the specified name and value. The specified 481 * value is formatted as defined in 482 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a> 483 */ 484 @Deprecated 485 public static void addDateHeader(HttpMessage message, CharSequence name, Date value) { 486 message.headers().add(name, value); 487 } 488 489 /** 490 * @deprecated Use {@link HttpUtil#getContentLength(HttpMessage)} instead. 491 * 492 * Returns the length of the content. Please note that this value is 493 * not retrieved from {@link HttpContent#payload()} but from the 494 * {@code "Content-Length"} header, and thus they are independent from each 495 * other. 496 * 497 * @return the content length 498 * 499 * @throws NumberFormatException 500 * if the message does not have the {@code "Content-Length"} header 501 * or its value is not a number 502 */ 503 @Deprecated 504 public static long getContentLength(HttpMessage message) { 505 return HttpUtil.getContentLength(message); 506 } 507 508 /** 509 * @deprecated Use {@link HttpUtil#getContentLength(HttpMessage, long)} instead. 510 * 511 * Returns the length of the content. Please note that this value is 512 * not retrieved from {@link HttpContent#payload()} but from the 513 * {@code "Content-Length"} header, and thus they are independent from each 514 * other. 515 * 516 * @return the content length or {@code defaultValue} if this message does 517 * not have the {@code "Content-Length"} header or its value is not 518 * a number 519 */ 520 @Deprecated 521 public static long getContentLength(HttpMessage message, long defaultValue) { 522 return HttpUtil.getContentLength(message, defaultValue); 523 } 524 525 /** 526 * @deprecated Use {@link HttpUtil#setContentLength(HttpMessage, long)} instead. 527 */ 528 @Deprecated 529 public static void setContentLength(HttpMessage message, long length) { 530 HttpUtil.setContentLength(message, length); 531 } 532 533 /** 534 * @deprecated Use {@link #get(CharSequence)} instead. 535 * 536 * Returns the value of the {@code "Host"} header. 537 */ 538 @Deprecated 539 public static String getHost(HttpMessage message) { 540 return message.headers().get(HttpHeaderNames.HOST); 541 } 542 543 /** 544 * @deprecated Use {@link #get(CharSequence, String)} instead. 545 * 546 * Returns the value of the {@code "Host"} header. If there is no such 547 * header, the {@code defaultValue} is returned. 548 */ 549 @Deprecated 550 public static String getHost(HttpMessage message, String defaultValue) { 551 return message.headers().get(HttpHeaderNames.HOST, defaultValue); 552 } 553 554 /** 555 * @deprecated Use {@link #set(CharSequence, Object)} instead. 556 * 557 * @see #setHost(HttpMessage, CharSequence) 558 */ 559 @Deprecated 560 public static void setHost(HttpMessage message, String value) { 561 message.headers().set(HttpHeaderNames.HOST, value); 562 } 563 564 /** 565 * @deprecated Use {@link #set(CharSequence, Object)} instead. 566 * 567 * Sets the {@code "Host"} header. 568 */ 569 @Deprecated 570 public static void setHost(HttpMessage message, CharSequence value) { 571 message.headers().set(HttpHeaderNames.HOST, value); 572 } 573 574 /** 575 * @deprecated Use {@link #getTimeMillis(CharSequence)} instead. 576 * 577 * Returns the value of the {@code "Date"} header. 578 * 579 * @throws ParseException 580 * if there is no such header or the header value is not a formatted date 581 */ 582 @Deprecated 583 public static Date getDate(HttpMessage message) throws ParseException { 584 return getDateHeader(message, HttpHeaderNames.DATE); 585 } 586 587 /** 588 * @deprecated Use {@link #getTimeMillis(CharSequence, long)} instead. 589 * 590 * Returns the value of the {@code "Date"} header. If there is no such 591 * header or the header is not a formatted date, the {@code defaultValue} 592 * is returned. 593 */ 594 @Deprecated 595 public static Date getDate(HttpMessage message, Date defaultValue) { 596 return getDateHeader(message, HttpHeaderNames.DATE, defaultValue); 597 } 598 599 /** 600 * @deprecated Use {@link #set(CharSequence, Object)} instead. 601 * 602 * Sets the {@code "Date"} header. 603 */ 604 @Deprecated 605 public static void setDate(HttpMessage message, Date value) { 606 message.headers().set(HttpHeaderNames.DATE, value); 607 } 608 609 /** 610 * @deprecated Use {@link HttpUtil#is100ContinueExpected(HttpMessage)} instead. 611 * 612 * Returns {@code true} if and only if the specified message contains the 613 * {@code "Expect: 100-continue"} header. 614 */ 615 @Deprecated 616 public static boolean is100ContinueExpected(HttpMessage message) { 617 return HttpUtil.is100ContinueExpected(message); 618 } 619 620 /** 621 * @deprecated Use {@link HttpUtil#set100ContinueExpected(HttpMessage, boolean)} instead. 622 * 623 * Sets the {@code "Expect: 100-continue"} header to the specified message. 624 * If there is any existing {@code "Expect"} header, they are replaced with 625 * the new one. 626 */ 627 @Deprecated 628 public static void set100ContinueExpected(HttpMessage message) { 629 HttpUtil.set100ContinueExpected(message, true); 630 } 631 632 /** 633 * @deprecated Use {@link HttpUtil#set100ContinueExpected(HttpMessage, boolean)} instead. 634 * 635 * Sets or removes the {@code "Expect: 100-continue"} header to / from the 636 * specified message. If {@code set} is {@code true}, 637 * the {@code "Expect: 100-continue"} header is set and all other previous 638 * {@code "Expect"} headers are removed. Otherwise, all {@code "Expect"} 639 * headers are removed completely. 640 */ 641 @Deprecated 642 public static void set100ContinueExpected(HttpMessage message, boolean set) { 643 HttpUtil.set100ContinueExpected(message, set); 644 } 645 646 /** 647 * @deprecated Use {@link HttpUtil#isTransferEncodingChunked(HttpMessage)} instead. 648 * 649 * Checks to see if the transfer encoding in a specified {@link HttpMessage} is chunked 650 * 651 * @param message The message to check 652 * @return True if transfer encoding is chunked, otherwise false 653 */ 654 @Deprecated 655 public static boolean isTransferEncodingChunked(HttpMessage message) { 656 return HttpUtil.isTransferEncodingChunked(message); 657 } 658 659 /** 660 * @deprecated Use {@link HttpUtil#setTransferEncodingChunked(HttpMessage, boolean)} instead. 661 */ 662 @Deprecated 663 public static void removeTransferEncodingChunked(HttpMessage m) { 664 HttpUtil.setTransferEncodingChunked(m, false); 665 } 666 667 /** 668 * @deprecated Use {@link HttpUtil#setTransferEncodingChunked(HttpMessage, boolean)} instead. 669 */ 670 @Deprecated 671 public static void setTransferEncodingChunked(HttpMessage m) { 672 HttpUtil.setTransferEncodingChunked(m, true); 673 } 674 675 /** 676 * @deprecated Use {@link HttpUtil#isContentLengthSet(HttpMessage)} instead. 677 */ 678 @Deprecated 679 public static boolean isContentLengthSet(HttpMessage m) { 680 return HttpUtil.isContentLengthSet(m); 681 } 682 683 /** 684 * @deprecated Use {@link AsciiString#contentEqualsIgnoreCase(CharSequence, CharSequence)} instead. 685 */ 686 @Deprecated 687 public static boolean equalsIgnoreCase(CharSequence name1, CharSequence name2) { 688 return contentEqualsIgnoreCase(name1, name2); 689 } 690 691 /** 692 * @deprecated Use {@link AsciiString} instead. 693 * <p> 694 * Create a new {@link CharSequence} which is optimized for reuse as {@link HttpHeaders} name or value. 695 * So if you have a Header name or value that you want to reuse you should make use of this. 696 */ 697 @Deprecated 698 public static CharSequence newEntity(String name) { 699 return new AsciiString(name); 700 } 701 702 protected HttpHeaders() { } 703 704 /** 705 * @see #get(CharSequence) 706 */ 707 public abstract String get(String name); 708 709 /** 710 * Returns the value of a header with the specified name. If there are 711 * more than one values for the specified name, the first value is returned. 712 * 713 * @param name The name of the header to search 714 * @return The first header value or {@code null} if there is no such header 715 * @see #getAsString(CharSequence) 716 */ 717 public String get(CharSequence name) { 718 return get(name.toString()); 719 } 720 721 /** 722 * Returns the value of a header with the specified name. If there are 723 * more than one values for the specified name, the first value is returned. 724 * 725 * @param name The name of the header to search 726 * @return The first header value or {@code defaultValue} if there is no such header 727 */ 728 public String get(CharSequence name, String defaultValue) { 729 String value = get(name); 730 if (value == null) { 731 return defaultValue; 732 } 733 return value; 734 } 735 736 /** 737 * Returns the integer value of a header with the specified name. If there are more than one values for the 738 * specified name, the first value is returned. 739 * 740 * @param name the name of the header to search 741 * @return the first header value if the header is found and its value is an integer. {@code null} if there's no 742 * such header or its value is not an integer. 743 */ 744 public abstract Integer getInt(CharSequence name); 745 746 /** 747 * Returns the integer value of a header with the specified name. If there are more than one values for the 748 * specified name, the first value is returned. 749 * 750 * @param name the name of the header to search 751 * @param defaultValue the default value 752 * @return the first header value if the header is found and its value is an integer. {@code defaultValue} if 753 * there's no such header or its value is not an integer. 754 */ 755 public abstract int getInt(CharSequence name, int defaultValue); 756 757 /** 758 * Returns the short value of a header with the specified name. If there are more than one values for the 759 * specified name, the first value is returned. 760 * 761 * @param name the name of the header to search 762 * @return the first header value if the header is found and its value is a short. {@code null} if there's no 763 * such header or its value is not a short. 764 */ 765 public abstract Short getShort(CharSequence name); 766 767 /** 768 * Returns the short value of a header with the specified name. If there are more than one values for the 769 * specified name, the first value is returned. 770 * 771 * @param name the name of the header to search 772 * @param defaultValue the default value 773 * @return the first header value if the header is found and its value is a short. {@code defaultValue} if 774 * there's no such header or its value is not a short. 775 */ 776 public abstract short getShort(CharSequence name, short defaultValue); 777 778 /** 779 * Returns the date value of a header with the specified name. If there are more than one values for the 780 * specified name, the first value is returned. 781 * 782 * @param name the name of the header to search 783 * @return the first header value if the header is found and its value is a date. {@code null} if there's no 784 * such header or its value is not a date. 785 */ 786 public abstract Long getTimeMillis(CharSequence name); 787 788 /** 789 * Returns the date value of a header with the specified name. If there are more than one values for the 790 * specified name, the first value is returned. 791 * 792 * @param name the name of the header to search 793 * @param defaultValue the default value 794 * @return the first header value if the header is found and its value is a date. {@code defaultValue} if 795 * there's no such header or its value is not a date. 796 */ 797 public abstract long getTimeMillis(CharSequence name, long defaultValue); 798 799 /** 800 * @see #getAll(CharSequence) 801 */ 802 public abstract List<String> getAll(String name); 803 804 /** 805 * Returns the values of headers with the specified name 806 * 807 * @param name The name of the headers to search 808 * @return A {@link List} of header values which will be empty if no values 809 * are found 810 * @see #getAllAsString(CharSequence) 811 */ 812 public List<String> getAll(CharSequence name) { 813 return getAll(name.toString()); 814 } 815 816 /** 817 * Returns a new {@link List} that contains all headers in this object. Note that modifying the 818 * returned {@link List} will not affect the state of this object. If you intend to enumerate over the header 819 * entries only, use {@link #iterator()} instead, which has much less overhead. 820 * @see #iteratorCharSequence() 821 */ 822 public abstract List<Map.Entry<String, String>> entries(); 823 824 /** 825 * @see #contains(CharSequence) 826 */ 827 public abstract boolean contains(String name); 828 829 /** 830 * @deprecated It is preferred to use {@link #iteratorCharSequence()} unless you need {@link String}. 831 * If {@link String} is required then use {@link #iteratorAsString()}. 832 */ 833 @Deprecated 834 @Override 835 public abstract Iterator<Entry<String, String>> iterator(); 836 837 /** 838 * @return Iterator over the name/value header pairs. 839 */ 840 public abstract Iterator<Entry<CharSequence, CharSequence>> iteratorCharSequence(); 841 842 /** 843 * Equivalent to {@link #getAll(String)} but it is possible that no intermediate list is generated. 844 * @param name the name of the header to retrieve 845 * @return an {@link Iterator} of header values corresponding to {@code name}. 846 */ 847 public Iterator<String> valueStringIterator(CharSequence name) { 848 return getAll(name).iterator(); 849 } 850 851 /** 852 * Equivalent to {@link #getAll(String)} but it is possible that no intermediate list is generated. 853 * @param name the name of the header to retrieve 854 * @return an {@link Iterator} of header values corresponding to {@code name}. 855 */ 856 public Iterator<? extends CharSequence> valueCharSequenceIterator(CharSequence name) { 857 return valueStringIterator(name); 858 } 859 860 /** 861 * Checks to see if there is a header with the specified name 862 * 863 * @param name The name of the header to search for 864 * @return True if at least one header is found 865 */ 866 public boolean contains(CharSequence name) { 867 return contains(name.toString()); 868 } 869 870 /** 871 * Checks if no header exists. 872 */ 873 public abstract boolean isEmpty(); 874 875 /** 876 * Returns the number of headers in this object. 877 */ 878 public abstract int size(); 879 880 /** 881 * Returns a new {@link Set} that contains the names of all headers in this object. Note that modifying the 882 * returned {@link Set} will not affect the state of this object. If you intend to enumerate over the header 883 * entries only, use {@link #iterator()} instead, which has much less overhead. 884 */ 885 public abstract Set<String> names(); 886 887 /** 888 * @see #add(CharSequence, Object) 889 */ 890 public abstract HttpHeaders add(String name, Object value); 891 892 /** 893 * Adds a new header with the specified name and value. 894 * 895 * If the specified value is not a {@link String}, it is converted 896 * into a {@link String} by {@link Object#toString()}, except in the cases 897 * of {@link Date} and {@link Calendar}, which are formatted to the date 898 * format defined in <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>. 899 * 900 * @param name The name of the header being added 901 * @param value The value of the header being added 902 * 903 * @return {@code this} 904 */ 905 public HttpHeaders add(CharSequence name, Object value) { 906 return add(name.toString(), value); 907 } 908 909 /** 910 * @see #add(CharSequence, Iterable) 911 */ 912 public abstract HttpHeaders add(String name, Iterable<?> values); 913 914 /** 915 * Adds a new header with the specified name and values. 916 * 917 * This getMethod can be represented approximately as the following code: 918 * <pre> 919 * for (Object v: values) { 920 * if (v == null) { 921 * break; 922 * } 923 * headers.add(name, v); 924 * } 925 * </pre> 926 * 927 * @param name The name of the headers being set 928 * @param values The values of the headers being set 929 * @return {@code this} 930 */ 931 public HttpHeaders add(CharSequence name, Iterable<?> values) { 932 return add(name.toString(), values); 933 } 934 935 /** 936 * Adds all header entries of the specified {@code headers}. 937 * 938 * @return {@code this} 939 */ 940 public HttpHeaders add(HttpHeaders headers) { 941 requireNonNull(headers, "headers"); 942 for (Map.Entry<String, String> e: headers) { 943 add(e.getKey(), e.getValue()); 944 } 945 return this; 946 } 947 948 /** 949 * Add the {@code name} to {@code value}. 950 * @param name The name to modify 951 * @param value The value 952 * @return {@code this} 953 */ 954 public abstract HttpHeaders addInt(CharSequence name, int value); 955 956 /** 957 * Add the {@code name} to {@code value}. 958 * @param name The name to modify 959 * @param value The value 960 * @return {@code this} 961 */ 962 public abstract HttpHeaders addShort(CharSequence name, short value); 963 964 /** 965 * @see #set(CharSequence, Object) 966 */ 967 public abstract HttpHeaders set(String name, Object value); 968 969 /** 970 * Sets a header with the specified name and value. 971 * 972 * If there is an existing header with the same name, it is removed. 973 * If the specified value is not a {@link String}, it is converted into a 974 * {@link String} by {@link Object#toString()}, except for {@link Date} 975 * and {@link Calendar}, which are formatted to the date format defined in 976 * <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>. 977 * 978 * @param name The name of the header being set 979 * @param value The value of the header being set 980 * @return {@code this} 981 */ 982 public HttpHeaders set(CharSequence name, Object value) { 983 return set(name.toString(), value); 984 } 985 986 /** 987 * @see #set(CharSequence, Iterable) 988 */ 989 public abstract HttpHeaders set(String name, Iterable<?> values); 990 991 /** 992 * Sets a header with the specified name and values. 993 * 994 * If there is an existing header with the same name, it is removed. 995 * This getMethod can be represented approximately as the following code: 996 * <pre> 997 * headers.remove(name); 998 * for (Object v: values) { 999 * if (v == null) { 1000 * break; 1001 * } 1002 * headers.add(name, v); 1003 * } 1004 * </pre> 1005 * 1006 * @param name The name of the headers being set 1007 * @param values The values of the headers being set 1008 * @return {@code this} 1009 */ 1010 public HttpHeaders set(CharSequence name, Iterable<?> values) { 1011 return set(name.toString(), values); 1012 } 1013 1014 /** 1015 * Cleans the current header entries and copies all header entries of the specified {@code headers}. 1016 * 1017 * @return {@code this} 1018 */ 1019 public HttpHeaders set(HttpHeaders headers) { 1020 requireNonNull(headers, "headers"); 1021 1022 clear(); 1023 1024 if (headers.isEmpty()) { 1025 return this; 1026 } 1027 1028 for (Entry<String, String> entry : headers) { 1029 add(entry.getKey(), entry.getValue()); 1030 } 1031 return this; 1032 } 1033 1034 /** 1035 * Retains all current headers but calls {@link #set(String, Object)} for each entry in {@code headers} 1036 * 1037 * @param headers The headers used to {@link #set(String, Object)} values in this instance 1038 * @return {@code this} 1039 */ 1040 public HttpHeaders setAll(HttpHeaders headers) { 1041 requireNonNull(headers, "headers"); 1042 1043 if (headers.isEmpty()) { 1044 return this; 1045 } 1046 1047 for (Entry<String, String> entry : headers) { 1048 set(entry.getKey(), entry.getValue()); 1049 } 1050 return this; 1051 } 1052 1053 /** 1054 * Set the {@code name} to {@code value}. This will remove all previous values associated with {@code name}. 1055 * @param name The name to modify 1056 * @param value The value 1057 * @return {@code this} 1058 */ 1059 public abstract HttpHeaders setInt(CharSequence name, int value); 1060 1061 /** 1062 * Set the {@code name} to {@code value}. This will remove all previous values associated with {@code name}. 1063 * @param name The name to modify 1064 * @param value The value 1065 * @return {@code this} 1066 */ 1067 public abstract HttpHeaders setShort(CharSequence name, short value); 1068 1069 /** 1070 * @see #remove(CharSequence) 1071 */ 1072 public abstract HttpHeaders remove(String name); 1073 1074 /** 1075 * Removes the header with the specified name. 1076 * 1077 * @param name The name of the header to remove 1078 * @return {@code this} 1079 */ 1080 public HttpHeaders remove(CharSequence name) { 1081 return remove(name.toString()); 1082 } 1083 1084 /** 1085 * Removes all headers from this {@link HttpMessage}. 1086 * 1087 * @return {@code this} 1088 */ 1089 public abstract HttpHeaders clear(); 1090 1091 /** 1092 * @see #contains(CharSequence, CharSequence, boolean) 1093 */ 1094 public boolean contains(String name, String value, boolean ignoreCase) { 1095 Iterator<String> valueIterator = valueStringIterator(name); 1096 if (ignoreCase) { 1097 while (valueIterator.hasNext()) { 1098 if (valueIterator.next().equalsIgnoreCase(value)) { 1099 return true; 1100 } 1101 } 1102 } else { 1103 while (valueIterator.hasNext()) { 1104 if (valueIterator.next().equals(value)) { 1105 return true; 1106 } 1107 } 1108 } 1109 return false; 1110 } 1111 1112 /** 1113 * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise. 1114 * This also handles multiple values that are separated with a {@code ,}. 1115 * <p> 1116 * If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value. 1117 * @param name the name of the header to find 1118 * @param value the value of the header to find 1119 * @param ignoreCase {@code true} then a case insensitive compare is run to compare values. 1120 * otherwise a case sensitive compare is run to compare values. 1121 */ 1122 public boolean containsValue(CharSequence name, CharSequence value, boolean ignoreCase) { 1123 Iterator<? extends CharSequence> itr = valueCharSequenceIterator(name); 1124 while (itr.hasNext()) { 1125 if (containsCommaSeparatedTrimmed(itr.next(), value, ignoreCase)) { 1126 return true; 1127 } 1128 } 1129 return false; 1130 } 1131 1132 private static boolean containsCommaSeparatedTrimmed(CharSequence rawNext, CharSequence expected, 1133 boolean ignoreCase) { 1134 int begin = 0; 1135 int end; 1136 if (ignoreCase) { 1137 if ((end = AsciiString.indexOf(rawNext, ',', begin)) == -1) { 1138 return contentEqualsIgnoreCase(trim(rawNext), expected); 1139 } else { 1140 do { 1141 if (contentEqualsIgnoreCase(trim(rawNext.subSequence(begin, end)), expected)) { 1142 return true; 1143 } 1144 begin = end + 1; 1145 } while ((end = AsciiString.indexOf(rawNext, ',', begin)) != -1); 1146 1147 if (begin < rawNext.length()) { 1148 return contentEqualsIgnoreCase(trim(rawNext.subSequence(begin, rawNext.length())), expected); 1149 } 1150 } 1151 } else { 1152 if ((end = AsciiString.indexOf(rawNext, ',', begin)) == -1) { 1153 return contentEquals(trim(rawNext), expected); 1154 } else { 1155 do { 1156 if (contentEquals(trim(rawNext.subSequence(begin, end)), expected)) { 1157 return true; 1158 } 1159 begin = end + 1; 1160 } while ((end = AsciiString.indexOf(rawNext, ',', begin)) != -1); 1161 1162 if (begin < rawNext.length()) { 1163 return contentEquals(trim(rawNext.subSequence(begin, rawNext.length())), expected); 1164 } 1165 } 1166 } 1167 return false; 1168 } 1169 1170 /** 1171 * {@link Headers#get(Object)} and convert the result to a {@link String}. 1172 * @param name the name of the header to retrieve 1173 * @return the first header value if the header is found. {@code null} if there's no such header. 1174 */ 1175 public final String getAsString(CharSequence name) { 1176 return get(name); 1177 } 1178 1179 /** 1180 * {@link Headers#getAll(Object)} and convert each element of {@link List} to a {@link String}. 1181 * @param name the name of the header to retrieve 1182 * @return a {@link List} of header values or an empty {@link List} if no values are found. 1183 */ 1184 public final List<String> getAllAsString(CharSequence name) { 1185 return getAll(name); 1186 } 1187 1188 /** 1189 * {@link Iterator} that converts each {@link Entry}'s key and value to a {@link String}. 1190 */ 1191 public final Iterator<Entry<String, String>> iteratorAsString() { 1192 return iterator(); 1193 } 1194 1195 /** 1196 * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise. 1197 * <p> 1198 * If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value. 1199 * @param name the name of the header to find 1200 * @param value the value of the header to find 1201 * @param ignoreCase {@code true} then a case insensitive compare is run to compare values. 1202 * otherwise a case sensitive compare is run to compare values. 1203 */ 1204 public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) { 1205 return contains(name.toString(), value.toString(), ignoreCase); 1206 } 1207 1208 @Override 1209 public String toString() { 1210 return HeadersUtils.toString(getClass(), iteratorCharSequence(), size()); 1211 } 1212 1213 /** 1214 * Returns a deep copy of the passed in {@link HttpHeaders}. 1215 */ 1216 public HttpHeaders copy() { 1217 return new DefaultHttpHeaders().set(this); 1218 } 1219 }