LibJF/libjf-mainhttp-v0/src/main/java/io/gitlab/jfronny/libjf/mainhttp/impl/HttpDecoder.java

59 lines
2.0 KiB
Java

package io.gitlab.jfronny.libjf.mainhttp.impl;
import io.gitlab.jfronny.libjf.mainhttp.impl.util.Trie;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class HttpDecoder extends ChannelInboundHandlerAdapter {
private static final Trie<String> METHOD = Trie.of(List.of(
"GET",
"HEAD",
"POST",
"PUT",
"PATCH",
"DELETE",
"OPTIONS", "TRACE", "CONNECT"
));
@Override
public void channelRead(@NotNull ChannelHandlerContext ctx, @NotNull Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
buf.markReaderIndex();
boolean passOn = true;
try {
// Check whether buf starts with an HTTP method, as a request would
Trie<String> current = METHOD;
while (buf.isReadable()
&& current != null
&& current.content == null)
current = current.next.get((char) buf.readByte());
if (current == null || current.content == null) return;
// Method identified, this is HTTP!
passOn = false;
// Read all data from buffer
buf.resetReaderIndex();
byte[] data = new byte[buf.readableBytes()];
buf.readBytes(data);
buf.release();
// Process request
ctx.pipeline()
.firstContext()
.writeAndFlush(Unpooled.wrappedBuffer(MainHttp.handle(data)))
.addListener(ChannelFutureListener.CLOSE);
} catch (RuntimeException re) {
MainHttp.LOGGER.error("Could not process HTTP", re);
} finally {
if (passOn) {
buf.resetReaderIndex();
ctx.channel().pipeline().remove(this);
ctx.fireChannelRead(msg);
}
}
}
}