/*
* Copyright (c) 2011-2013 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.core.http.impl;
import io.netty.channel.Channel;
import io.netty.handler.codec.http2.AbstractHttp2ConnectionHandlerBuilder;
import io.netty.handler.codec.http2.CompressorHttp2ConnectionEncoder;
import io.netty.handler.codec.http2.DefaultHttp2LocalFlowController;
import io.netty.handler.codec.http2.DelegatingDecompressorFrameListener;
import io.netty.handler.codec.http2.Http2ConnectionDecoder;
import io.netty.handler.codec.http2.Http2ConnectionEncoder;
import io.netty.handler.codec.http2.Http2FrameLogger;
import io.netty.handler.codec.http2.Http2LocalFlowController;
import io.netty.handler.codec.http2.Http2Settings;
import io.netty.handler.logging.LogLevel;
import io.vertx.core.http.HttpServerOptions;
import java.util.Map;
import java.util.function.Function;
/**
* @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
*/
class VertxHttp2ConnectionHandlerBuilder<C extends Http2ConnectionBase> extends AbstractHttp2ConnectionHandlerBuilder<VertxHttp2ConnectionHandler<C>, VertxHttp2ConnectionHandlerBuilder<C>> {
private Map<Channel, ? super C> connectionMap;
private boolean useCompression;
private boolean useDecompression;
private int compressionLevel = HttpServerOptions.DEFAULT_COMPRESSION_LEVEL;
private io.vertx.core.http.Http2Settings initialSettings;
private Function<VertxHttp2ConnectionHandler<C>, C> connectionFactory;
private boolean logEnabled;
VertxHttp2ConnectionHandlerBuilder() {
}
protected VertxHttp2ConnectionHandlerBuilder<C> server(boolean isServer) {
return super.server(isServer);
}
VertxHttp2ConnectionHandlerBuilder<C> connectionMap(Map<Channel, ? super C> connectionMap) {
this.connectionMap = connectionMap;
return this;
}
VertxHttp2ConnectionHandlerBuilder<C> initialSettings(io.vertx.core.http.Http2Settings settings) {
this.initialSettings = settings;
return this;
}
VertxHttp2ConnectionHandlerBuilder<C> useCompression(boolean useCompression) {
this.useCompression = useCompression;
return this;
}
/**
* This method allows to set the compression level to be used in the http/2 connection encoder
* (for data sent to client) when compression support is turned on (@see useCompression) and
* the client advertises to support deflate/gizip compression in the Accept-Encoding header
*
* default value is : 6 (Netty legacy)
*
* While one can think that best value is always the maximum compression ratio,
* there's a trade-off to consider: the most compressed level requires the most computatinal work to compress/decompress,
* E.g. you have it set fairly high on a high-volume website, you may experience performance degradation
* and latency on resource serving due to CPU overload, and however - as the comptational work is required also client side
* while decompressing - setting an higher compression level can result in an overall higher page load time
* especially nowadays when many clients are handled mobile devices with a low CPU profile.
*
* see also: http://www.gzip.org/algorithm.txt
*
* @param compressionLevel integer 1-9, 1 means use fastest algorithm, 9 slower algorithm but better compression ratio
* @return a reference to this instance for fulent API coding style
*/
VertxHttp2ConnectionHandlerBuilder<C> compressionLevel(int compressionLevel) {
this.compressionLevel = compressionLevel;
return this;
}
VertxHttp2ConnectionHandlerBuilder<C> useDecompression(boolean useDecompression) {
this.useDecompression = useDecompression;
return this;
}
VertxHttp2ConnectionHandlerBuilder<C> connectionFactory(Function<VertxHttp2ConnectionHandler<C>, C> connectionFactory) {
this.connectionFactory = connectionFactory;
return this;
}
VertxHttp2ConnectionHandlerBuilder<C> logEnabled(boolean logEnabled) {
this.logEnabled = logEnabled;
return this;
}
@Override
protected VertxHttp2ConnectionHandler<C> build() {
if (initialSettings != null) {
HttpUtils.fromVertxInitialSettings(isServer(), initialSettings, initialSettings());
}
if (logEnabled) {
frameLogger(new Http2FrameLogger(LogLevel.DEBUG));
}
return super.build();
}
@Override
protected VertxHttp2ConnectionHandler<C> build(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) throws Exception {
if (isServer()) {
if (useCompression) {
encoder = new CompressorHttp2ConnectionEncoder(encoder,compressionLevel,CompressorHttp2ConnectionEncoder.DEFAULT_WINDOW_BITS,CompressorHttp2ConnectionEncoder.DEFAULT_MEM_LEVEL);
}
VertxHttp2ConnectionHandler<C> handler = new VertxHttp2ConnectionHandler<>(connectionMap, decoder, encoder, initialSettings, connectionFactory);
if (useDecompression) {
frameListener(new DelegatingDecompressorFrameListener(decoder.connection(), handler.connection));
} else {
frameListener(handler.connection);
}
return handler;
} else {
VertxHttp2ConnectionHandler<C> handler = new VertxHttp2ConnectionHandler<>(connectionMap, decoder, encoder, initialSettings, connectionFactory);
if (useCompression) {
frameListener(new DelegatingDecompressorFrameListener(decoder.connection(), handler.connection));
} else {
frameListener(handler.connection);
}
return handler;
}
}
}