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 a {@link FullHttpResponse}.
29   */
30  public class DefaultFullHttpResponse extends DefaultHttpResponse implements FullHttpResponse {
31  
32      private final ByteBuf content;
33      private final HttpHeaders trailingHeaders;
34  
35      /**
36       * Used to cache the value of the hash code and avoid {@link IllegalReferenceCountException}.
37       */
38      private int hash;
39  
40      /**
41       * Create an empty HTTP response with the given HTTP version and status.
42       */
43      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status) {
44          this(version, status, Unpooled.buffer(0), headersFactory(), trailersFactory());
45      }
46  
47      /**
48       * Create an HTTP response with the given HTTP version, status, and contents.
49       */
50      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, ByteBuf content) {
51          this(version, status, content, headersFactory(), trailersFactory());
52      }
53  
54      /**
55       * Create an empty HTTP response with the given HTTP version, status, and optional header validation.
56       *
57       * @deprecated Prefer the {@link #DefaultFullHttpResponse(HttpVersion, HttpResponseStatus, ByteBuf,
58       * HttpHeadersFactory, HttpHeadersFactory)} constructor instead.
59       */
60      @Deprecated
61      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, boolean validateHeaders) {
62          this(version, status, Unpooled.buffer(0),
63                  headersFactory().withValidation(validateHeaders),
64                  trailersFactory().withValidation(validateHeaders));
65      }
66  
67      /**
68       * Create an empty HTTP response with the given HTTP version, status, optional header validation,
69       * and optional header combining.
70       *
71       * @deprecated Prefer the {@link #DefaultFullHttpResponse(HttpVersion, HttpResponseStatus, ByteBuf,
72       * HttpHeadersFactory, HttpHeadersFactory)} constructor instead.
73       */
74      @Deprecated
75      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, boolean validateHeaders,
76                                     boolean singleFieldHeaders) {
77          this(version, status, Unpooled.buffer(0),
78                  headersFactory().withValidation(validateHeaders).withCombiningHeaders(singleFieldHeaders),
79                  trailersFactory().withValidation(validateHeaders).withCombiningHeaders(singleFieldHeaders));
80      }
81  
82      /**
83       * Create an HTTP response with the given HTTP version, status, contents, and optional header validation.
84       *
85       * @deprecated Prefer the {@link #DefaultFullHttpResponse(HttpVersion, HttpResponseStatus, ByteBuf,
86       * HttpHeadersFactory, HttpHeadersFactory)} constructor instead.
87       */
88      @Deprecated
89      public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status,
90                                     ByteBuf content, boolean validateHeaders) {
91          this(version, status, content,
92                  headersFactory().withValidation(validateHeaders),
93                  trailersFactory().withValidation(validateHeaders));
94      }
95  
96      /**
97       * Create an HTTP response with the given HTTP version, status, contents, optional header validation,
98       * and optional header combining.
99       *
100      * @deprecated Prefer the {@link #DefaultFullHttpResponse(HttpVersion, HttpResponseStatus, ByteBuf,
101      * HttpHeadersFactory, HttpHeadersFactory)} constructor instead.
102      */
103     @Deprecated
104     public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status,
105                                    ByteBuf content, boolean validateHeaders, boolean singleFieldHeaders) {
106         this(version, status, content,
107                 headersFactory().withValidation(validateHeaders).withCombiningHeaders(singleFieldHeaders),
108                 trailersFactory().withValidation(validateHeaders).withCombiningHeaders(singleFieldHeaders));
109     }
110 
111     /**
112      * Create an HTTP response with the given HTTP version, status, contents,
113      * and with headers and trailers created by the given header factories.
114      * <p>
115      * The recommended header factory is {@link DefaultHttpHeadersFactory#headersFactory()},
116      * and the recommended trailer factory is {@link DefaultHttpHeadersFactory#trailersFactory()}.
117      */
118     public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, ByteBuf content,
119                                    HttpHeadersFactory headersFactory, HttpHeadersFactory trailersFactory) {
120         this(version, status, content, headersFactory.newHeaders(), trailersFactory.newHeaders());
121     }
122 
123     /**
124      * Create an HTTP response with the given HTTP version, status, contents, headers and trailers.
125      */
126     public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status,
127             ByteBuf content, HttpHeaders headers, HttpHeaders trailingHeaders) {
128         super(version, status, headers);
129         this.content = checkNotNull(content, "content");
130         this.trailingHeaders = checkNotNull(trailingHeaders, "trailingHeaders");
131     }
132 
133     @Override
134     public HttpHeaders trailingHeaders() {
135         return trailingHeaders;
136     }
137 
138     @Override
139     public ByteBuf content() {
140         return content;
141     }
142 
143     @Override
144     public int refCnt() {
145         return content.refCnt();
146     }
147 
148     @Override
149     public FullHttpResponse retain() {
150         content.retain();
151         return this;
152     }
153 
154     @Override
155     public FullHttpResponse retain(int increment) {
156         content.retain(increment);
157         return this;
158     }
159 
160     @Override
161     public FullHttpResponse touch() {
162         content.touch();
163         return this;
164     }
165 
166     @Override
167     public FullHttpResponse touch(Object hint) {
168         content.touch(hint);
169         return this;
170     }
171 
172     @Override
173     public boolean release() {
174         return content.release();
175     }
176 
177     @Override
178     public boolean release(int decrement) {
179         return content.release(decrement);
180     }
181 
182     @Override
183     public FullHttpResponse setProtocolVersion(HttpVersion version) {
184         super.setProtocolVersion(version);
185         return this;
186     }
187 
188     @Override
189     public FullHttpResponse setStatus(HttpResponseStatus status) {
190         super.setStatus(status);
191         return this;
192     }
193 
194     @Override
195     public FullHttpResponse copy() {
196         return replace(content().copy());
197     }
198 
199     @Override
200     public FullHttpResponse duplicate() {
201         return replace(content().duplicate());
202     }
203 
204     @Override
205     public FullHttpResponse retainedDuplicate() {
206         return replace(content().retainedDuplicate());
207     }
208 
209     @Override
210     public FullHttpResponse replace(ByteBuf content) {
211         FullHttpResponse response = new DefaultFullHttpResponse(protocolVersion(), status(), content,
212                 headers().copy(), trailingHeaders().copy());
213         response.setDecoderResult(decoderResult());
214         return response;
215     }
216 
217     @Override
218     public int hashCode() {
219         int hash = this.hash;
220         if (hash == 0) {
221             if (ByteBufUtil.isAccessible(content())) {
222                 try {
223                     hash = 31 + content().hashCode();
224                 } catch (IllegalReferenceCountException ignored) {
225                     // Handle race condition between checking refCnt() == 0 and using the object.
226                     hash = 31;
227                 }
228             } else {
229                 hash = 31;
230             }
231             hash = 31 * hash + trailingHeaders().hashCode();
232             hash = 31 * hash + super.hashCode();
233             this.hash = hash;
234         }
235         return hash;
236     }
237 
238     @Override
239     public boolean equals(Object o) {
240         if (!(o instanceof DefaultFullHttpResponse)) {
241             return false;
242         }
243 
244         DefaultFullHttpResponse other = (DefaultFullHttpResponse) o;
245 
246         return super.equals(other) &&
247                content().equals(other.content()) &&
248                trailingHeaders().equals(other.trailingHeaders());
249     }
250 
251     @Override
252     public String toString() {
253         return HttpMessageUtil.appendFullResponse(new StringBuilder(256), this).toString();
254     }
255 }