/*
 * Copyright 2012-2018 the original author or authors.
 *
 * Licensed 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
 *
 *      http://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 org.springframework.boot.autoconfigure.web.embedded;

import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.netty.NettyServerCustomizer;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import org.springframework.util.unit.DataSize;

/**
 * Customization for Netty-specific features.
 *
 * @author Brian Clozel
 * @author Chentao Qu
 * @since 2.1.0
 */
public class NettyWebServerFactoryCustomizer
		implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory>, Ordered {

	private final Environment environment;

	private final ServerProperties serverProperties;

	public NettyWebServerFactoryCustomizer(Environment environment,
			ServerProperties serverProperties) {
		this.environment = environment;
		this.serverProperties = serverProperties;
	}

	@Override
	public int getOrder() {
		return 0;
	}

	@Override
	public void customize(NettyReactiveWebServerFactory factory) {
		factory.setUseForwardHeaders(
				getOrDeduceUseForwardHeaders(this.serverProperties, this.environment));
		PropertyMapper propertyMapper = PropertyMapper.get();
		propertyMapper.from(this.serverProperties::getMaxHttpHeaderSize).whenNonNull()
				.asInt(DataSize::toBytes)
				.to((maxHttpRequestHeaderSize) -> customizeMaxHttpHeaderSize(factory,
						maxHttpRequestHeaderSize));
	}

	private boolean getOrDeduceUseForwardHeaders(ServerProperties serverProperties,
			Environment environment) {
		if (serverProperties.isUseForwardHeaders() != null) {
			return serverProperties.isUseForwardHeaders();
		}
		CloudPlatform platform = CloudPlatform.getActive(environment);
		return platform != null && platform.isUsingForwardHeaders();
	}

	private void customizeMaxHttpHeaderSize(NettyReactiveWebServerFactory factory,
			Integer maxHttpHeaderSize) {
		factory.addServerCustomizers((NettyServerCustomizer) (httpServer) -> httpServer
				.httpRequestDecoder((httpRequestDecoderSpec) -> httpRequestDecoderSpec
						.maxHeaderSize(maxHttpHeaderSize)));
	}

}

@@ -677,16 +677,84 @@
 edded;%0A%0A
+import java.time.Duration;%0A%0Aimport io.netty.channel.ChannelOption;%0A%0A
 import o
@@ -813,16 +813,16 @@
 erties;%0A
-
 import o
@@ -1397,16 +1397,43 @@
 ntao Qu%0A
+ * @author Artsiom Yudovin%0A
  * @sinc
@@ -2357,24 +2357,207 @@
 aderSize));%0A
+%09%09propertyMapper.from(this.serverProperties::getConnectionTimeout).whenNonNull()%0A%09%09%09%09.asInt(Duration::toMillis)%0A%09%09%09%09.to((duration) -%3E customizeConnectionTimeOut(factory, duration));%0A%0A
 %09%7D%0A%0A%09private
@@ -3170,16 +3170,16 @@
 derSpec%0A
-
 %09%09%09%09%09%09.m
@@ -3217,10 +3217,369 @@
 ));%0A%09%7D%0A%0A
+%09private void customizeConnectionTimeOut(NettyReactiveWebServerFactory factory,%0A%09%09%09int duration) %7B%0A%09%09factory.addServerCustomizers((NettyServerCustomizer) (httpServer) -%3E httpServer%0A%09%09%09%09.tcpConfiguration((tcpServer) -%3E tcpServer%0A%09%09%09%09%09%09.bootstrap((serverBootstrap) -%3E serverBootstrap.childOption(%0A%09%09%09%09%09%09%09%09ChannelOption.CONNECT_TIMEOUT_MILLIS, duration))));%0A%09%7D%0A%0A
 %7D%0A

Support server.connection-timeout for Netty server