2013-08-19 2 views
2

Я использую Netty 3.6.6, и я бы хотел отправить большой ответ обратно вызывающему. Я не могу скопировать тело ответа в ChannelBuffer, так как в некоторых случаях он будет очень большим.как передать ответ по HTTP с netty

Я переношу сервер из CXF в Netty, ранее я мог просто использовать OutputStream, предоставленный CXF, для записи данных.

Первоначально я попытался просто отправить ответ без содержания, а затем продолжал записывать данные на канал в серии буферов 8k. Это не удалось, поскольку клиент, казалось, получил исходный ответ и не видел никаких данных и жаловался. Я попробовал настроить ответ как chunked, но это, похоже, не имело никакого значения, и не устанавливало chunked header, клиент всегда видел пустой поток.

Я видел пример файлового сервера для 3.6.6, и это похоже на то, что я хочу сделать, за исключением того, что данные не будут файлом. Я видел ChunkedStream & NioStream, который казался близким к тому, что мне нужно, за исключением того, что они принимают InputStream/ReadableByteChannel, тогда как у меня есть OutputStream; Я мог бы попробовать использовать PipedInput & OutputStreams, но похоже, что это принесет неудачное узкое место.

Я уверен, что есть способ передать много данных обратно клиенту в ответ на запрос, но я просто не вижу, как это сделать, если у меня нет файла.

Мне также интересно, как вы можете сообщить клиенту, что ответ завершен, если соединение поддерживается, и вы передаете контент, но не знаете длину контента. Похоже, что клиент будет ждать навсегда, чтобы соединение закрылось в этих случаях.

Изменения статического примера файлового сервера из 3.6.6, чтобы удалить заголовок длиной содержимого (только закомментировать), указать, что св фрагментированного ответ

response.setChunked(true); 
    response.setHeader(Names.TRANSFER_ENCODING, Values.CHUNKED); 

, а затем с помощью ChunkedNioStream отправить файл после написание ответа:

// Write the initial line and the header. 
    ch.write(response); 

    final ReadableByteChannel aIn = java.nio.channels.Channels.newChannel(new FileInputStream(file)); 
    ChannelFuture writeFuture = ch.write(new ChunkedNioStream(aIn)); 

Вырабатывает нежелательное поведение, клиент получает пару сотен байт, а затем прекратить прием, в основном то, что я вижу в моем приложении. Правильная вещь, похоже, происходит только с длиной содержимого, что невозможно в моем случае использования.

ответ

5

При попытке написать ChunkedNioStream в ChunkedWriteHandler, он просто создает поток, который содержит содержание ChunkedNioStreamтолько. То есть он производит ChannelBuffer s, а не HttpChunk s.

Поскольку HttpMessageEncoder обрабатывает только HttpMessage и HttpChunk, ChannelBuffer производства ChunkedNioStream обойден к проводу, без HTTP куска заголовка предварённого, в результате чего ваш браузера спутать.

Чтобы решить эту проблему, вам необходимо реализовать свой собственный ChunkedInput, который производит HttpChunk s вместо ChannelBuffer s. Тем не менее, я должен согласиться с тем, что это может быть сложной задачей, поэтому вы можете просто использовать fork HttpMessageEncoder, чтобы он также понимал ChannelBuffer и обрабатывал его точно так же, как HttpChunk. Пожалуйста, посмотрите this part от HttpMessageEncoder для получения дополнительной информации.

+0

Возможно, это исправлено в Netty 4.x с 'ChunkedInput', правильно? –

Смежные вопросы