View Javadoc
1   /*
2    * Copyright 2014 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License, version 2.0 (the
5    * "License"); you may not use this file except in compliance with the License. You may obtain a
6    * 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 distributed under the License
11   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing permissions and limitations under
13   * the License.
14   */
15  
16  package io.netty.handler.codec.http2;
17  
18  import io.netty.handler.codec.Headers;
19  import io.netty.util.AsciiString;
20  import io.netty.util.internal.UnstableApi;
21  
22  import java.util.Iterator;
23  import java.util.Map.Entry;
24  
25  /**
26   * A collection of headers sent or received via HTTP/2.
27   */
28  @UnstableApi
29  public interface Http2Headers extends Headers<CharSequence, CharSequence, Http2Headers> {
30  
31      /**
32       * HTTP/2 pseudo-headers names.
33       */
34      enum PseudoHeaderName {
35          /**
36           * {@code :method}.
37           */
38          METHOD(":method", true),
39  
40          /**
41           * {@code :scheme}.
42           */
43          SCHEME(":scheme", true),
44  
45          /**
46           * {@code :authority}.
47           */
48          AUTHORITY(":authority", true),
49  
50          /**
51           * {@code :path}.
52           */
53          PATH(":path", true),
54  
55          /**
56           * {@code :status}.
57           */
58          STATUS(":status", false),
59  
60          /**
61           * {@code :protocol}, as defined in <a href="https://datatracker.ietf.org/doc/rfc8441/">RFC 8441,
62           * Bootstrapping WebSockets with HTTP/2</a>.
63           */
64          PROTOCOL(":protocol", true);
65  
66          private static final char PSEUDO_HEADER_PREFIX = ':';
67          private static final byte PSEUDO_HEADER_PREFIX_BYTE = (byte) PSEUDO_HEADER_PREFIX;
68  
69          private final AsciiString value;
70          private final boolean requestOnly;
71          private static final CharSequenceMap<PseudoHeaderName> PSEUDO_HEADERS = new CharSequenceMap<PseudoHeaderName>();
72  
73          static {
74              for (PseudoHeaderName pseudoHeader : values()) {
75                  PSEUDO_HEADERS.add(pseudoHeader.value(), pseudoHeader);
76              }
77          }
78  
79          PseudoHeaderName(String value, boolean requestOnly) {
80              this.value = AsciiString.cached(value);
81              this.requestOnly = requestOnly;
82          }
83  
84          public AsciiString value() {
85              // Return a slice so that the buffer gets its own reader index.
86              return value;
87          }
88  
89          /**
90           * Indicates whether the specified header follows the pseudo-header format (begins with ':' character)
91           *
92           * @return {@code true} if the header follow the pseudo-header format
93           */
94          public static boolean hasPseudoHeaderFormat(CharSequence headerName) {
95              if (headerName instanceof AsciiString) {
96                  final AsciiString asciiHeaderName = (AsciiString) headerName;
97                  return asciiHeaderName.length() > 0 && asciiHeaderName.byteAt(0) == PSEUDO_HEADER_PREFIX_BYTE;
98              } else {
99                  return headerName.length() > 0 && headerName.charAt(0) == PSEUDO_HEADER_PREFIX;
100             }
101         }
102 
103         /**
104          * Indicates whether the given header name is a valid HTTP/2 pseudo header.
105          */
106         public static boolean isPseudoHeader(CharSequence header) {
107             return PSEUDO_HEADERS.contains(header);
108         }
109 
110         /**
111          * Returns the {@link PseudoHeaderName} corresponding to the specified header name.
112          *
113          * @return corresponding {@link PseudoHeaderName} if any, {@code null} otherwise.
114          */
115         public static PseudoHeaderName getPseudoHeader(CharSequence header) {
116             return PSEUDO_HEADERS.get(header);
117         }
118 
119         /**
120          * Indicates whether the pseudo-header is to be used in a request context.
121          *
122          * @return {@code true} if the pseudo-header is to be used in a request context
123          */
124         public boolean isRequestOnly() {
125             return requestOnly;
126         }
127     }
128 
129     /**
130      * Returns an iterator over all HTTP/2 headers. The iteration order is as follows:
131      *   1. All pseudo headers (order not specified).
132      *   2. All non-pseudo headers (in insertion order).
133      */
134     @Override
135     Iterator<Entry<CharSequence, CharSequence>> iterator();
136 
137     /**
138      * Equivalent to {@link #getAll(Object)} but no intermediate list is generated.
139      * @param name the name of the header to retrieve
140      * @return an {@link Iterator} of header values corresponding to {@code name}.
141      */
142     Iterator<CharSequence> valueIterator(CharSequence name);
143 
144     /**
145      * Sets the {@link PseudoHeaderName#METHOD} header
146      */
147     Http2Headers method(CharSequence value);
148 
149     /**
150      * Sets the {@link PseudoHeaderName#SCHEME} header
151      */
152     Http2Headers scheme(CharSequence value);
153 
154     /**
155      * Sets the {@link PseudoHeaderName#AUTHORITY} header
156      */
157     Http2Headers authority(CharSequence value);
158 
159     /**
160      * Sets the {@link PseudoHeaderName#PATH} header
161      */
162     Http2Headers path(CharSequence value);
163 
164     /**
165      * Sets the {@link PseudoHeaderName#STATUS} header
166      */
167     Http2Headers status(CharSequence value);
168 
169     /**
170      * Gets the {@link PseudoHeaderName#METHOD} header or {@code null} if there is no such header
171      */
172     CharSequence method();
173 
174     /**
175      * Gets the {@link PseudoHeaderName#SCHEME} header or {@code null} if there is no such header
176      */
177     CharSequence scheme();
178 
179     /**
180      * Gets the {@link PseudoHeaderName#AUTHORITY} header or {@code null} if there is no such header
181      */
182     CharSequence authority();
183 
184     /**
185      * Gets the {@link PseudoHeaderName#PATH} header or {@code null} if there is no such header
186      */
187     CharSequence path();
188 
189     /**
190      * Gets the {@link PseudoHeaderName#STATUS} header or {@code null} if there is no such header
191      */
192     CharSequence status();
193 
194     /**
195      * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise.
196      * <p>
197      * If {@code caseInsensitive} is {@code true} then a case insensitive compare is done on the value.
198      *
199      * @param name the name of the header to find
200      * @param value the value of the header to find
201      * @param caseInsensitive {@code true} then a case insensitive compare is run to compare values.
202      * otherwise a case sensitive compare is run to compare values.
203      */
204     boolean contains(CharSequence name, CharSequence value, boolean caseInsensitive);
205 }