View Javadoc
1   /*
2    * Copyright 2013 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.buffer.Unpooled;
21  import io.netty.util.IllegalReferenceCountException;
22  
23  import static io.netty.handler.codec.http.DefaultHttpHeadersFactory.headersFactory;
24  import static io.netty.handler.codec.http.DefaultHttpHeadersFactory.trailersFactory;
25  import static io.netty.util.internal.ObjectUtil.checkNotNull;
26  
27  /**
28   * Default implementation of {@link FullHttpRequest}.
29   */
30  public class DefaultFullHttpRequest extends DefaultHttpRequest implements FullHttpRequest {
31      private final ByteBuf content;
32      private final HttpHeaders trailingHeader;
33  
34      /**
35       * Used to cache the value of the hash code and avoid {@link IllegalReferenceCountException}.
36       */
37      private int hash;
38  
39      /**
40       * Create a full HTTP response with the given HTTP version, method, and URI.
41       */
42      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri) {
43          this(httpVersion, method, uri, Unpooled.buffer(0), headersFactory(), trailersFactory());
44      }
45  
46      /**
47       * Create a full HTTP response with the given HTTP version, method, URI, and contents.
48       */
49      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri, ByteBuf content) {
50          this(httpVersion, method, uri, content, headersFactory(), trailersFactory());
51      }
52  
53      /**
54       * Create a full HTTP response with the given HTTP version, method, URI, and optional validation.
55       * @deprecated Use the {@link #DefaultFullHttpRequest(HttpVersion, HttpMethod, String, ByteBuf,
56       * HttpHeadersFactory, HttpHeadersFactory)} constructor instead.
57       */
58      @Deprecated
59      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri, boolean validateHeaders) {
60          this(httpVersion, method, uri, Unpooled.buffer(0),
61                  headersFactory().withValidation(validateHeaders),
62                  trailersFactory().withValidation(validateHeaders));
63      }
64  
65      /**
66       * Create a full HTTP response with the given HTTP version, method, URI, contents, and optional validation.
67       * @deprecated Use the {@link #DefaultFullHttpRequest(HttpVersion, HttpMethod, String, ByteBuf,
68       * HttpHeadersFactory, HttpHeadersFactory)} constructor instead.
69       */
70      @Deprecated
71      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri,
72                                    ByteBuf content, boolean validateHeaders) {
73          this(httpVersion, method, uri, content,
74                  headersFactory().withValidation(validateHeaders),
75                  trailersFactory().withValidation(validateHeaders));
76      }
77  
78      /**
79       * Create a full HTTP response with the given HTTP version, method, URI, contents,
80       * and factories for creating headers and trailers.
81       * <p>
82       * The recommended default header factory is {@link DefaultHttpHeadersFactory#headersFactory()},
83       * and the recommended default trailer factory is {@link DefaultHttpHeadersFactory#trailersFactory()}.
84       */
85      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri,
86              ByteBuf content, HttpHeadersFactory headersFactory, HttpHeadersFactory trailersFactory) {
87          this(httpVersion, method, uri, content, headersFactory.newHeaders(), trailersFactory.newHeaders());
88      }
89  
90      /**
91       * Create a full HTTP response with the given HTTP version, method, URI, contents, and header and trailer objects.
92       */
93      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri,
94              ByteBuf content, HttpHeaders headers, HttpHeaders trailingHeader) {
95          super(httpVersion, method, uri, headers);
96          this.content = checkNotNull(content, "content");
97          this.trailingHeader = checkNotNull(trailingHeader, "trailingHeader");
98      }
99  
100     @Override
101     public HttpHeaders trailingHeaders() {
102         return trailingHeader;
103     }
104 
105     @Override
106     public ByteBuf content() {
107         return content;
108     }
109 
110     @Override
111     public int refCnt() {
112         return content.refCnt();
113     }
114 
115     @Override
116     public FullHttpRequest retain() {
117         content.retain();
118         return this;
119     }
120 
121     @Override
122     public FullHttpRequest retain(int increment) {
123         content.retain(increment);
124         return this;
125     }
126 
127     @Override
128     public FullHttpRequest touch() {
129         content.touch();
130         return this;
131     }
132 
133     @Override
134     public FullHttpRequest touch(Object hint) {
135         content.touch(hint);
136         return this;
137     }
138 
139     @Override
140     public boolean release() {
141         return content.release();
142     }
143 
144     @Override
145     public boolean release(int decrement) {
146         return content.release(decrement);
147     }
148 
149     @Override
150     public FullHttpRequest setProtocolVersion(HttpVersion version) {
151         super.setProtocolVersion(version);
152         return this;
153     }
154 
155     @Override
156     public FullHttpRequest setMethod(HttpMethod method) {
157         super.setMethod(method);
158         return this;
159     }
160 
161     @Override
162     public FullHttpRequest setUri(String uri) {
163         super.setUri(uri);
164         return this;
165     }
166 
167     @Override
168     public FullHttpRequest copy() {
169         return replace(content().copy());
170     }
171 
172     @Override
173     public FullHttpRequest duplicate() {
174         return replace(content().duplicate());
175     }
176 
177     @Override
178     public FullHttpRequest retainedDuplicate() {
179         return replace(content().retainedDuplicate());
180     }
181 
182     @Override
183     public FullHttpRequest replace(ByteBuf content) {
184         FullHttpRequest request = new DefaultFullHttpRequest(protocolVersion(), method(), uri(), content,
185                 headers().copy(), trailingHeaders().copy());
186         request.setDecoderResult(decoderResult());
187         return request;
188     }
189 
190     @Override
191     public int hashCode() {
192         int hash = this.hash;
193         if (hash == 0) {
194             if (ByteBufUtil.isAccessible(content())) {
195                 try {
196                     hash = 31 + content().hashCode();
197                 } catch (IllegalReferenceCountException ignored) {
198                     // Handle race condition between checking refCnt() == 0 and using the object.
199                     hash = 31;
200                 }
201             } else {
202                 hash = 31;
203             }
204             hash = 31 * hash + trailingHeaders().hashCode();
205             hash = 31 * hash + super.hashCode();
206             this.hash = hash;
207         }
208         return hash;
209     }
210 
211     @Override
212     public boolean equals(Object o) {
213         if (!(o instanceof DefaultFullHttpRequest)) {
214             return false;
215         }
216 
217         DefaultFullHttpRequest other = (DefaultFullHttpRequest) o;
218 
219         return super.equals(other) &&
220                content().equals(other.content()) &&
221                trailingHeaders().equals(other.trailingHeaders());
222     }
223 
224     @Override
225     public String toString() {
226         return HttpMessageUtil.appendFullRequest(new StringBuilder(256), this).toString();
227     }
228 }