View Javadoc
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    *   http://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  
20  import static io.netty.handler.codec.http.HttpConstants.*;
21  
22  /**
23   * Encodes an {@link HttpResponse} or an {@link HttpContent} into
24   * a {@link ByteBuf}.
25   */
26  public class HttpResponseEncoder extends HttpObjectEncoder<HttpResponse> {
27  
28      @Override
29      public boolean acceptOutboundMessage(Object msg) throws Exception {
30          return super.acceptOutboundMessage(msg) && !(msg instanceof HttpRequest);
31      }
32  
33      @Override
34      protected void encodeInitialLine(ByteBuf buf, HttpResponse response) throws Exception {
35          response.getProtocolVersion().encode(buf);
36          buf.writeByte(SP);
37          response.getStatus().encode(buf);
38          buf.writeBytes(CRLF);
39      }
40  
41      @Override
42      protected void sanitizeHeadersBeforeEncode(HttpResponse msg, boolean isAlwaysEmpty) {
43          if (isAlwaysEmpty) {
44              int status = msg.getStatus().code();
45              if ((status >= 100 && status <= 199) ||
46                      status == HttpResponseStatus.NO_CONTENT.code()) {
47  
48                  // Stripping Content-Length:
49                  // See https://tools.ietf.org/html/rfc7230#section-3.3.2
50                  msg.headers().remove(HttpHeaders.Names.CONTENT_LENGTH);
51  
52                  // Stripping Transfer-Encoding:
53                  // See https://tools.ietf.org/html/rfc7230#section-3.3.1
54                  msg.headers().remove(HttpHeaders.Names.TRANSFER_ENCODING);
55              }
56          }
57      }
58  
59      @Override
60      protected boolean isContentAlwaysEmpty(HttpResponse msg) {
61          // Correctly handle special cases as stated in:
62          // https://tools.ietf.org/html/rfc7230#section-3.3.3
63          int status = msg.getStatus().code();
64  
65          if (status >= 100 && status <= 199) {
66  
67              if (status == HttpResponseStatus.SWITCHING_PROTOCOLS.code()) {
68                  // We need special handling for WebSockets version 00 as it will include an body.
69                  // Fortunally this version should not really be used in the wild very often.
70                  // See https://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-1.2
71                  return msg.headers().contains(HttpHeaders.Names.SEC_WEBSOCKET_VERSION);
72              }
73              return true;
74          }
75          return status == HttpResponseStatus.NO_CONTENT.code() ||
76                  status == HttpResponseStatus.NOT_MODIFIED.code();
77      }
78  }