Use allocator when constructing ByteBufHolder sub-types or use Unpool… (#9377)

Motivation:

In many places Netty uses Unpooled.buffer(0) while should use EMPTY_BUFFER. We can't change this due to back compatibility in the constructors but can use Unpooled.EMPTY_BUFFER in some cases to ensure we not allocate at all. In others we can directly use the allocator either from the Channel / ChannelHandlerContext or the request / response.

Modification:

- Use Unpooled.EMPTY_BUFFER where possible
- Use allocator where possible

Result:

Fixes #9345 for websockets and http package
This commit is contained in:
Norman Maurer 2019-07-18 10:29:50 +02:00 committed by GitHub
parent 84cf8f14e9
commit 1e8c0c59f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 116 additions and 45 deletions

View File

@ -228,7 +228,8 @@ public class CorsHandler extends ChannelDuplexHandler {
}
private static void forbidden(final ChannelHandlerContext ctx, final HttpRequest request) {
HttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), FORBIDDEN);
HttpResponse response = new DefaultFullHttpResponse(
request.protocolVersion(), FORBIDDEN, ctx.alloc().buffer(0));
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, HttpHeaderValues.ZERO);
release(request);
respond(ctx, request, response);

View File

@ -108,7 +108,7 @@ public class WebSocket00FrameDecoder extends ReplayingDecoder<Void> implements W
if (type == (byte) 0xFF && frameSize == 0) {
receivedClosingHandshake = true;
return new CloseWebSocketFrame();
return new CloseWebSocketFrame(true, 0, ctx.alloc().buffer(0));
}
ByteBuf payload = readBytes(ctx.alloc(), buffer, (int) frameSize);
return new BinaryWebSocketFrame(payload);

View File

@ -178,7 +178,8 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
URI wsURL = uri();
// Format request
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, upgradeUrl(wsURL));
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, upgradeUrl(wsURL),
Unpooled.wrappedBuffer(key3));
HttpHeaders headers = request.headers();
if (customHeaders != null) {
@ -200,7 +201,6 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
// Set Content-Length to workaround some known defect.
// See also: http://www.ietf.org/mail-archive/web/hybi/current/msg02149.html
headers.set(HttpHeaderNames.CONTENT_LENGTH, key3.length);
request.content().writeBytes(key3);
return request;
}

View File

@ -15,6 +15,7 @@
*/
package io.netty.handler.codec.http.websocketx;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
@ -211,7 +212,8 @@ public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker {
}
// Format request
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, upgradeUrl(wsURL));
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, upgradeUrl(wsURL),
Unpooled.EMPTY_BUFFER);
HttpHeaders headers = request.headers();
if (customHeaders != null) {

View File

@ -15,6 +15,7 @@
*/
package io.netty.handler.codec.http.websocketx;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
@ -213,7 +214,8 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker {
}
// Format request
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, upgradeUrl(wsURL));
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, upgradeUrl(wsURL),
Unpooled.EMPTY_BUFFER);
HttpHeaders headers = request.headers();
if (customHeaders != null) {

View File

@ -15,6 +15,7 @@
*/
package io.netty.handler.codec.http.websocketx;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
@ -214,7 +215,8 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker {
}
// Format request
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, upgradeUrl(wsURL));
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, upgradeUrl(wsURL),
Unpooled.EMPTY_BUFFER);
HttpHeaders headers = request.headers();
if (customHeaders != null) {

View File

@ -141,7 +141,8 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker {
// Create the WebSocket handshake response.
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, new HttpResponseStatus(101,
isHixie76 ? "WebSocket Protocol Handshake" : "Web Socket Protocol Handshake"));
isHixie76 ? "WebSocket Protocol Handshake" : "Web Socket Protocol Handshake"),
req.content().alloc().buffer(0));
if (headers != null) {
res.headers().add(headers);
}

View File

@ -134,7 +134,8 @@ public class WebSocketServerHandshaker07 extends WebSocketServerHandshaker {
}
FullHttpResponse res =
new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS);
new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS,
req.content().alloc().buffer(0));
if (headers != null) {
res.headers().add(headers);

View File

@ -140,7 +140,8 @@ public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker {
throw new WebSocketHandshakeException("not a WebSocket request: missing key");
}
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS);
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS,
req.content().alloc().buffer(0));
if (headers != null) {
res.headers().add(headers);

View File

@ -139,7 +139,8 @@ public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker {
throw new WebSocketHandshakeException("not a WebSocket request: missing key");
}
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS);
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS,
req.content().alloc().buffer(0));
if (headers != null) {
res.headers().add(headers);
}

View File

@ -172,7 +172,7 @@ public class WebSocketServerHandshakerFactory {
public static ChannelFuture sendUnsupportedVersionResponse(Channel channel, ChannelPromise promise) {
HttpResponse res = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
HttpResponseStatus.UPGRADE_REQUIRED);
HttpResponseStatus.UPGRADE_REQUIRED, channel.alloc().buffer(0));
res.headers().set(HttpHeaderNames.SEC_WEBSOCKET_VERSION, WebSocketVersion.V13.toHttpHeaderValue());
HttpUtil.setContentLength(res, 0);
return channel.writeAndFlush(res, promise);

View File

@ -266,7 +266,7 @@ public class WebSocketServerProtocolHandler extends WebSocketProtocolHandler {
if (msg instanceof FullHttpRequest) {
((FullHttpRequest) msg).release();
FullHttpResponse response =
new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.FORBIDDEN);
new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.FORBIDDEN, ctx.alloc().buffer(0));
ctx.channel().writeAndFlush(response);
} else {
ctx.fireChannelRead(msg);

View File

@ -77,7 +77,7 @@ class WebSocketServerProtocolHandshakeHandler extends ChannelInboundHandlerAdapt
try {
if (!GET.equals(req.method())) {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN));
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN, ctx.alloc().buffer(0)));
return;
}

View File

@ -21,6 +21,7 @@ import io.netty.handler.codec.base64.Base64;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.FastThreadLocal;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.SuppressJava6Requirement;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ -90,7 +91,11 @@ final class WebSocketUtil {
* @param data The data to encode
* @return An encoded string containing the data
*/
@SuppressJava6Requirement(reason = "Guarded with java version check")
static String base64(byte[] data) {
if (PlatformDependent.javaVersion() >= 8) {
return java.util.Base64.getEncoder().encodeToString(data);
}
ByteBuf encodedData = Unpooled.wrappedBuffer(data);
ByteBuf encoded = Base64.encode(encodedData);
String encodedString = encoded.toString(CharsetUtil.UTF_8);

View File

@ -53,6 +53,7 @@ public class CorsHandlerTest {
public void nonCorsRequest() {
final HttpResponse response = simpleRequest(forAnyOrigin().build(), null);
assertThat(response.headers().contains(ACCESS_CONTROL_ALLOW_ORIGIN), is(false));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -60,6 +61,7 @@ public class CorsHandlerTest {
final HttpResponse response = simpleRequest(forAnyOrigin().build(), "http://localhost:7777");
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), is("*"));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_HEADERS), is(nullValue()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -70,6 +72,7 @@ public class CorsHandlerTest {
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), is("null"));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_CREDENTIALS), is(equalTo("true")));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_HEADERS), is(nullValue()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -78,6 +81,7 @@ public class CorsHandlerTest {
final HttpResponse response = simpleRequest(forOrigin(origin).build(), origin);
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), is(origin));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_HEADERS), is(nullValue()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -88,9 +92,12 @@ public class CorsHandlerTest {
final HttpResponse response1 = simpleRequest(forOrigins(origins).build(), origin1);
assertThat(response1.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), is(origin1));
assertThat(response1.headers().get(ACCESS_CONTROL_ALLOW_HEADERS), is(nullValue()));
assertThat(ReferenceCountUtil.release(response1), is(true));
final HttpResponse response2 = simpleRequest(forOrigins(origins).build(), origin2);
assertThat(response2.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), is(origin2));
assertThat(response2.headers().get(ACCESS_CONTROL_ALLOW_HEADERS), is(nullValue()));
assertThat(ReferenceCountUtil.release(response2), is(true));
}
@Test
@ -100,6 +107,7 @@ public class CorsHandlerTest {
forOrigins("https://localhost:8888").build(), origin);
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), is(nullValue()));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_HEADERS), is(nullValue()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -112,6 +120,7 @@ public class CorsHandlerTest {
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_METHODS), containsString("GET"));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_METHODS), containsString("DELETE"));
assertThat(response.headers().get(VARY), equalTo(ORIGIN.toString()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -127,6 +136,7 @@ public class CorsHandlerTest {
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_HEADERS), containsString("content-type"));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_HEADERS), containsString("xheader1"));
assertThat(response.headers().get(VARY), equalTo(ORIGIN.toString()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -136,6 +146,7 @@ public class CorsHandlerTest {
assertThat(response.headers().get(CONTENT_LENGTH), is("0"));
assertThat(response.headers().get(DATE), is(notNullValue()));
assertThat(response.headers().get(VARY), equalTo(ORIGIN.toString()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -147,6 +158,7 @@ public class CorsHandlerTest {
assertThat(response.headers().get(of("CustomHeader")), equalTo("somevalue"));
assertThat(response.headers().get(VARY), equalTo(ORIGIN.toString()));
assertThat(response.headers().get(CONTENT_LENGTH), is("0"));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -155,6 +167,7 @@ public class CorsHandlerTest {
final CorsConfig config = forOrigin("http://localhost").build();
final HttpResponse response = preflightRequest(config, origin, "xheader1");
assertThat(response.headers().contains(ACCESS_CONTROL_ALLOW_ORIGIN), is(false));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -168,6 +181,7 @@ public class CorsHandlerTest {
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
assertValues(response, headerName, value1, value2);
assertThat(response.headers().get(VARY), equalTo(ORIGIN.toString()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -181,6 +195,7 @@ public class CorsHandlerTest {
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
assertValues(response, headerName, value1, value2);
assertThat(response.headers().get(VARY), equalTo(ORIGIN.toString()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -195,6 +210,7 @@ public class CorsHandlerTest {
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
assertThat(response.headers().get(of("GenHeader")), equalTo("generatedValue"));
assertThat(response.headers().get(VARY), equalTo(ORIGIN.toString()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -207,6 +223,7 @@ public class CorsHandlerTest {
final HttpResponse response = preflightRequest(config, origin, "content-type, xheader1");
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), is(equalTo("null")));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_CREDENTIALS), is(equalTo("true")));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -215,6 +232,7 @@ public class CorsHandlerTest {
final CorsConfig config = forOrigin(origin).allowCredentials().build();
final HttpResponse response = preflightRequest(config, origin, "content-type, xheader1");
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_CREDENTIALS), is(equalTo("true")));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -223,6 +241,7 @@ public class CorsHandlerTest {
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "");
// the only valid value for Access-Control-Allow-Credentials is true.
assertThat(response.headers().contains(ACCESS_CONTROL_ALLOW_CREDENTIALS), is(false));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -232,6 +251,7 @@ public class CorsHandlerTest {
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), equalTo("*"));
assertThat(response.headers().get(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("custom1"));
assertThat(response.headers().get(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("custom2"));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -239,6 +259,7 @@ public class CorsHandlerTest {
final CorsConfig config = forAnyOrigin().allowCredentials().build();
final HttpResponse response = simpleRequest(config, "http://localhost:7777");
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_CREDENTIALS), equalTo("true"));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -246,6 +267,7 @@ public class CorsHandlerTest {
final CorsConfig config = forAnyOrigin().build();
final HttpResponse response = simpleRequest(config, "http://localhost:7777");
assertThat(response.headers().contains(ACCESS_CONTROL_ALLOW_CREDENTIALS), is(false));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -255,6 +277,7 @@ public class CorsHandlerTest {
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_CREDENTIALS), equalTo("true"));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), equalTo("http://localhost:7777"));
assertThat(response.headers().get(VARY), equalTo(ORIGIN.toString()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -263,6 +286,7 @@ public class CorsHandlerTest {
final HttpResponse response = simpleRequest(config, "http://localhost:7777");
assertThat(response.headers().get(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("one"));
assertThat(response.headers().get(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("two"));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -271,6 +295,7 @@ public class CorsHandlerTest {
final HttpResponse response = simpleRequest(config, "http://localhost:7777");
assertThat(response.status(), is(FORBIDDEN));
assertThat(response.headers().get(CONTENT_LENGTH), is("0"));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -279,6 +304,7 @@ public class CorsHandlerTest {
final HttpResponse response = simpleRequest(config, "http://localhost:7777");
assertThat(response.status(), is(OK));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), is(nullValue()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -287,6 +313,7 @@ public class CorsHandlerTest {
final HttpResponse response = simpleRequest(config, null);
assertThat(response.status(), is(OK));
assertThat(response.headers().get(ACCESS_CONTROL_ALLOW_ORIGIN), is(nullValue()));
assertThat(ReferenceCountUtil.release(response), is(true));
}
@Test
@ -478,7 +505,9 @@ public class CorsHandlerTest {
httpRequest.headers().set(ACCESS_CONTROL_REQUEST_HEADERS, requestHeaders);
}
assertThat(channel.writeInbound(httpRequest), is(false));
return (HttpResponse) channel.readOutbound();
HttpResponse response = channel.readOutbound();
assertThat(channel.finish(), is(false));
return response;
}
private static HttpResponse preflightRequest(final CorsConfig config,

View File

@ -76,6 +76,7 @@ public class WebSocket08EncoderDecoderTest {
Assert.assertNotNull(response);
Assert.assertEquals(expectedStatus.code(), response.statusCode());
Assert.assertEquals(errorMessage, response.reasonText());
response.release();
// Without auto-close
config = WebSocketDecoderConfig.newBuilder()

View File

@ -258,7 +258,9 @@ public abstract class WebSocketClientHandshakerTest {
// Create a EmbeddedChannel which we will use to encode a BinaryWebsocketFrame to bytes and so use these
// to test the actual handshaker.
WebSocketServerHandshakerFactory factory = new WebSocketServerHandshakerFactory(url, null, false);
WebSocketServerHandshaker socketServerHandshaker = factory.newHandshaker(shaker.newHandshakeRequest());
FullHttpRequest request = shaker.newHandshakeRequest();
WebSocketServerHandshaker socketServerHandshaker = factory.newHandshaker(request);
request.release();
EmbeddedChannel websocketChannel = new EmbeddedChannel(socketServerHandshaker.newWebSocketEncoder(),
socketServerHandshaker.newWebsocketDecoder());
assertTrue(websocketChannel.writeOutbound(new BinaryWebSocketFrame(Unpooled.wrappedBuffer(data))));

View File

@ -29,6 +29,7 @@ import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
import org.junit.Before;
import org.junit.Test;
@ -59,6 +60,7 @@ public class WebSocketServerProtocolHandlerTest {
assertEquals(SWITCHING_PROTOCOLS, response.status());
response.release();
assertNotNull(WebSocketServerProtocolHandler.getHandshaker(handshakerCtx.channel()));
assertFalse(ch.finish());
}
@Test
@ -75,6 +77,7 @@ public class WebSocketServerProtocolHandlerTest {
response = responses.remove();
assertEquals(FORBIDDEN, response.status());
response.release();
assertFalse(ch.finish());
}
@Test
@ -94,6 +97,7 @@ public class WebSocketServerProtocolHandlerTest {
assertEquals(BAD_REQUEST, response.status());
assertEquals("not a WebSocket handshake request: missing upgrade", getResponseMessage(response));
response.release();
assertFalse(ch.finish());
}
@Test
@ -114,6 +118,7 @@ public class WebSocketServerProtocolHandlerTest {
assertEquals(BAD_REQUEST, response.status());
assertEquals("not a WebSocket request: missing key", getResponseMessage(response));
response.release();
assertFalse(ch.finish());
}
@Test
@ -122,6 +127,10 @@ public class WebSocketServerProtocolHandlerTest {
EmbeddedChannel ch = createChannel(customTextFrameHandler);
writeUpgradeRequest(ch);
FullHttpResponse response = responses.remove();
assertEquals(SWITCHING_PROTOCOLS, response.status());
response.release();
if (ch.pipeline().context(HttpRequestDecoder.class) != null) {
// Removing the HttpRequestDecoder because we are writing a TextWebSocketFrame and thus
// decoding is not necessary.
@ -131,6 +140,7 @@ public class WebSocketServerProtocolHandlerTest {
ch.writeInbound(new TextWebSocketFrame("payload"));
assertEquals("processed: payload", customTextFrameHandler.getContent());
assertFalse(ch.finish());
}
private EmbeddedChannel createChannel() {
@ -151,7 +161,7 @@ public class WebSocketServerProtocolHandlerTest {
}
private static String getResponseMessage(FullHttpResponse response) {
return new String(response.content().array());
return response.content().toString(CharsetUtil.UTF_8);
}
private class MockOutboundHandler extends ChannelOutboundHandlerAdapter {

View File

@ -15,6 +15,7 @@
*/
package io.netty.example.http.cors;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
@ -30,7 +31,8 @@ import io.netty.handler.codec.http.HttpVersion;
public class OkResponseHandler extends SimpleChannelInboundHandler<Object> {
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) {
final FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
final FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.EMPTY_BUFFER);
response.headers().set("custom-response-header", "Some value");
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}

View File

@ -272,9 +272,6 @@ public class HttpStaticFileServerHandler extends SimpleChannelInboundHandler<Ful
private static final Pattern ALLOWED_FILE_NAME = Pattern.compile("[^-\\._]?[^<>&\\\"]*");
private void sendListing(ChannelHandlerContext ctx, File dir, String dirPath) {
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
StringBuilder buf = new StringBuilder()
.append("<!DOCTYPE html>\r\n")
.append("<html><head><meta charset='utf-8' /><title>")
@ -307,15 +304,18 @@ public class HttpStaticFileServerHandler extends SimpleChannelInboundHandler<Ful
}
buf.append("</ul></body></html>\r\n");
ByteBuf buffer = Unpooled.copiedBuffer(buf, CharsetUtil.UTF_8);
response.content().writeBytes(buffer);
buffer.release();
ByteBuf buffer = ctx.alloc().buffer(buf.length());
buffer.writeCharSequence(buf.toString(), CharsetUtil.UTF_8);
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, buffer);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
this.sendAndCleanupConnection(ctx, response);
}
private void sendRedirect(ChannelHandlerContext ctx, String newUri) {
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, FOUND);
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, FOUND, Unpooled.EMPTY_BUFFER);
response.headers().set(HttpHeaderNames.LOCATION, newUri);
this.sendAndCleanupConnection(ctx, response);
@ -336,7 +336,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelInboundHandler<Ful
* Context
*/
private void sendNotModified(ChannelHandlerContext ctx) {
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, NOT_MODIFIED);
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, NOT_MODIFIED, Unpooled.EMPTY_BUFFER);
setDateHeader(response);
this.sendAndCleanupConnection(ctx, response);

View File

@ -16,6 +16,7 @@
package io.netty.example.http.snoop;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
@ -83,7 +84,7 @@ public final class HttpSnoopClient {
// Prepare the HTTP request.
HttpRequest request = new DefaultFullHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath(), Unpooled.EMPTY_BUFFER);
request.headers().set(HttpHeaderNames.HOST, host);
request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
request.headers().set(HttpHeaderNames.ACCEPT_ENCODING, HttpHeaderValues.GZIP);

View File

@ -185,7 +185,7 @@ public class HttpSnoopServerHandler extends SimpleChannelInboundHandler<Object>
}
private static void send100Continue(ChannelHandlerContext ctx) {
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, CONTINUE);
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, CONTINUE, Unpooled.EMPTY_BUFFER);
ctx.write(response);
}

View File

@ -72,13 +72,13 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>
private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
// Handle a bad request.
if (!req.decoderResult().isSuccess()) {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST));
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST, Unpooled.EMPTY_BUFFER));
return;
}
// Allow only GET methods.
if (!GET.equals(req.method())) {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN));
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN, Unpooled.EMPTY_BUFFER));
return;
}
@ -94,7 +94,7 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>
return;
}
if ("/favicon.ico".equals(req.uri())) {
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND);
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND, Unpooled.EMPTY_BUFFER);
sendHttpResponse(ctx, req, res);
return;
}

View File

@ -57,13 +57,13 @@ public class WebSocketIndexPageHandler extends SimpleChannelInboundHandler<FullH
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
// Handle a bad request.
if (!req.decoderResult().isSuccess()) {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST));
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST, Unpooled.EMPTY_BUFFER));
return;
}
// Allow only GET methods.
if (!GET.equals(req.method())) {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN));
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN, Unpooled.EMPTY_BUFFER));
return;
}
@ -78,7 +78,7 @@ public class WebSocketIndexPageHandler extends SimpleChannelInboundHandler<FullH
sendHttpResponse(ctx, req, res);
} else {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND));
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND, Unpooled.EMPTY_BUFFER));
}
}

View File

@ -15,6 +15,7 @@
package io.netty.example.http2.helloworld.client;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
@ -113,7 +114,7 @@ public final class Http2Client {
System.err.println("Sending request(s)...");
if (URL != null) {
// Create a simple GET request.
FullHttpRequest request = new DefaultFullHttpRequest(HTTP_1_1, GET, URL);
FullHttpRequest request = new DefaultFullHttpRequest(HTTP_1_1, GET, URL, Unpooled.EMPTY_BUFFER);
request.headers().add(HttpHeaderNames.HOST, hostName);
request.headers().add(HttpConversionUtil.ExtensionHeaderNames.SCHEME.text(), scheme.name());
request.headers().add(HttpHeaderNames.ACCEPT_ENCODING, HttpHeaderValues.GZIP);

View File

@ -14,6 +14,7 @@
*/
package io.netty.example.http2.helloworld.client;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
@ -137,7 +138,7 @@ public class Http2ClientInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
DefaultFullHttpRequest upgradeRequest =
new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/", Unpooled.EMPTY_BUFFER);
// Set HOST header as the remote peer may require it.
InetSocketAddress remote = (InetSocketAddress) ctx.channel().remoteAddress();

View File

@ -28,6 +28,7 @@ import static io.netty.util.internal.ObjectUtil.checkNotNull;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
@ -49,7 +50,7 @@ public class HelloWorldHttp1Handler extends SimpleChannelInboundHandler<FullHttp
@Override
public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
if (HttpUtil.is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE, Unpooled.EMPTY_BUFFER));
}
boolean keepAlive = HttpUtil.isKeepAlive(req);

View File

@ -16,6 +16,7 @@
package io.netty.example.http2.tiles;
import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
import static io.netty.buffer.Unpooled.copiedBuffer;
import static io.netty.buffer.Unpooled.unreleasableBuffer;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
@ -47,7 +48,7 @@ public final class FallbackRequestHandler extends SimpleChannelInboundHandler<Ht
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
if (HttpUtil.is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE, EMPTY_BUFFER));
}
ByteBuf content = ctx.alloc().buffer();

View File

@ -23,6 +23,8 @@ import static io.netty.handler.codec.http.HttpUtil.isKeepAlive;
import static io.netty.handler.codec.http.HttpResponseStatus.CONTINUE;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_0;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
@ -40,7 +42,7 @@ public final class Http1RequestHandler extends Http2RequestHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
if (HttpUtil.is100ContinueExpected(request)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE, Unpooled.EMPTY_BUFFER));
}
super.channelRead0(ctx, request);
}

View File

@ -21,6 +21,7 @@ import java.math.BigInteger;
import javax.net.ssl.SSLSession;
import javax.security.cert.X509Certificate;
import io.netty.buffer.Unpooled;
import org.bouncycastle.asn1.ocsp.OCSPResponseStatus;
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.bouncycastle.cert.ocsp.CertificateStatus;
@ -164,7 +165,8 @@ public class OcspClientExample {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
FullHttpRequest request = new DefaultFullHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, "/", Unpooled.EMPTY_BUFFER);
request.headers().set(HttpHeaderNames.HOST, host);
request.headers().set(HttpHeaderNames.USER_AGENT, "netty-ocsp-example/1.0");

View File

@ -16,6 +16,7 @@
package io.netty.example.spdy.client;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
@ -84,7 +85,8 @@ public final class SpdyClient {
System.out.println("Connected to " + HOST + ':' + PORT);
// Create a GET request.
HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "");
HttpRequest request = new DefaultFullHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, "", Unpooled.EMPTY_BUFFER);
request.headers().set(HttpHeaderNames.HOST, HOST);
request.headers().set(HttpHeaderNames.ACCEPT_ENCODING, HttpHeaderValues.GZIP);

View File

@ -50,7 +50,7 @@ public class SpdyServerHandler extends SimpleChannelInboundHandler<Object> {
HttpRequest req = (HttpRequest) msg;
if (is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE, Unpooled.EMPTY_BUFFER));
}
boolean keepAlive = isKeepAlive(req);

View File

@ -73,13 +73,13 @@ public class AutobahnServerHandler extends ChannelInboundHandlerAdapter {
throws Exception {
// Handle a bad request.
if (!req.decoderResult().isSuccess()) {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST));
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST, ctx.alloc().buffer(0)));
return;
}
// Allow only GET methods.
if (!GET.equals(req.method())) {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN));
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN, ctx.alloc().buffer(0)));
return;
}

View File

@ -47,7 +47,7 @@ public class HelloWorldHttp1Handler extends SimpleChannelInboundHandler<FullHttp
@Override
public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
if (HttpUtil.is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE, ctx.alloc().buffer(0)));
}
boolean keepAlive = HttpUtil.isKeepAlive(req);