From 0b290c009135a02826226c0a7cde87f3fe174f8f Mon Sep 17 00:00:00 2001 From: Jaroslaw Rzeszotko Date: Mon, 21 Mar 2022 19:54:50 +0100 Subject: [PATCH] Use direct buffers for gzip input/output, if configured - fixes. --- .../gzip/GzipHttpOutputInterceptor.java | 108 ++++++++++-------- 1 file changed, 58 insertions(+), 50 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java index 8e7afe3e7434..7310576edfe6 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java @@ -266,6 +266,16 @@ public GzipBufferCB(ByteBuffer content, boolean complete, Callback callback) super(callback); _content = content; _last = complete; + + if (_channel.isUseOutputDirectByteBuffers()) + { + _crc.update(_content.slice()); + + Deflater deflater = _deflaterEntry.get(); + deflater.setInput(_content); + if (_last) + deflater.finish(); + } } @Override @@ -318,66 +328,64 @@ protected Action process() throws Exception Deflater deflater = _deflaterEntry.get(); if (!deflater.finished()) { - if (deflater.needsInput()) + if (_channel.isUseOutputDirectByteBuffers()) { - // if there is no more content available to compress - // then we are either finished all content or just the current write. - if (BufferUtil.isEmpty(_content)) + if (deflater.needsInput() && !_last) { - if (_last) - deflater.finish(); - else - return Action.SUCCEEDED; + return Action.SUCCEEDED; } - else if (_channel.isUseOutputDirectByteBuffers()) - { - _crc.update(_content.slice()); - deflater.setInput(_content); - if (_last) - deflater.finish(); - } - else + + int pos = BufferUtil.flipToFill(_buffer); + int produced = deflater.deflate(_buffer, _syncFlush ? Deflater.SYNC_FLUSH : Deflater.NO_FLUSH); + BufferUtil.flipToFlush(_buffer, pos); + } + else + { + if (deflater.needsInput()) { - // If there is more content available to compress, we have to make sure - // it is available in an array for the current deflator API, maybe slicing - // of content. - ByteBuffer slice; - if (_content.hasArray()) - slice = _content; + // if there is no more content available to compress + // then we are either finished all content or just the current write. + if (BufferUtil.isEmpty(_content)) + { + if (_last) + deflater.finish(); + else + return Action.SUCCEEDED; + } else { - if (_copy == null) - _copy = _channel.getByteBufferPool().acquire(_bufferSize, false); + // If there is more content available to compress, we have to make sure + // it is available in an array for the current deflator API, maybe slicing + // of content. + ByteBuffer slice; + if (_content.hasArray()) + slice = _content; else - BufferUtil.clear(_copy); - slice = _copy; - BufferUtil.append(_copy, _content); + { + if (_copy == null) + _copy = _channel.getByteBufferPool().acquire(_bufferSize, false); + else + BufferUtil.clear(_copy); + slice = _copy; + BufferUtil.append(_copy, _content); + } + + // transfer the data from the slice to the the deflator + byte[] array = slice.array(); + int off = slice.arrayOffset() + slice.position(); + int len = slice.remaining(); + _crc.update(array, off, len); + // Ideally we would want to use the ByteBuffer API for Deflaters. However due the the ByteBuffer implementation + // of the CRC32.update() it is less efficient for us to use this rather than to convert to array ourselves, + // unless the ByteBuffer is a DirectByteBuffer. + _deflaterEntry.get().setInput(array, off, len); + slice.position(slice.position() + len); + if (_last && BufferUtil.isEmpty(_content)) + deflater.finish(); } - - // transfer the data from the slice to the the deflator - byte[] array = slice.array(); - int off = slice.arrayOffset() + slice.position(); - int len = slice.remaining(); - _crc.update(array, off, len); - // Ideally we would want to use the ByteBuffer API for Deflaters. However due the the ByteBuffer implementation - // of the CRC32.update() it is less efficient for us to use this rather than to convert to array ourselves, - // unless the ByteBuffer is a DirectByteBuffer. - _deflaterEntry.get().setInput(array, off, len); - slice.position(slice.position() + len); - if (_last && BufferUtil.isEmpty(_content)) - deflater.finish(); } - } - // deflate the content into the available space in the buffer - if (_channel.isUseOutputDirectByteBuffers()) - { - int pos = BufferUtil.flipToFill(_buffer); - deflater.deflate(_buffer, _syncFlush ? Deflater.SYNC_FLUSH : Deflater.NO_FLUSH); - BufferUtil.flipToFlush(_buffer, pos); - } - else - { + // deflate the content into the available space in the buffer int off = _buffer.arrayOffset() + _buffer.limit(); int len = BufferUtil.space(_buffer); int produced = deflater.deflate(_buffer.array(), off, len, _syncFlush ? Deflater.SYNC_FLUSH : Deflater.NO_FLUSH);