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 }