Allow client configuration of hosts binding
This commit is contained in:
parent
41d06a2646
commit
aa60500fb0
|
@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
|
- [2020-06-14] Added new `client_hostname` selector to allow for custom address binding for Netty by [@lflare].
|
||||||
|
- [2020-06-14] Added new `ui_hostname` selector to allow for custom address binding for WebUiNetty by [@lflare].
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ class Netty(private val tls: ServerSettings.TlsCert, private val clientSettings:
|
||||||
.option(ChannelOption.SO_BACKLOG, 1000)
|
.option(ChannelOption.SO_BACKLOG, 1000)
|
||||||
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
||||||
|
|
||||||
val channel = bootstrap.bind(clientSettings.clientPort).sync().channel()
|
val channel = bootstrap.bind(InetSocketAddress(clientSettings.clientHostname, clientSettings.clientPort)).sync().channel()
|
||||||
address = channel.localAddress() as InetSocketAddress
|
address = channel.localAddress() as InetSocketAddress
|
||||||
closeFuture = channel.closeFuture()
|
closeFuture = channel.closeFuture()
|
||||||
}
|
}
|
||||||
|
|
62
src/main/kotlin/mdnet/base/WebUiNetty.kt
Executable file
62
src/main/kotlin/mdnet/base/WebUiNetty.kt
Executable file
|
@ -0,0 +1,62 @@
|
||||||
|
package mdnet.base
|
||||||
|
|
||||||
|
import io.netty.bootstrap.ServerBootstrap
|
||||||
|
import io.netty.channel.ChannelFactory
|
||||||
|
import io.netty.channel.ChannelFuture
|
||||||
|
import io.netty.channel.ChannelInitializer
|
||||||
|
import io.netty.channel.ChannelOption
|
||||||
|
import io.netty.channel.ServerChannel
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup
|
||||||
|
import io.netty.channel.socket.SocketChannel
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel
|
||||||
|
import io.netty.handler.codec.http.HttpObjectAggregator
|
||||||
|
import io.netty.handler.codec.http.HttpServerCodec
|
||||||
|
import io.netty.handler.codec.http.HttpServerKeepAliveHandler
|
||||||
|
import io.netty.handler.stream.ChunkedWriteHandler
|
||||||
|
import java.net.InetSocketAddress
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import org.http4k.core.HttpHandler
|
||||||
|
import org.http4k.server.Http4kChannelHandler
|
||||||
|
import org.http4k.server.Http4kServer
|
||||||
|
import org.http4k.server.ServerConfig
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
private val LOGGER = LoggerFactory.getLogger(WebUiNetty::class.java)
|
||||||
|
|
||||||
|
class WebUiNetty(private val hostname: String, private val port: Int) : ServerConfig {
|
||||||
|
override fun toServer(httpHandler: HttpHandler): Http4kServer = object : Http4kServer {
|
||||||
|
private val masterGroup = NioEventLoopGroup()
|
||||||
|
private val workerGroup = NioEventLoopGroup()
|
||||||
|
private lateinit var closeFuture: ChannelFuture
|
||||||
|
private lateinit var address: InetSocketAddress
|
||||||
|
|
||||||
|
override fun start(): Http4kServer = apply {
|
||||||
|
val bootstrap = ServerBootstrap()
|
||||||
|
bootstrap.group(masterGroup, workerGroup)
|
||||||
|
.channelFactory(ChannelFactory<ServerChannel> { NioServerSocketChannel() })
|
||||||
|
.childHandler(object : ChannelInitializer<SocketChannel>() {
|
||||||
|
public override fun initChannel(ch: SocketChannel) {
|
||||||
|
ch.pipeline().addLast("codec", HttpServerCodec())
|
||||||
|
ch.pipeline().addLast("keepAlive", HttpServerKeepAliveHandler())
|
||||||
|
ch.pipeline().addLast("aggregator", HttpObjectAggregator(Int.MAX_VALUE))
|
||||||
|
ch.pipeline().addLast("streamer", ChunkedWriteHandler())
|
||||||
|
ch.pipeline().addLast("handler", Http4kChannelHandler(httpHandler))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.option(ChannelOption.SO_BACKLOG, 1000)
|
||||||
|
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
||||||
|
|
||||||
|
val channel = bootstrap.bind(InetSocketAddress(hostname, port)).sync().channel()
|
||||||
|
address = channel.localAddress() as InetSocketAddress
|
||||||
|
closeFuture = channel.closeFuture()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun stop() = apply {
|
||||||
|
masterGroup.shutdownGracefully(5, 15, TimeUnit.SECONDS).sync()
|
||||||
|
workerGroup.shutdownGracefully(5, 15, TimeUnit.SECONDS).sync()
|
||||||
|
closeFuture.sync()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun port(): Int = address.port
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
/* ktlint-disable no-wildcard-imports */
|
/* ktlint-disable no-wildcard-imports */
|
||||||
package mdnet.base.server
|
package mdnet.base.server
|
||||||
|
|
||||||
|
import java.time.Instant
|
||||||
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
import mdnet.base.Statistics
|
import mdnet.base.Statistics
|
||||||
|
import mdnet.base.WebUiNetty
|
||||||
import mdnet.base.settings.WebSettings
|
import mdnet.base.settings.WebSettings
|
||||||
import org.http4k.core.Body
|
import org.http4k.core.Body
|
||||||
import org.http4k.core.Method
|
import org.http4k.core.Method
|
||||||
|
@ -9,16 +12,13 @@ import org.http4k.core.Response
|
||||||
import org.http4k.core.Status
|
import org.http4k.core.Status
|
||||||
import org.http4k.core.then
|
import org.http4k.core.then
|
||||||
import org.http4k.filter.ServerFilters
|
import org.http4k.filter.ServerFilters
|
||||||
|
import org.http4k.format.Gson.auto
|
||||||
import org.http4k.routing.ResourceLoader
|
import org.http4k.routing.ResourceLoader
|
||||||
import org.http4k.routing.bind
|
import org.http4k.routing.bind
|
||||||
import org.http4k.routing.routes
|
import org.http4k.routing.routes
|
||||||
import org.http4k.routing.singlePageApp
|
import org.http4k.routing.singlePageApp
|
||||||
import org.http4k.server.Http4kServer
|
import org.http4k.server.Http4kServer
|
||||||
import org.http4k.server.Netty
|
|
||||||
import org.http4k.server.asServer
|
import org.http4k.server.asServer
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
|
||||||
import org.http4k.format.Gson.auto
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
fun getUiServer(
|
fun getUiServer(
|
||||||
webSettings: WebSettings,
|
webSettings: WebSettings,
|
||||||
|
@ -43,5 +43,5 @@ fun getUiServer(
|
||||||
singlePageApp(ResourceLoader.Classpath("/webui"))
|
singlePageApp(ResourceLoader.Classpath("/webui"))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.asServer(Netty(webSettings.uiPort))
|
.asServer(WebUiNetty(webSettings.uiHostname, webSettings.uiPort))
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,14 @@ data class ClientSettings(
|
||||||
@field:SerializedName("max_cache_size_mib") val maxCacheSizeMib: Long = 20480,
|
@field:SerializedName("max_cache_size_mib") val maxCacheSizeMib: Long = 20480,
|
||||||
@field:SerializedName("max_bandwidth_mib_per_hour") val maxBandwidthMibPerHour: Long = 0,
|
@field:SerializedName("max_bandwidth_mib_per_hour") val maxBandwidthMibPerHour: Long = 0,
|
||||||
@field:SerializedName("max_burst_rate_kib_per_second") val maxBurstRateKibPerSecond: Long = 0,
|
@field:SerializedName("max_burst_rate_kib_per_second") val maxBurstRateKibPerSecond: Long = 0,
|
||||||
|
@field:SerializedName("client_hostname") val clientHostname: String = "0.0.0.0",
|
||||||
@field:SerializedName("client_port") val clientPort: Int = 443,
|
@field:SerializedName("client_port") val clientPort: Int = 443,
|
||||||
@field:Secret @field:SerializedName("client_secret") val clientSecret: String = "PASTE-YOUR-SECRET-HERE",
|
@field:Secret @field:SerializedName("client_secret") val clientSecret: String = "PASTE-YOUR-SECRET-HERE",
|
||||||
@field:SerializedName("threads") val threads: Int = 32,
|
@field:SerializedName("threads") val threads: Int = 32,
|
||||||
@field:SerializedName("web_settings") val webSettings: WebSettings? = null
|
@field:SerializedName("web_settings") val webSettings: WebSettings? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
data class WebSettings(@field:SerializedName("ui_port") val uiPort: Int = 8080)
|
data class WebSettings(
|
||||||
|
@field:SerializedName("ui_hostname") val uiHostname: String = "127.0.0.1",
|
||||||
|
@field:SerializedName("ui_port") val uiPort: Int = 8080
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue