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.netty5.handler.codec.http;
17  
18  import io.netty5.buffer.api.Buffer;
19  import io.netty5.buffer.api.BufferClosedException;
20  import io.netty5.util.Send;
21  
22  import static java.util.Objects.requireNonNull;
23  
24  /**
25   * Default implementation of {@link FullHttpRequest}.
26   */
27  public class DefaultFullHttpRequest extends DefaultHttpRequest implements FullHttpRequest {
28      private final Buffer payload;
29      private final HttpHeaders trailingHeader;
30  
31      /**
32       * Used to cache the value of the hash code and avoid {@link BufferClosedException}.
33       */
34      private int hash;
35  
36      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri, Buffer payload) {
37          this(httpVersion, method, uri, payload, true);
38      }
39  
40      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri,
41                                    Buffer payload, boolean validateHeaders) {
42          super(httpVersion, method, uri, validateHeaders);
43          this.payload = requireNonNull(payload, "payload");
44          trailingHeader = new DefaultHttpHeaders(validateHeaders);
45      }
46  
47      public DefaultFullHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri,
48                                    Buffer payload, HttpHeaders headers, HttpHeaders trailingHeader) {
49          super(httpVersion, method, uri, headers);
50          this.payload = requireNonNull(payload, "payload");
51          this.trailingHeader = requireNonNull(trailingHeader, "trailingHeader");
52      }
53  
54      @Override
55      public void close() {
56          payload.close();
57      }
58  
59      @Override
60      public boolean isAccessible() {
61          return payload.isAccessible();
62      }
63  
64      @Override
65      public FullHttpRequest touch(Object hint) {
66          payload.touch(hint);
67          return this;
68      }
69  
70      @Override
71      public Buffer payload() {
72          return payload;
73      }
74  
75      @Override
76      public Send<FullHttpRequest> send() {
77          return payload.send().map(FullHttpRequest.class,
78                  payload -> new DefaultFullHttpRequest(
79                          protocolVersion(), method(), uri(), payload, headers(), trailingHeader));
80      }
81  
82      @Override
83      public FullHttpRequest copy() {
84          return new DefaultFullHttpRequest(
85                  protocolVersion(), method(), uri(), payload.copy(), headers().copy(), trailingHeader.copy());
86      }
87  
88      @Override
89      public HttpHeaders trailingHeaders() {
90          return trailingHeader;
91      }
92  
93      @Override
94      public FullHttpRequest setProtocolVersion(HttpVersion version) {
95          super.setProtocolVersion(version);
96          return this;
97      }
98  
99      @Override
100     public FullHttpRequest setMethod(HttpMethod method) {
101         super.setMethod(method);
102         return this;
103     }
104 
105     @Override
106     public FullHttpRequest setUri(String uri) {
107         super.setUri(uri);
108         return this;
109     }
110 
111     @Override
112     public int hashCode() {
113         int hash = this.hash;
114         if (hash == 0) {
115             final Buffer payload = payload();
116             if (payload.isAccessible()) {
117                 try {
118                     hash = 31 + payload.hashCode();
119                 } catch (BufferClosedException ignored) {
120                     // Handle race condition between liveness checking and using the object.
121                     hash = 31;
122                 }
123             } else {
124                 hash = 31;
125             }
126             hash = 31 * hash + trailingHeaders().hashCode();
127             hash = 31 * hash + super.hashCode();
128             this.hash = hash;
129         }
130         return hash;
131     }
132 
133     @Override
134     public boolean equals(Object o) {
135         if (!(o instanceof DefaultFullHttpRequest)) {
136             return false;
137         }
138 
139         DefaultFullHttpRequest other = (DefaultFullHttpRequest) o;
140 
141         return super.equals(other) &&
142                 payload().equals(other.payload()) &&
143                 trailingHeaders().equals(other.trailingHeaders());
144     }
145 
146     @Override
147     public String toString() {
148         return HttpMessageUtil.appendFullRequest(new StringBuilder(256), this).toString();
149     }
150 }