未受欢迎!
该项目已存档和不太19岁。
FMJSJX/libnetty提供了一种新的
Fast-CGI编解码器组件。
netty-codec-fcgi
基于Netty-4.1.x的快速CGI编解码器组件。
快速开始:
客户端
fastcgiclient.java
...
import com . github . fmjsjx . netty . codec . fcgi . DefaultFullFCGIRequest ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIParameterNames ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIParameterValues ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIRequestEncoder ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIResponseDecoder ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIServiceMode ;
...
public class FastCGIClient {
...
public static void main ( String [] args ) {
FCGIRequestEncoder fcgiRequestEncoder = new FCGIRequestEncoder ();
NioEventLoopGroup group = new NioEventLoopGroup ( 1 );
Bootstrap b = new Bootstrap (). group ( group ). channel ( SocketChannel . class ). option ( ChannelOption . TCP_NODELAY , true )
. handler ( new ChannelInitializer < SocketChannel >() {
@ Override
protected void initChannel ( SocketChannel ch ) throws Exception {
ch . pipeline (). addLast ( fcgiRequestEncoder , new FCGIResponseDecoder ( FCGIServiceMode . SIMPLE ),
new FastCGIClientHandler ());
}
});
ChannelFutureListener listener = future -> {
Channel ch = future . channel ();
if ( future . isSuccess ()) {
// send request
DefaultFullFCGIRequest request = new DefaultFullFCGIRequest ( requestId );
request . params (). addParam ( FCGIParameterNames . SCRIPT_FILENAME , "/path/to/script_name" )
. addParam ( FCGIParameterNames . REQUEST_METHOD , FCGIParameterValues . POST )
. addParam ( FCGIParameterNames . CONTENT_TYPE , FCGIParameterValues . APPLICATION_JSON_UTF8 )
. addParam ( FCGIParameterNames . CONTENT_LENGTH , String . valueOf ( content . readableBytes ()))
. addParam ( FCGIParameterNames . REMOTE_ADDR , clientIP );
request . stdin ( content );
ch . writeAndFlush ( request );
} else {
// connect failed
}
};
ChannelFuture cf = b . connect ( serverAddress );
cf . addListener ( listener );
}
...
}fastcgiclienthandler.java
import static com . github . fmjsjx . netty . codec . fcgi . FCGIConstants .*;
import com . github . fmjsjx . netty . codec . fcgi . FCGIEndRequest ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIResponseHeaders ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIResponseUtil ;
import com . github . fmjsjx . netty . codec . fcgi . FullFCGIResponse ;
...
public class FastCGIClientHandler extends SimpleChannelInboundHandler < FullFCGIResponse > {
...
@ Override
protected void channelRead0 ( ChannelHandlerContext ctx , FullFCGIResponse msg ) throws Exception {
try {
FCGIEndRequest endRequest = msg . endRequest ();
if ( endRequest . protocolStatus () != FCGI_REQUEST_COMPLETE ) {
// error protocol status
ctx . close ();
return ;
}
if ( msg . hasStderr ()) {
// has stderr, ...
System . err . println ( msg . stderr (). content (). toString ( CharsetUtil . UTF_8 ));
ctx . close ();
return ;
}
ByteBuf content = msg . stdout (). content ();
FCGIResponseHeaders headers = FCGIResponseUtil . decodeHeaders ( content );
...
} finally {
// in simple mode, just close socket connection when response received
ctx . close ();
}
}
...
}服务器端
fastcgiserver.java
import com . github . fmjsjx . netty . codec . fcgi . FCGIRequestDecoder ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIResponseEncoder ;
...
public class FastCGIServer {
...
public static void main ( String [] args ) throws Exception {
FCGIResponseEncoder fcgiResponseEncoder = new FCGIResponseEncoder ();
NioEventLoopGroup bossGroup = new NioEventLoopGroup ( 1 );
NioEventLoopGroup workerGroup = new NioEventLoopGroup ();
try {
ServerBootstrap b = new ServerBootstrap (). group ( bossGroup , workerGroup ). channel ( ServerSocketChannel . class )
. option ( ChannelOption . SO_BACKLOG , 128 ). childOption ( ChannelOption . TCP_NODELAY , true )
. handler ( new ChannelInitializer < SocketChannel >() {
@ Override
protected void initChannel ( SocketChannel ch ) throws Exception {
ch . pipeline (). addLast ( fcgiResponseEncoder , new FCGIRequestDecoder (), new FastCGIServerHandler ());
}
});
Channel serverChannel = b . bind ( address ). sync (). channel ();
serverChannel . closeFuture (). sync ();
} finally {
bossGroup . shutdownGracefully ();
workerGroup . shutdownGracefully ();
}
}
...
}fastcgiserverhandler.java
import com . github . fmjsjx . netty . codec . fcgi . DefaultFullFCGIResponse ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIAbortRequest ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIGetValues ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIGetValuesResult ;
import com . github . fmjsjx . netty . codec . fcgi . FCGIMessage ;
import com . github . fmjsjx . netty . codec . fcgi . FullFCGIRequest ;
...
public class FastCGIServerHandler extends SimpleChannelInboundHandler < FCGIMessage > {
...
@ Override
protected void channelRead0 ( ChannelHandlerContext ctx , FCGIMessage msg ) throws Exception {
if ( msg instanceof FullFCGIRequest ) {
requestReceived ( ctx , ( FullFCGIRequest ) msg );
} else if ( msg instanceof FCGIAbortRequest ) {
// abort request received
ctx . close ();
} else if ( msg instanceof FCGIGetValues ) {
FCGIGetValuesResult result = new FCGIGetValuesResult ();
// do something and set result...
...
ctx . writeAndFlush ( result ). addListener ( ChannelFutureListener . CLOSE );
}
}
private void requestReceived ( ChannelHandlerContext ctx , FullFCGIRequest msg ) {
// do something and generate resposne content...
ByteBuf content = ...;
DefaultFullFCGIResponse response = new DefaultFullFCGIResponse ( msg . requestId ());
response . stdout ( content );
ctx . writeAndFlush ( response ). addListener ( ChannelFutureListener . CLOSE );
}
...
}下载源码
通过命令行克隆项目:
git clone https://github.com/fmjsjx/netty-codec-fcgi.git