![JAR search and dependency download from the Maven repository](/logo.png)
rpc.turbo.transport.server.rest.handler.NettyRestHandler Maven / Gradle / Ivy
The newest version!
package rpc.turbo.transport.server.rest.handler;
import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpResponseStatus.SERVICE_UNAVAILABLE;
import java.net.InetSocketAddress;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpUtil;
import rpc.turbo.common.RemoteContext;
import rpc.turbo.config.HostPort;
import rpc.turbo.filter.RestServerFilter;
import rpc.turbo.invoke.InvokeException;
import rpc.turbo.invoke.Invoker;
import rpc.turbo.invoke.ServerInvokerFactory;
import rpc.turbo.param.HttpParamExtractor;
import rpc.turbo.param.MethodParam;
import rpc.turbo.serialization.JsonMapper;
import rpc.turbo.transport.server.rest.protocol.RestHttpResponse;
public class NettyRestHandler extends SimpleChannelInboundHandler {
private static final Log logger = LogFactory.getLog(NettyRestHandler.class);
private static final Throwable ONLY_SUPPORT_GET_POST = new InvokeException("only support get and post", false);
private static final Throwable NOT_SUPPORT_THIS_METHOD = new InvokeException("not support this method", false);
private static final Throwable UNKNOWN = new InvokeException("UNKNOWN ERROR", false);
private final ServerInvokerFactory invokerFactory;
private final JsonMapper jsonMapper;
private final CopyOnWriteArrayList filters;
private HostPort clientAddress;
private HostPort serverAddress;
public NettyRestHandler(ServerInvokerFactory invokerFactory, JsonMapper jsonMapper,
CopyOnWriteArrayList filters) {
this.invokerFactory = invokerFactory;
this.jsonMapper = jsonMapper;
this.filters = filters;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
if (logger.isInfoEnabled()) {
logger.info("channelActive: " + ctx.channel());
}
InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
clientAddress = new HostPort(insocket.getAddress().getHostAddress(), 0);
insocket = (InetSocketAddress) ctx.channel().localAddress();
serverAddress = new HostPort(insocket.getAddress().getHostAddress(), insocket.getPort());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (logger.isErrorEnabled()) {
logger.error("Exception caught on " + ctx.channel(), cause);
}
ctx.channel().close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, final FullHttpRequest httpRequest) throws Exception {
boolean keepAlive = HttpUtil.isKeepAlive(httpRequest);
String uri = httpRequest.uri();
HttpMethod httpMethod = httpRequest.method();
int index = uri.indexOf('&', invokerFactory.restPrefix.length());
if (index < 0) {
index = uri.length();
}
if (invokerFactory.restPrefix.length() >= index) {
if (logger.isInfoEnabled()) {
logger.info("not support this method " + toString(httpRequest));
}
doRequestFilter(httpRequest, null);
ctx.write(new RestHttpResponse(null, httpRequest, NOT_FOUND, NOT_SUPPORT_THIS_METHOD, keepAlive),
ctx.voidPromise());
return;
}
String restPath = uri.substring(invokerFactory.restPrefix.length(), index);
final Invoker> invoker = invokerFactory.get(restPath);
CompletableFuture> future = null;
try {
if (invoker == null) {
if (logger.isInfoEnabled()) {
logger.info("not support this method " + toString(httpRequest));
}
doRequestFilter(httpRequest, null);
ctx.write(new RestHttpResponse(null, httpRequest, NOT_FOUND, NOT_SUPPORT_THIS_METHOD, keepAlive),
ctx.voidPromise());
return;
}
boolean allowHandle = doRequestFilter(httpRequest, invoker);
if (!allowHandle) {
ctx.write(new RestHttpResponse(invoker, httpRequest, SERVICE_UNAVAILABLE,
RestServerFilter.SERVER_FILTER_DENY, keepAlive), ctx.voidPromise());
return;
}
Object params = null;
if (httpMethod == HttpMethod.GET) {
params = HttpParamExtractor.extractFromQueryPath(invoker, uri, index);
} else if (httpMethod == HttpMethod.POST) {
params = HttpParamExtractor.extractFromBody(invoker, jsonMapper, httpRequest.content());
} else {
if (logger.isInfoEnabled()) {
logger.info("only support get and post " + toString(httpRequest));
}
ctx.write(new RestHttpResponse(invoker, httpRequest, INTERNAL_SERVER_ERROR, ONLY_SUPPORT_GET_POST,
keepAlive), ctx.voidPromise());
return;
}
if (params == null) {
future = invoker.invoke();
} else if (params instanceof MethodParam) {
future = invoker.invoke((MethodParam) params);
} else if (params instanceof Object[]) {
future = invoker.invoke((Object[]) params);
} else {
future = invoker.invoke((Object) params);
}
} catch (Throwable e) {
if (logger.isWarnEnabled()) {
logger.warn(uri + " error ", e);
}
ctx.write(new RestHttpResponse(invoker, httpRequest, INTERNAL_SERVER_ERROR, e, keepAlive),
ctx.voidPromise());
return;
}
if (future == null) {
if (logger.isWarnEnabled()) {
logger.warn("unknown error " + toString(httpRequest));
}
ctx.write(new RestHttpResponse(invoker, httpRequest, INTERNAL_SERVER_ERROR, UNKNOWN, keepAlive),
ctx.voidPromise());
return;
}
future.whenComplete((result, throwable) -> {
if (result != null) {
ctx.write(new RestHttpResponse(invoker, httpRequest, OK, result, keepAlive), ctx.voidPromise());
} else if (throwable != null) {
ctx.write(new RestHttpResponse(invoker, httpRequest, INTERNAL_SERVER_ERROR, throwable, keepAlive),
ctx.voidPromise());
} else {
ctx.write(new RestHttpResponse(invoker, httpRequest, INTERNAL_SERVER_ERROR, UNKNOWN, keepAlive),
ctx.voidPromise());
}
});
}
private boolean doRequestFilter(FullHttpRequest request, Invoker> invoker) {
final int filterLength = filters.size();
if (filterLength == 0) {
return true;
}
RemoteContext.setServerAddress(serverAddress);
RemoteContext.setClientAddress(clientAddress);
if (invoker != null) {
RemoteContext.setRemoteMethod(invoker.getMethod());
RemoteContext.setServiceMethodName(invokerFactory.getServiceMethodName(invoker.getServiceId()));
} else {
RemoteContext.setRemoteMethod(null);
RemoteContext.setServiceMethodName(null);
}
for (int i = 0; i < filterLength; i++) {
RestServerFilter filter = filters.get(i);
if (!filter.onRecive(request)) {
return false;
}
}
return true;
}
private String toString(FullHttpRequest httpRequest) {
String uri = httpRequest.uri();
HttpMethod httpMethod = httpRequest.method();
return httpMethod.name() + " " + uri;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy