Refactor HttpContentCompressor using CompressionEncoderFactory (#11480)
Motivation: The `HttpContentCompressor.beginEncode()` method has too many if else, so consider refactoring Modification: Create the corresponding `CompressionEncoderFactory` according to the compression algorithm, remove the if else Result: The code of `HttpContentCompressor` is cleaner than the previous implementation Signed-off-by: xingrufei <xingrufei@sogou-inc.com> Co-authored-by: Norman Maurer <norman_maurer@apple.com>
This commit is contained in:
parent
6085cd7ab6
commit
df22356a3a
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package io.netty.handler.codec.http;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compression Encoder Factory for create {@link MessageToByteEncoder}
|
||||||
|
* used to compress http content
|
||||||
|
*/
|
||||||
|
interface CompressionEncoderFactory {
|
||||||
|
MessageToByteEncoder<ByteBuf> createEncoder();
|
||||||
|
}
|
@ -15,8 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.http;
|
package io.netty.handler.codec.http;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
import io.netty.channel.embedded.EmbeddedChannel;
|
||||||
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
|
import io.netty.handler.codec.compression.ZlibEncoder;
|
||||||
import io.netty.handler.codec.compression.Brotli;
|
import io.netty.handler.codec.compression.Brotli;
|
||||||
import io.netty.handler.codec.compression.BrotliEncoder;
|
import io.netty.handler.codec.compression.BrotliEncoder;
|
||||||
import io.netty.handler.codec.compression.ZlibCodecFactory;
|
import io.netty.handler.codec.compression.ZlibCodecFactory;
|
||||||
@ -30,6 +33,9 @@ import io.netty.handler.codec.compression.ZstdEncoder;
|
|||||||
import io.netty.handler.codec.compression.ZstdOptions;
|
import io.netty.handler.codec.compression.ZstdOptions;
|
||||||
import io.netty.util.internal.ObjectUtil;
|
import io.netty.util.internal.ObjectUtil;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compresses an {@link HttpMessage} and an {@link HttpContent} in {@code gzip} or
|
* Compresses an {@link HttpMessage} and an {@link HttpContent} in {@code gzip} or
|
||||||
* {@code deflate} encoding while respecting the {@code "Accept-Encoding"} header.
|
* {@code deflate} encoding while respecting the {@code "Accept-Encoding"} header.
|
||||||
@ -50,6 +56,7 @@ public class HttpContentCompressor extends HttpContentEncoder {
|
|||||||
private final int memLevel;
|
private final int memLevel;
|
||||||
private final int contentSizeThreshold;
|
private final int contentSizeThreshold;
|
||||||
private ChannelHandlerContext ctx;
|
private ChannelHandlerContext ctx;
|
||||||
|
private final Map<String, CompressionEncoderFactory> factories;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new handler with the default compression level (<tt>6</tt>),
|
* Creates a new handler with the default compression level (<tt>6</tt>),
|
||||||
@ -130,6 +137,7 @@ public class HttpContentCompressor extends HttpContentEncoder {
|
|||||||
this.gzipOptions = null;
|
this.gzipOptions = null;
|
||||||
this.deflateOptions = null;
|
this.deflateOptions = null;
|
||||||
this.zstdOptions = null;
|
this.zstdOptions = null;
|
||||||
|
this.factories = null;
|
||||||
supportsCompressionOptions = false;
|
supportsCompressionOptions = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +207,14 @@ public class HttpContentCompressor extends HttpContentEncoder {
|
|||||||
this.gzipOptions = gzipOptions;
|
this.gzipOptions = gzipOptions;
|
||||||
this.deflateOptions = deflateOptions;
|
this.deflateOptions = deflateOptions;
|
||||||
this.zstdOptions = zstdOptions;
|
this.zstdOptions = zstdOptions;
|
||||||
|
this.factories = new HashMap<String, CompressionEncoderFactory>() {
|
||||||
|
{
|
||||||
|
put("gzip", new GzipEncoderFactory());
|
||||||
|
put("deflate", new DeflateEncoderFactory());
|
||||||
|
put("br", new BrEncoderFactory());
|
||||||
|
put("zstd", new ZstdEncoderFactory());
|
||||||
|
}
|
||||||
|
};
|
||||||
this.compressionLevel = -1;
|
this.compressionLevel = -1;
|
||||||
this.windowBits = -1;
|
this.windowBits = -1;
|
||||||
this.memLevel = -1;
|
this.memLevel = -1;
|
||||||
@ -232,32 +248,15 @@ public class HttpContentCompressor extends HttpContentEncoder {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetContentEncoding.equals("gzip")) {
|
CompressionEncoderFactory encoderFactory = factories.get(targetContentEncoding);
|
||||||
return new Result(targetContentEncoding,
|
|
||||||
new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(),
|
if (encoderFactory == null) {
|
||||||
ctx.channel().config(), ZlibCodecFactory.newZlibEncoder(
|
throw new Error();
|
||||||
ZlibWrapper.GZIP, gzipOptions.compressionLevel()
|
|
||||||
, gzipOptions.windowBits(), gzipOptions.memLevel())));
|
|
||||||
}
|
}
|
||||||
if (targetContentEncoding.equals("deflate")) {
|
|
||||||
return new Result(targetContentEncoding,
|
return new Result(targetContentEncoding,
|
||||||
new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(),
|
new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(),
|
||||||
ctx.channel().config(), ZlibCodecFactory.newZlibEncoder(
|
ctx.channel().config(), encoderFactory.createEncoder()));
|
||||||
ZlibWrapper.ZLIB, deflateOptions.compressionLevel(),
|
|
||||||
deflateOptions.windowBits(), deflateOptions.memLevel())));
|
|
||||||
}
|
|
||||||
if (targetContentEncoding.equals("br")) {
|
|
||||||
return new Result(targetContentEncoding,
|
|
||||||
new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(),
|
|
||||||
ctx.channel().config(), new BrotliEncoder(brotliOptions.parameters())));
|
|
||||||
}
|
|
||||||
if (targetContentEncoding.equals("zstd")) {
|
|
||||||
return new Result(targetContentEncoding,
|
|
||||||
new EmbeddedChannel(ctx.channel().id(), ctx.channel().metadata().hasDisconnect(),
|
|
||||||
ctx.channel().config(), new ZstdEncoder(zstdOptions.compressionLevel(),
|
|
||||||
zstdOptions.blockSize(), zstdOptions.maxEncodeSize())));
|
|
||||||
}
|
|
||||||
throw new Error();
|
|
||||||
} else {
|
} else {
|
||||||
ZlibWrapper wrapper = determineWrapper(acceptEncoding);
|
ZlibWrapper wrapper = determineWrapper(acceptEncoding);
|
||||||
if (wrapper == null) {
|
if (wrapper == null) {
|
||||||
@ -384,4 +383,57 @@ public class HttpContentCompressor extends HttpContentEncoder {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compression Encoder Factory that creates {@link ZlibEncoder}s
|
||||||
|
* used to compress http content for gzip content encoding
|
||||||
|
*/
|
||||||
|
private final class GzipEncoderFactory implements CompressionEncoderFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageToByteEncoder<ByteBuf> createEncoder() {
|
||||||
|
return ZlibCodecFactory.newZlibEncoder(
|
||||||
|
ZlibWrapper.GZIP, gzipOptions.compressionLevel(),
|
||||||
|
gzipOptions.windowBits(), gzipOptions.memLevel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compression Encoder Factory that creates {@link ZlibEncoder}s
|
||||||
|
* used to compress http content for deflate content encoding
|
||||||
|
*/
|
||||||
|
private final class DeflateEncoderFactory implements CompressionEncoderFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageToByteEncoder<ByteBuf> createEncoder() {
|
||||||
|
return ZlibCodecFactory.newZlibEncoder(
|
||||||
|
ZlibWrapper.ZLIB, deflateOptions.compressionLevel(),
|
||||||
|
deflateOptions.windowBits(), deflateOptions.memLevel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compression Encoder Factory that creates {@link BrotliEncoder}s
|
||||||
|
* used to compress http content for br content encoding
|
||||||
|
*/
|
||||||
|
private final class BrEncoderFactory implements CompressionEncoderFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageToByteEncoder<ByteBuf> createEncoder() {
|
||||||
|
return new BrotliEncoder(brotliOptions.parameters());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compression Encoder Factory for create {@link ZstdEncoder}
|
||||||
|
* used to compress http content for zstd content encoding
|
||||||
|
*/
|
||||||
|
private final class ZstdEncoderFactory implements CompressionEncoderFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageToByteEncoder<ByteBuf> createEncoder() {
|
||||||
|
return new ZstdEncoder(zstdOptions.compressionLevel(),
|
||||||
|
zstdOptions.blockSize(), zstdOptions.maxEncodeSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user