Skip to content

Commit 412a6ef

Browse files
karadzhovPetar Karadzhov
andauthored
feat(http4s): ember client and server (#961)
Co-authored-by: Petar Karadzhov <[email protected]>
1 parent 64de91d commit 412a6ef

File tree

20 files changed

+459
-10
lines changed

20 files changed

+459
-10
lines changed

build.sbt

Lines changed: 102 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@ def pureconfig = libraryDependencies ++= {
1616
lazy val root = project
1717
.in(file("."))
1818
.aggregate(
19+
appMonix,
20+
appZio,
1921
bundleMonixHttp4sBlaze,
22+
bundleMonixHttp4sEmber,
2023
bundleZioHttp4sBlaze,
24+
bundleZioHttp4sEmber,
2125
cassandraDatastaxDriver,
2226
cassandraDatastaxDriverPureConfig,
2327
catsEffect,
@@ -33,10 +37,14 @@ lazy val root = project
3337
grpcServerPureConfig,
3438
http4sClientBlaze,
3539
http4sClientBlazePureConfig,
40+
http4sClientEmber,
41+
http4sClientEmberPureConfig,
3642
http4sClientMonixCatnap,
3743
http4sServer,
3844
http4sServerBlaze,
3945
http4sServerBlazePureConfig,
46+
http4sServerEmber,
47+
http4sServerEmberPureConfig,
4048
http4sServerMicrometer,
4149
jdkHttpClient,
4250
jdkHttpClientPureConfig,
@@ -67,45 +75,93 @@ lazy val root = project
6775
publish / skip := true
6876
)
6977

70-
lazy val bundleMonixHttp4sBlaze = project
71-
.in(file("bundle-monix-http4s-blaze"))
78+
lazy val appMonix = project
79+
.in(file("app-monix"))
7280
.dependsOn(
73-
http4sClientBlaze,
74-
http4sClientBlazePureConfig,
75-
http4sServerBlaze,
76-
http4sServerBlazePureConfig,
7781
http4sServerMicrometer,
7882
jvmMicrometer,
7983
jvmPureConfig,
8084
pureConfig
8185
)
8286
.settings(BuildSettings.common)
8387
.settings(
84-
name := "sst-bundle-monix-http4s-blaze",
88+
name := "sst-app-monix",
8589
libraryDependencies += Dependencies.monixEval
8690
)
8791

88-
lazy val bundleZioHttp4sBlaze = project
89-
.in(file("bundle-zio-http4s-blaze"))
92+
lazy val bundleMonixHttp4sBlaze = project
93+
.in(file("bundle-monix-http4s-blaze"))
9094
.dependsOn(
9195
http4sClientBlaze,
9296
http4sClientBlazePureConfig,
9397
http4sServerBlaze,
9498
http4sServerBlazePureConfig,
99+
appMonix
100+
)
101+
.settings(BuildSettings.common)
102+
.settings(
103+
name := "sst-bundle-monix-http4s-blaze"
104+
)
105+
106+
lazy val bundleMonixHttp4sEmber = project
107+
.in(file("bundle-monix-http4s-ember"))
108+
.dependsOn(
109+
http4sClientEmber,
110+
http4sClientEmberPureConfig,
111+
http4sServerEmber,
112+
http4sServerEmberPureConfig,
113+
appMonix
114+
)
115+
.settings(BuildSettings.common)
116+
.settings(
117+
name := "sst-bundle-monix-http4s-ember"
118+
)
119+
120+
lazy val appZio = project
121+
.in(file("app-zio"))
122+
.dependsOn(
95123
http4sServerMicrometer,
96124
jvmMicrometer,
97125
jvmPureConfig,
98126
pureConfig
99127
)
100128
.settings(BuildSettings.common)
101129
.settings(
102-
name := "sst-bundle-zio-http4s-blaze",
130+
name := "sst-app-zio",
103131
libraryDependencies ++= Seq(
104132
Dependencies.zio,
105133
Dependencies.zioInteropCats
106134
)
107135
)
108136

137+
lazy val bundleZioHttp4sBlaze = project
138+
.in(file("bundle-zio-http4s-blaze"))
139+
.dependsOn(
140+
http4sClientBlaze,
141+
http4sClientBlazePureConfig,
142+
http4sServerBlaze,
143+
http4sServerBlazePureConfig,
144+
appZio
145+
)
146+
.settings(BuildSettings.common)
147+
.settings(
148+
name := "sst-bundle-zio-http4s-blaze"
149+
)
150+
151+
lazy val bundleZioHttp4sEmber = project
152+
.in(file("bundle-zio-http4s-ember"))
153+
.dependsOn(
154+
http4sClientEmber,
155+
http4sClientEmberPureConfig,
156+
http4sServerEmber,
157+
http4sServerEmberPureConfig,
158+
appZio
159+
)
160+
.settings(BuildSettings.common)
161+
.settings(
162+
name := "sst-bundle-zio-http4s-ember"
163+
)
164+
109165
lazy val cassandraDatastaxDriver = project
110166
.in(file("cassandra-datastax-driver"))
111167
.settings(BuildSettings.common)
@@ -256,12 +312,26 @@ lazy val http4sClientBlaze = project
256312
libraryDependencies += Dependencies.http4sBlazeClient
257313
)
258314

315+
lazy val http4sClientEmber = project
316+
.in(file("http4s-client-ember"))
317+
.settings(BuildSettings.common)
318+
.settings(
319+
name := "sst-http4s-client-ember",
320+
libraryDependencies += Dependencies.http4sEmberClient
321+
)
322+
259323
lazy val http4sClientBlazePureConfig = project
260324
.in(file("http4s-client-blaze-pureconfig"))
261325
.dependsOn(http4sClientBlaze, jvmPureConfig)
262326
.settings(BuildSettings.common)
263327
.settings(name := "sst-http4s-client-blaze-pureconfig")
264328

329+
lazy val http4sClientEmberPureConfig = project
330+
.in(file("http4s-client-ember-pureconfig"))
331+
.dependsOn(http4sClientEmber, jvmPureConfig)
332+
.settings(BuildSettings.common)
333+
.settings(name := "sst-http4s-client-ember-pureconfig")
334+
265335
lazy val http4sClientMonixCatnap = project
266336
.in(file("http4s-client-monix-catnap"))
267337
.dependsOn(monixCatnapMicrometer)
@@ -297,6 +367,19 @@ lazy val http4sServerBlaze = project
297367
)
298368
)
299369

370+
lazy val http4sServerEmber = project
371+
.in(file("http4s-server-ember"))
372+
.dependsOn(http4sServer, http4sClientEmber % Test)
373+
.settings(BuildSettings.common)
374+
.settings(
375+
name := "sst-http4s-server-ember",
376+
libraryDependencies ++= Seq(
377+
Dependencies.http4sEmberServer,
378+
Dependencies.http4sDsl,
379+
Dependencies.slf4jApi
380+
)
381+
)
382+
300383
lazy val http4sServerBlazePureConfig = project
301384
.in(file("http4s-server-blaze-pureconfig"))
302385
.dependsOn(http4sServerBlaze)
@@ -306,6 +389,15 @@ lazy val http4sServerBlazePureConfig = project
306389
pureconfig
307390
)
308391

392+
lazy val http4sServerEmberPureConfig = project
393+
.in(file("http4s-server-ember-pureconfig"))
394+
.dependsOn(http4sServerEmber)
395+
.settings(BuildSettings.common)
396+
.settings(
397+
name := "sst-http4s-server-ember-pureconfig",
398+
pureconfig
399+
)
400+
309401
lazy val http4sServerMicrometer = project
310402
.in(file("http4s-server-micrometer"))
311403
.dependsOn(http4sServer)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.avast.sst.http4s.client.pureconfig.ember
2+
3+
import cats.syntax.either.*
4+
import com.avast.sst.http4s.client.Http4sEmberClientConfig
5+
import com.avast.sst.http4s.client.Http4sEmberClientConfig.SocketOptions
6+
import org.http4s.headers.`User-Agent`
7+
import pureconfig.ConfigReader
8+
import pureconfig.error.CannotConvert
9+
import pureconfig.generic.ProductHint
10+
import pureconfig.generic.semiauto.*
11+
12+
trait ConfigReaders {
13+
implicit protected def hint[T]: ProductHint[T] = ProductHint.default
14+
15+
implicit val http4sClientUserAgentReader: ConfigReader[`User-Agent`] = ConfigReader[String].emap { value =>
16+
`User-Agent`.parse(value).leftMap { parseFailure => CannotConvert(value, "User-Agent HTTP header", parseFailure.message) }
17+
}
18+
19+
implicit val http4sClientSocketOptionsReader: ConfigReader[SocketOptions] = deriveReader[SocketOptions]
20+
21+
implicit val http4sClientHttp4sEmberClientConfigReader: ConfigReader[Http4sEmberClientConfig] = deriveReader[Http4sEmberClientConfig]
22+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.avast.sst.http4s.client.pureconfig.ember
2+
3+
import pureconfig.ConfigFieldMapping
4+
import pureconfig.generic.ProductHint
5+
6+
/** Contains [[pureconfig.ConfigReader]] instances with default "kebab-case" naming convention. */
7+
object implicits extends ConfigReaders {
8+
9+
/** Contains [[pureconfig.ConfigReader]] instances with "kebab-case" naming convention.
10+
*
11+
* This is alias for the default `implicits._` import.
12+
*/
13+
object KebabCase extends ConfigReaders
14+
15+
/** Contains [[pureconfig.ConfigReader]] instances with "camelCase" naming convention. */
16+
object CamelCase extends ConfigReaders {
17+
implicit override protected def hint[T]: ProductHint[T] = ProductHint(ConfigFieldMapping(pureconfig.CamelCase, pureconfig.CamelCase))
18+
}
19+
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.avast.sst.http4s.client.pureconfig.ember
2+
3+
import cats.syntax.either.*
4+
import com.avast.sst.http4s.client.Http4sEmberClientConfig
5+
import org.http4s.headers.`User-Agent`
6+
import pureconfig.ConfigReader
7+
import pureconfig.error.CannotConvert
8+
import pureconfig.generic.derivation.default.*
9+
10+
trait ConfigReaders {
11+
12+
implicit val http4sClientUserAgentReader: ConfigReader[`User-Agent`] = ConfigReader[String].emap { value =>
13+
`User-Agent`.parse(value).leftMap { parseFailure => CannotConvert(value, "User-Agent HTTP header", parseFailure.message) }
14+
}
15+
16+
implicit val http4sClientHttp4sEmberClientConfigReader: ConfigReader[Http4sEmberClientConfig] =
17+
ConfigReader.derived
18+
19+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.avast.sst.http4s.client.pureconfig.ember
2+
3+
import pureconfig.ConfigFieldMapping
4+
5+
/** Contains [[pureconfig.ConfigReader]] instances with default "kebab-case" naming convention. */
6+
object implicits extends ConfigReaders {
7+
8+
/** Contains [[pureconfig.ConfigReader]] instances with "kebab-case" naming convention.
9+
*
10+
* This is alias for the default `implicits._` import.
11+
*/
12+
object KebabCase extends ConfigReaders
13+
14+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.avast.sst.http4s.client
2+
3+
import com.avast.sst.http4s.client.Http4sEmberClientConfig.{Defaults, SocketOptions}
4+
import org.http4s.ProductId
5+
import org.http4s.client.defaults
6+
import org.http4s.headers.`User-Agent`
7+
8+
import scala.concurrent.duration.{DurationInt, FiniteDuration}
9+
10+
final case class Http4sEmberClientConfig(
11+
maxTotal: Int = Defaults.maxTotal,
12+
maxPerKey: Int = Defaults.maxPerKey,
13+
idleTimeInPool: FiniteDuration = Defaults.idleTimeInPool,
14+
chunkSize: Int = Defaults.chunkSize,
15+
maxResponseHeaderSize: Int = Defaults.maxResponseHeaderSize,
16+
idleConnectionTime: FiniteDuration = Defaults.idleConnectionTime,
17+
timeout: FiniteDuration = Defaults.timeout,
18+
socketOptions: SocketOptions = SocketOptions(),
19+
userAgent: `User-Agent` = Defaults.userAgent,
20+
checkEndpointIdentification: Boolean = Defaults.checkEndpointIdentification
21+
)
22+
23+
object Http4sEmberClientConfig {
24+
final case class SocketOptions(
25+
reuseAddress: Boolean = true,
26+
sendBufferSize: Int = 256 * 1024,
27+
receiveBufferSize: Int = 256 * 1024,
28+
keepAlive: Boolean = false,
29+
noDelay: Boolean = false
30+
)
31+
32+
object Defaults {
33+
val maxTotal = 100
34+
val maxPerKey = 100
35+
val idleTimeInPool: FiniteDuration = 30.seconds
36+
val chunkSize: Int = 32 * 1024
37+
val maxResponseHeaderSize: Int = 4096
38+
val idleConnectionTime: FiniteDuration = defaults.RequestTimeout
39+
val timeout: FiniteDuration = defaults.RequestTimeout
40+
val userAgent: `User-Agent` = `User-Agent`(ProductId("http4s-ember", Some(org.http4s.BuildInfo.version)))
41+
val checkEndpointIdentification = true
42+
}
43+
}

0 commit comments

Comments
 (0)