Я относительно новый с netty и не уверен, что я делаю все правильно. Я постараюсь быть как можно короче. Пожалуйста, задайте больше информации, если что-то неясно.Обработать исключение HTTP-клиента в netty
Итак, у меня есть сетчатый сервер, обслуживающий HTTP-запросы, где ожидается, что содержимое сообщения protobuf будет сериализовано для строк Json.
Трубопровод канала выглядит следующим образом:
@Override protected void initChannel(final SocketChannel channel) throws Exception {
final ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(1048576));
pipeline.addLast(new HttpProtobufServerCodec(charset, requestConverter, responseConverter));
pipeline.addLast(new ProtobufMessageHandler(mapping));
}
Первого два обработчик канала является стандартной Нетти материал,
HttpProtobufServerCodec выглядит следующим образом:
public class HttpProtobufServerCodec extends CombinedChannelDuplexHandler<HttpToProtobufDecoder, ProtobufToHttpEncoder>
и HttpToProtobufDecoder выглядит следующим образом:
public final class HttpToProtobufDecoder extends MessageToMessageDecoder<FullHttpRequest> {
private Charset charset;
private final Converter<byte[], ?> converter;
protected HttpToProtobufDecoder(final Charset charset, final Converter<byte[], ?> converter) {
this.charset = charset;
this.converter = converter;
}
@Override protected void decode(final ChannelHandlerContext ctx, final FullHttpRequest msg, final List<Object> out)
throws Exception {
byte[] payloadBytes = new byte[msg.content().readableBytes()];
msg.content().readBytes(payloadBytes);
Message message = (Message) converter.convert(payloadBytes);
out.add(message);
}
@Override public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.BAD_REQUEST,
Unpooled.wrappedBuffer(charset.encode("Could not read request!").array()));
//ctx.writeAndFlush(response);
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
}
Итак, я получаю FullHttpRequest в HttpToProtobufDecoder и пытаюсь декодировать содержимое запроса в сообщении protobuf. Это порождает исключение, если контент не может быть декодирован, что помещает нас в метод exceptionCaught (...).
В Исключении пойманный ответ HTTP 400 создается и записывается в channelHandlerContext. Здесь у меня есть мой вопрос.
если комментарии по следующим направлениям включаются:
//ctx.writeAndFlush(response);
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
клиент таймаут при чтении тела ответа. Но если я закрою канал после записи 400, все будет хорошо. Что происходит? чтение входного потока блокируется, потому что нет доступных входных данных. То есть мы застряли в in.read (...) ниже, где-то далеко вниз в коде клиента:
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
byteCount += bytesRead;
}
Итак, вопрос в том, есть ли у вас близкий канал после написания ответа HTTP 400 для какой-то причины ?
Я даже об этом правильно? Должен ли я писать ответное сообщение HTTP в exceptionCaught?
Извините, если вопрос немного неясен. Любая помощь будет высоко ценится!
/Спасибо!
Спасибо! Я сам пришел к этому точному выводу. Приятно подтвердить это. Я каким-то образом, хотя HttpServerCodec должен/должен справиться с этим. –