Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding pekko-http support #305

Merged
merged 7 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import java.time.format.DateTimeFormatter
import java.time.{LocalDate, LocalTime}
import java.util.concurrent.TimeUnit

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.apache.pekko.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import org.apache.pekko.http.scaladsl.marshalling.ToResponseMarshallable
import org.apache.pekko.http.scaladsl.model.StatusCodes._
import org.apache.pekko.http.scaladsl.model.{ContentTypes, HttpEntity}
import org.apache.pekko.http.scaladsl.server.Directives._
import org.apache.pekko.http.scaladsl.testkit.ScalatestRouteTest
import org.openjdk.jmh.annotations._
import org.scalatest.{FunSpec, Matchers}
import pl.iterators.kebs.json.KebsSpray
Expand Down
47 changes: 43 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,21 @@ val akkaHttpTestkit = "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVer
def akkaHttpInExamples = {
val akkaHttpSprayJson = "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion
Seq(akkaStream.cross(CrossVersion.for3Use2_13),
akkaHttp.cross(CrossVersion.for3Use2_13),
akkaHttpSprayJson.cross(CrossVersion.for3Use2_13))
akkaHttp.cross(CrossVersion.for3Use2_13),
akkaHttpSprayJson.cross(CrossVersion.for3Use2_13))
}

val pekkoVersion = "1.0.1"
val pekkoHttpVersion = "1.0.0"
val pekkoHttpJsonV = "2.0.0"
val pekkoStream = "org.apache.pekko" %% "pekko-stream" % pekkoVersion
val pekkoStreamTestkit = "org.apache.pekko" %% "pekko-stream-testkit" % pekkoVersion
val pekkoHttp = "org.apache.pekko" %% "pekko-http" % pekkoHttpVersion
val pekkoHttpTestkit = "org.apache.pekko" %% "pekko-http-testkit" % pekkoHttpVersion

def pekkoHttpInExamples = {
val pekkoHttpSprayJson = "org.apache.pekko" %% "pekko-http-spray-json" % pekkoHttpVersion
Seq(pekkoStream, pekkoHttp, pekkoHttpSprayJson)
}

val http4sVersion = "0.23.23"
Expand All @@ -158,6 +171,8 @@ val http4sStirTestkit = "pl.iterators" %% "http4s-stir-testkit" % http4sStirVers

def akkaHttpInBenchmarks = akkaHttpInExamples :+ (akkaHttpTestkit).cross(CrossVersion.for3Use2_13)

def pekkoHttpInBenchmarks = pekkoHttpInExamples :+ pekkoHttpTestkit

lazy val commonSettings = baseSettings ++ Seq(
scalacOptions ++=
(if (scalaVersion.value.startsWith("3"))
Expand Down Expand Up @@ -214,6 +229,16 @@ lazy val akkaHttpSettings = commonSettings ++ Seq(
scalacOptions ++= paradiseFlag(scalaVersion.value)
)

lazy val pekkoHttpSettings = commonSettings ++ Seq(
libraryDependencies += pekkoHttp,
libraryDependencies += pekkoStream,
libraryDependencies += pekkoStreamTestkit % "test",
libraryDependencies += pekkoHttpTestkit % "test",
libraryDependencies += optionalEnumeratum,
libraryDependencies ++= paradisePlugin(scalaVersion.value),
scalacOptions ++= paradiseFlag(scalaVersion.value)
)

lazy val http4sSettings = commonSettings ++ Seq(
libraryDependencies += http4s,
libraryDependencies += optionalEnumeratum,
Expand Down Expand Up @@ -253,13 +278,14 @@ lazy val examplesSettings = commonSettings ++ Seq(
libraryDependencies += slickPg.cross(CrossVersion.for3Use2_13),
libraryDependencies += circeParser,
libraryDependencies ++= enumeratumInExamples,
libraryDependencies ++= akkaHttpInExamples,
libraryDependencies ++= pekkoHttpInExamples,
libraryDependencies ++= paradisePlugin(scalaVersion.value),
scalacOptions ++= paradiseFlag(scalaVersion.value)
)

lazy val benchmarkSettings = commonSettings ++ Seq(
libraryDependencies += scalaTest.value,
libraryDependencies ++= pekkoHttpInBenchmarks,
libraryDependencies += enumeratum,
libraryDependencies ++= akkaHttpInBenchmarks
)
Expand Down Expand Up @@ -389,6 +415,18 @@ lazy val akkaHttpSupport = project
crossScalaVersions := supportedScalaVersions
)

lazy val pekkoHttpSupport = project
.in(file("pekko-http"))
.dependsOn(core.jvm, instances % "test -> test", tagged.jvm % "test -> test", taggedMeta % "test -> test")
.settings(pekkoHttpSettings: _*)
.settings(publishSettings: _*)
.settings(
name := "pekko-http",
description := "Automatic generation of pekko-http deserializers for 1-element case classes",
moduleName := "kebs-pekko-http",
crossScalaVersions := supportedScalaVersions
)

lazy val http4sSupport = project
.in(file("http4s"))
.dependsOn(core.jvm, instances, opaque.jvm % "test -> test", tagged.jvm % "test -> test", taggedMeta % "test -> test")
Expand Down Expand Up @@ -491,7 +529,7 @@ lazy val taggedMeta = project

lazy val examples = project
.in(file("examples"))
.dependsOn(slickSupport, sprayJsonSupport, playJsonSupport, akkaHttpSupport, taggedMeta, circeSupport, instances)
.dependsOn(slickSupport, sprayJsonSupport, playJsonSupport, pekkoHttpSupport, taggedMeta, circeSupport, instances)
.settings(examplesSettings: _*)
.settings(noPublishSettings: _*)
.settings(disableScala(List("3")))
Expand Down Expand Up @@ -542,6 +580,7 @@ lazy val kebs = project
jsonschemaSupport,
scalacheckSupport,
akkaHttpSupport,
pekkoHttpSupport,
http4sSupport,
http4sStirSupport,
taggedMeta,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package pl.iterators.kebs_examples
import java.net.URL
import java.util.UUID

import akka.http.scaladsl.marshalling.{ToResponseMarshallable, _}
import akka.http.scaladsl.model.MediaTypes.`application/json`
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.{ContentType, ContentTypeRange, HttpEntity, MediaType}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.unmarshalling._
import akka.util.ByteString
import org.apache.pekko.http.scaladsl.marshalling.{ToResponseMarshallable, _}
import org.apache.pekko.http.scaladsl.model.MediaTypes.`application/json`
import org.apache.pekko.http.scaladsl.model.StatusCodes._
import org.apache.pekko.http.scaladsl.model.{ContentType, ContentTypeRange, HttpEntity, MediaType}
import org.apache.pekko.http.scaladsl.server.Directives._
import org.apache.pekko.http.scaladsl.server.Route
import org.apache.pekko.http.scaladsl.unmarshalling._
import org.apache.pekko.util.ByteString
import cats.data.NonEmptyList
import io.circe.jawn.parseByteBuffer
import io.circe._
Expand All @@ -27,7 +27,7 @@ object CirceExample {
}

object BeforeKebs {
object ThingProtocol extends CirceProtocol with CirceAkkaHttpSupport {
object ThingProtocol extends CirceProtocol with CircePekkoHttpSupport {
import io.circe._
import io.circe.generic.semiauto._
implicit val thingCreateRequestEncoder: Encoder[ThingCreateRequest] = deriveEncoder
Expand Down Expand Up @@ -62,7 +62,7 @@ object CirceExample {
}

object AfterKebs {
object ThingProtocol extends KebsCirce with CirceProtocol with CirceAkkaHttpSupport
object ThingProtocol extends KebsCirce with CirceProtocol with CircePekkoHttpSupport
import ThingProtocol._

class ThingRouter(thingsService: ThingsService)(implicit ec: ExecutionContext) {
Expand Down Expand Up @@ -105,7 +105,7 @@ object CirceExample {
}
}

trait CirceAkkaHttpSupport {
trait CircePekkoHttpSupport {

implicit def jsonUnmarshaller[T](implicit reader: Decoder[T]): FromEntityUnmarshaller[T] =
jsonUnmarshaller
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package pl.iterators.kebs_examples
import java.net.URL
import java.util.UUID

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Directives._
import org.apache.pekko.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import org.apache.pekko.http.scaladsl.marshalling.ToResponseMarshallable
import org.apache.pekko.http.scaladsl.model.StatusCodes._
import org.apache.pekko.http.scaladsl.server.Directives._
import enumeratum.{Enum, EnumEntry}
import pl.iterators.kebs.json.{KebsEnumFormats, KebsSpray}
import spray.json.{DefaultJsonProtocol, JsString, JsValue, JsonFormat, JsonReader, JsonWriter, deserializationError}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package pl.iterators.kebs_examples

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.unmarshalling.{FromStringUnmarshaller, Unmarshaller}
import akka.http.scaladsl.util.FastFuture
import org.apache.pekko.http.scaladsl.model.StatusCodes
import org.apache.pekko.http.scaladsl.server.Directives._
import org.apache.pekko.http.scaladsl.unmarshalling.{FromStringUnmarshaller, Unmarshaller}
import org.apache.pekko.http.scaladsl.util.FastFuture
import enumeratum.values._
import enumeratum.{Enum, EnumEntry}

object AkkaHttpUnmarshallers {
object PekkoHttpUnmarshallers {
sealed abstract class Column(val value: Int) extends IntEnumEntry
object Column extends IntEnum[Column] {
case object Name extends Column(1)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package pl.iterators.kebs_examples

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Directives._
import org.apache.pekko.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import org.apache.pekko.http.scaladsl.marshalling.ToResponseMarshallable
import org.apache.pekko.http.scaladsl.model.StatusCodes._
import org.apache.pekko.http.scaladsl.server.Directives._
import pl.iterators.kebs.instances.net.URIString
import pl.iterators.kebs.instances.util.UUIDString
import pl.iterators.kebs.json.KebsSpray
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@ import java.io.IOException
import java.time.format.DateTimeFormatter
import java.time.{LocalDate, LocalTime}

import akka.actor.ActorSystem
import akka.event.LoggingAdapter
import akka.http.scaladsl.Http
import akka.http.scaladsl.client.RequestBuilding
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.Uri.Query
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.Materializer
import org.apache.pekko.actor.ActorSystem
import org.apache.pekko.event.LoggingAdapter
import org.apache.pekko.http.scaladsl.Http
import org.apache.pekko.http.scaladsl.client.RequestBuilding
import org.apache.pekko.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import org.apache.pekko.http.scaladsl.model.StatusCodes._
import org.apache.pekko.http.scaladsl.model.Uri.Query
import org.apache.pekko.http.scaladsl.model._
import org.apache.pekko.http.scaladsl.model.headers.RawHeader
import org.apache.pekko.http.scaladsl.unmarshalling.Unmarshal
import org.apache.pekko.stream.Materializer
import pl.iterators.kebs.json.KebsSpray
import spray.json._

import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try

object SprayJsonWithAkkaHttpExample {
object SprayJsonWithPekkoHttpExample {
trait Protocol extends DefaultJsonProtocol with SprayJsonSupport with KebsSpray {
implicit val localTimeFormat = new JsonFormat[LocalTime] {
override def write(obj: LocalTime): JsValue = JsString(formatter.format(obj))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package pl.iterators.kebs

import pl.iterators.kebs.opaque.Opaque

import java.net.URI
import java.util.UUID
import pl.iterators.kebs.enums.ValueEnum

object Domain {
case class TestTaggedUri(uri: URI)
case class TestId(id: UUID)
case class Id(id: Long)
opaque type TestTaggedUri = URI
object TestTaggedUri extends Opaque[TestTaggedUri, URI]
opaque type TestId = UUID
object TestId extends Opaque[TestId, UUID]
opaque type Id = Long
object Id extends Opaque[Id, Long]
case class I(i: Int)
case class S(s: String)
case class P[A](a: A)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Http4sStirMatchersTests
with DayOfWeekInt
with InstantEpochMilliLong
with URIString {
implicit def runtime: cats.effect.unsafe.IORuntime = cats.effect.unsafe.IORuntime.global
implicit def runtime: cats.effect.unsafe.IORuntime = cats.effect.unsafe.IORuntime.global

test("No CaseClass1Rep implicits derived") {
import pl.iterators.kebs.macros.CaseClass1Rep
Expand Down Expand Up @@ -77,7 +77,7 @@ class Http4sStirMatchersTests
complete(id.toString)
}
Get("/test/ce7a7cf1-8c00-49a9-a963-9fd119dd0642") ~> testRoute ~> check {
responseAs[String] shouldEqual "TestTaggedUri(ce7a7cf1-8c00-49a9-a963-9fd119dd0642)"
responseAs[String] shouldEqual "ce7a7cf1-8c00-49a9-a963-9fd119dd0642"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Http4sStirUnmarshallersTests
with URIString
with YearMonthString
with DayOfWeekInt {
implicit def runtime: cats.effect.unsafe.IORuntime = cats.effect.unsafe.IORuntime.global
implicit def runtime: cats.effect.unsafe.IORuntime = cats.effect.unsafe.IORuntime.global

test("No CaseClass1Rep implicits derived") {
import pl.iterators.kebs.macros.CaseClass1Rep
Expand Down Expand Up @@ -167,7 +167,7 @@ class Http4sStirUnmarshallersTests
}

Get("/test_tagged?tagged=123456") ~> route ~> check {
responseAs[String] shouldBe "Id(123456)"
responseAs[String] shouldBe "123456"
}
}

Expand All @@ -180,7 +180,7 @@ class Http4sStirUnmarshallersTests
}

Get("/test_tagged?tagged=ce7a7cf1-8c00-49a9-a963-9fd119dd0642") ~> route ~> check {
responseAs[String] shouldBe "TestId(ce7a7cf1-8c00-49a9-a963-9fd119dd0642)"
responseAs[String] shouldBe "ce7a7cf1-8c00-49a9-a963-9fd119dd0642"
}
}

Expand All @@ -193,7 +193,7 @@ class Http4sStirUnmarshallersTests
}

Get("/test_tagged?tagged=www.test.pl") ~> route ~> check {
responseAs[String] shouldBe "TestTaggedUri(www.test.pl)"
responseAs[String] shouldBe "www.test.pl"
}
}
}
26 changes: 26 additions & 0 deletions pekko-http/src/main/scala-2/matchers/KebsMatchers.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package pl.iterators.kebs.matchers

import org.apache.pekko.http.scaladsl.server.{PathMatcher1, PathMatchers}
import enumeratum.{Enum, EnumEntry}
import pl.iterators.kebs.instances.InstanceConverter
import pl.iterators.kebs.macros.CaseClass1Rep

import scala.language.implicitConversions

trait KebsMatchers extends PathMatchers {

implicit class SegmentIsomorphism[U](segment: PathMatcher1[U]) {
def as[T](implicit rep: CaseClass1Rep[T, U]): PathMatcher1[T] = segment.map(rep.apply)
}

implicit class SegmentConversion[Source](segment: PathMatcher1[Source]) {
def to[Type](implicit ico: InstanceConverter[Type, Source]): PathMatcher1[Type] = segment.map(ico.decode)
}

object EnumSegment {
def as[T <: EnumEntry: Enum]: PathMatcher1[T] = {
val enumCompanion = implicitly[Enum[T]]
Segment.map(enumCompanion.withNameInsensitive)
}
}
}
Loading
Loading