Skip to content

Commit

Permalink
feat(blaze-client): Socket options (#985)
Browse files Browse the repository at this point in the history
Co-authored-by: Petar Karadzhov <[email protected]>
  • Loading branch information
karadzhov and Petar Karadzhov authored Sep 20, 2022
1 parent 705dc52 commit 1a63572
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.avast.sst.http4s.client.pureconfig

import cats.syntax.either._
import cats.syntax.either.*
import com.avast.sst.http4s.client.Http4sBlazeClientConfig
import com.avast.sst.http4s.client.Http4sBlazeClientConfig.SocketOptions
import org.http4s.blaze.client.ParserMode
import org.http4s.headers.`User-Agent`
import pureconfig.ConfigReader
import pureconfig.error.CannotConvert
import pureconfig.generic.ProductHint
import pureconfig.generic.semiauto._
import pureconfig.generic.semiauto.*

trait ConfigReaders {

Expand All @@ -17,6 +18,8 @@ trait ConfigReaders {
`User-Agent`.parse(value).leftMap { parseFailure => CannotConvert(value, "User-Agent HTTP header", parseFailure.message) }
}

implicit val http4sClientSocketOptionsReader: ConfigReader[SocketOptions] = deriveReader[SocketOptions]

implicit val http4sClientParserModeReader: ConfigReader[ParserMode] = deriveEnumerationReader

implicit val http4sClientHttp4sBlazeClientConfigReader: ConfigReader[Http4sBlazeClientConfig] = deriveReader[Http4sBlazeClientConfig]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.avast.sst.http4s.client.pureconfig

import cats.syntax.either.*
import com.avast.sst.http4s.client.Http4sBlazeClientConfig
import com.avast.sst.http4s.client.Http4sBlazeClientConfig.SocketOptions
import org.http4s.blaze.client.ParserMode
import org.http4s.headers.`User-Agent`
import pureconfig.ConfigReader
Expand All @@ -14,6 +15,8 @@ trait ConfigReaders {
`User-Agent`.parse(value).leftMap { parseFailure => CannotConvert(value, "User-Agent HTTP header", parseFailure.message) }
}

implicit val http4sClientSocketOptionsReader: ConfigReader[SocketOptions] = ConfigReader.derived

implicit val http4sClientParserModeReader: ConfigReader[ParserMode] = ConfigReader.derived

implicit val http4sClientHttp4sBlazeClientConfigReader: ConfigReader[Http4sBlazeClientConfig] =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.avast.sst.http4s.client

import com.avast.sst.http4s.client.Http4sBlazeClientConfig.SocketOptions
import org.http4s.blaze.client.ParserMode
import org.http4s.client.defaults
import org.http4s.headers.`User-Agent`
Expand All @@ -23,5 +24,16 @@ final case class Http4sBlazeClientConfig(
maxChunkSize: Int = Int.MaxValue,
chunkBufferMaxSize: Int = 1024 * 1024,
parserMode: ParserMode = ParserMode.Strict,
bufferSize: Int = 8192
bufferSize: Int = 8192,
socketOptions: Option[SocketOptions] = None
)

object Http4sBlazeClientConfig {
final case class SocketOptions(
reuseAddress: Boolean = true,
sendBufferSize: Int = 256 * 1024,
receiveBufferSize: Int = 256 * 1024,
keepAlive: Boolean = false,
noDelay: Boolean = false
)
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.avast.sst.http4s.client

import cats.effect.{ConcurrentEffect, Resource}
import com.avast.sst.http4s.client.Http4sBlazeClientConfig.SocketOptions
import org.http4s.blaze.channel.{ChannelOptions, OptionValue}
import org.http4s.blaze.client.BlazeClientBuilder
import org.http4s.client.Client

import java.net.StandardSocketOptions
import javax.net.ssl.SSLContext
import scala.concurrent.ExecutionContext
object Http4sBlazeClientModule {
Expand Down Expand Up @@ -35,7 +38,20 @@ object Http4sBlazeClientModule {
.withParserMode(config.parserMode)
.withBufferSize(config.bufferSize)

sslContext.map(builder.withSslContext).getOrElse(builder).resource
val builderWithMaybeSocketOptions = config.socketOptions.fold(builder)(s => builder.withChannelOptions(channelOptions(s)))
val builderWithMaybeTLS = sslContext.fold(builderWithMaybeSocketOptions)(builderWithMaybeSocketOptions.withSslContext)

builderWithMaybeTLS.resource
}

def channelOptions(socketOptions: SocketOptions): ChannelOptions =
ChannelOptions(
Vector(
OptionValue[java.lang.Boolean](StandardSocketOptions.SO_REUSEADDR, socketOptions.reuseAddress),
OptionValue[java.lang.Integer](StandardSocketOptions.SO_SNDBUF, socketOptions.sendBufferSize),
OptionValue[java.lang.Integer](StandardSocketOptions.SO_RCVBUF, socketOptions.receiveBufferSize),
OptionValue[java.lang.Boolean](StandardSocketOptions.SO_KEEPALIVE, socketOptions.keepAlive),
OptionValue[java.lang.Boolean](StandardSocketOptions.TCP_NODELAY, socketOptions.noDelay)
)
)
}

0 comments on commit 1a63572

Please sign in to comment.