-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#66 Added a betamax-netty module with a basic proof-of-concept HTTP e…
…xchange
- Loading branch information
1 parent
0b7ef95
commit 7c1a0b1
Showing
7 changed files
with
158 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
dependencies { | ||
compile project(':betamax-core') | ||
compile nettyDependency | ||
} | ||
|
||
modifyPom { | ||
project { | ||
name 'Betamax Netty' | ||
description 'The base Netty support classes for Betamax.' | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
betamax-netty/src/main/java/co/freeside/betamax/proxy/netty/HttpChannelInitializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package co.freeside.betamax.proxy.netty; | ||
|
||
import io.netty.channel.*; | ||
import io.netty.channel.socket.*; | ||
import io.netty.handler.codec.http.*; | ||
import io.netty.handler.stream.*; | ||
|
||
/** | ||
* Configures up a channel to handle HTTP requests and responses. | ||
*/ | ||
public class HttpChannelInitializer extends ChannelInitializer<SocketChannel> { | ||
|
||
public static final int MAX_CONTENT_LENGTH = 65536; | ||
|
||
private final ChannelHandler handler; | ||
|
||
public HttpChannelInitializer(ChannelHandler handler) { | ||
this.handler = handler; | ||
} | ||
|
||
@Override | ||
public void initChannel(SocketChannel channel) throws Exception { | ||
channel.pipeline() | ||
.addLast(new HttpRequestDecoder()) | ||
.addLast(new HttpObjectAggregator(MAX_CONTENT_LENGTH)) | ||
.addLast(new HttpResponseEncoder()) | ||
.addLast(new ChunkedWriteHandler()) | ||
.addLast(handler); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
betamax-netty/src/main/java/co/freeside/betamax/proxy/netty/NettyBetamaxServer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package co.freeside.betamax.proxy.netty; | ||
|
||
import java.net.*; | ||
import io.netty.bootstrap.*; | ||
import io.netty.channel.*; | ||
import io.netty.channel.nio.*; | ||
import io.netty.channel.socket.nio.*; | ||
|
||
/** | ||
* A Netty-based implementation of the Betamax proxy server. | ||
*/ | ||
public class NettyBetamaxServer { | ||
|
||
private final int port; | ||
private final ChannelHandler handler; | ||
private EventLoopGroup group; | ||
private Channel channel; | ||
|
||
public NettyBetamaxServer(int port, ChannelHandler handler) { | ||
this.port = port; | ||
this.handler = handler; | ||
} | ||
|
||
public InetSocketAddress run() throws Exception { | ||
group = new NioEventLoopGroup(); | ||
ServerBootstrap bootstrap = new ServerBootstrap(); | ||
bootstrap.group(group) | ||
.channel(NioServerSocketChannel.class) | ||
.childHandler(new HttpChannelInitializer(handler)) | ||
.option(ChannelOption.SO_BACKLOG, 128) | ||
.childOption(ChannelOption.SO_KEEPALIVE, true); | ||
|
||
channel = bootstrap.bind(port).sync().channel(); | ||
return (InetSocketAddress) channel.localAddress(); | ||
} | ||
|
||
public void shutdown() throws InterruptedException { | ||
if (channel != null) channel.close().sync(); | ||
if (group != null) group.shutdownGracefully(); | ||
} | ||
|
||
} |
37 changes: 37 additions & 0 deletions
37
betamax-netty/src/test/groovy/co/freeside/betamax/proxy/netty/EchoServerHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package co.freeside.betamax.proxy.netty; | ||
|
||
import io.netty.buffer.*; | ||
import io.netty.channel.*; | ||
import io.netty.handler.codec.http.*; | ||
import io.netty.util.*; | ||
import static io.netty.handler.codec.http.HttpHeaders.Names.*; | ||
import static io.netty.handler.codec.http.HttpResponseStatus.*; | ||
import static io.netty.handler.codec.http.HttpVersion.*; | ||
|
||
@ChannelHandler.Sharable | ||
public class EchoServerHandler extends ChannelInboundHandlerAdapter { | ||
|
||
@Override | ||
public void channelRead(ChannelHandlerContext ctx, Object msg) { | ||
FullHttpRequest request = (FullHttpRequest) msg; | ||
FullHttpResponse response = new DefaultFullHttpResponse( | ||
HTTP_1_1, | ||
OK, | ||
request.content() | ||
); | ||
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8"); | ||
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); | ||
} | ||
|
||
@Override | ||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { | ||
cause.printStackTrace(); | ||
FullHttpResponse response = new DefaultFullHttpResponse( | ||
HTTP_1_1, | ||
OK, | ||
Unpooled.copiedBuffer(cause.getClass().getSimpleName() + ": " + cause.getMessage(), CharsetUtil.UTF_8) | ||
); | ||
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8"); | ||
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
betamax-netty/src/test/groovy/co/freeside/betamax/proxy/netty/NettyServerSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package co.freeside.betamax.proxy.netty | ||
|
||
import spock.lang.Specification | ||
|
||
class NettyServerSpec extends Specification { | ||
|
||
void "can serve HTTP responses with Netty"() { | ||
given: | ||
def server = new NettyBetamaxServer(port, new EchoServerHandler()) | ||
server.run() | ||
|
||
when: | ||
HttpURLConnection connection = new URL("http://localhost:$port/").openConnection() | ||
connection.requestMethod = "POST" | ||
connection.doInput = true | ||
connection.doOutput = true | ||
connection.outputStream.withWriter("UTF-8") { writer -> | ||
writer << message | ||
} | ||
connection.connect() | ||
|
||
then: | ||
connection.inputStream.getText("UTF-8") == message | ||
|
||
cleanup: | ||
server.shutdown() | ||
|
||
where: | ||
port = 5000 | ||
message = "O HAI" | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters