org.http4s.HttpApp Scala Examples

The following examples show how to use org.http4s.HttpApp. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: CORSMiddleware.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.network.http.server.middleware

import cats.effect.ConcurrentEffect
import org.http4s.HttpApp
import org.http4s.server.middleware.{CORS, CORSConfig}

import scala.concurrent.duration._

object CORSMiddleware {
  val defaultConfig: CORSConfig = CORSConfig(
    anyOrigin = true,
    allowCredentials = true,
    maxAge = 1.day.toSeconds,
    anyMethod = true
  )

  private def corsConfig(allowedOriginsList: List[String]) =
    if (allowedOriginsList.isEmpty) {
      defaultConfig
    } else {
      defaultConfig.copy(anyOrigin = false, allowedOrigins = allowedOriginsList.toSet)
    }

  def apply[F[_]](http: HttpApp[F], allowedOrigins: List[String])(implicit F: ConcurrentEffect[F]): HttpApp[F] =
    CORS(http, corsConfig(allowedOrigins))
} 
Example 2
Source File: Http4sClientSpec.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.api.clients

import canoe.api._
import canoe.methods.Method
import canoe.models.InputFile
import cats.effect.IO
import io.circe.{Decoder, Encoder}
import org.http4s.HttpApp
import org.http4s.client.Client
import org.http4s.dsl.io._
import io.circe.Json
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import org.scalatest.freespec.AnyFreeSpec

class Http4sClientSpec extends AnyFreeSpec {
  private case class TestMethod(name: String = "test",
                                encoder: Encoder[String] = Encoder.encodeString,
                                decoder: Decoder[String] = Decoder.decodeString,
                                files: List[InputFile] = Nil)
      extends Method[String, String] {
    def attachments(request: String): List[(String, InputFile)] = files.map("" -> _)
  }

  private implicit val testMethod = TestMethod()

  private def response(s: String) = s"""{"ok" : true, "result" : "$s"}"""

  private implicit val logger = Slf4jLogger.getLogger[IO]

  "Client" - {
    "sends" - {
      "to correct Telegram endpoint" in {
        val client: Client[IO] = Client.fromHttpApp(HttpApp(r => Ok(response(r.uri.toString))))
        val tgClient = new Http4sTelegramClient("token", client)

        assert(tgClient.execute("any").unsafeRunSync() == s"https://api.telegram.org/bottoken/${testMethod.name}")
      }

      val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO] { r =>
        Ok(response(r.headers.get(org.http4s.headers.`Content-Type`).map(_.value.replace("\"", "''")).getOrElse("")))
      }))

      "json POST request if attachments contain file upload" in {
        assert(tgClient.execute("any").unsafeRunSync() == "application/json")
      }

      "multipart POST request if attachments contain file upload" in {
        val resp = tgClient.execute("any")(testMethod.copy(files = List(InputFile.Upload("", Array.emptyByteArray))))
        assert(resp.unsafeRunSync().startsWith("multipart/form-data"))
      }
    }

    "encodes/decodes" - {
      "request entity with method encoder" in {
        val tgClient = new Http4sTelegramClient(
          "",
          Client.fromHttpApp(HttpApp[IO](_.bodyAsText.compile.string.flatMap(s => Ok(response(s.replace("\"", "'"))))))
        )
        val res = tgClient.execute("")(testMethod.copy(encoder = Encoder.instance(_ => Json.fromString("encoded"))))

        assert(res.unsafeRunSync() == "'encoded'")
      }

      "result entity with method decoder" in {
        val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO](_ => Ok(response("")))))
        val res = tgClient.execute("")(testMethod.copy(decoder = Decoder.const("decoded")))

        assert(res.unsafeRunSync() == "decoded")
      }
    }

    "handles" - {
      "decode failure as ResponseDecodingError" in {
        val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO](_ => Ok("{}"))))

        assertThrows[ResponseDecodingError](tgClient.execute("any").unsafeRunSync())
      }

      "unsuccessful result as FailedMethod" in {
        val response = """{"ok" : false, "result" : "any"}"""
        val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO](_ => Ok(response))))

        assertThrows[FailedMethod[String, String]](tgClient.execute("any").unsafeRunSync())
      }
    }
  }
} 
Example 3
Source File: JoexServer.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.joex

import cats.effect._
import cats.effect.concurrent.Ref
import fs2.Stream
import fs2.concurrent.SignallingRef

import docspell.common.Pools
import docspell.joex.routes._

import org.http4s.HttpApp
import org.http4s.implicits._
import org.http4s.server.Router
import org.http4s.server.blaze.BlazeServerBuilder
import org.http4s.server.middleware.Logger

object JoexServer {

  private case class App[F[_]](
      httpApp: HttpApp[F],
      termSig: SignallingRef[F, Boolean],
      exitRef: Ref[F, ExitCode]
  )

  def stream[F[_]: ConcurrentEffect: ContextShift](
      cfg: Config,
      pools: Pools
  )(implicit T: Timer[F]): Stream[F, Nothing] = {

    val app = for {
      signal   <- Resource.liftF(SignallingRef[F, Boolean](false))
      exitCode <- Resource.liftF(Ref[F].of(ExitCode.Success))
      joexApp <-
        JoexAppImpl
          .create[F](cfg, signal, pools.connectEC, pools.httpClientEC, pools.blocker)

      httpApp = Router(
        "/api/info" -> InfoRoutes(),
        "/api/v1"   -> JoexRoutes(joexApp)
      ).orNotFound

      // With Middlewares in place
      finalHttpApp = Logger.httpApp(false, false)(httpApp)

    } yield App(finalHttpApp, signal, exitCode)

    Stream
      .resource(app)
      .flatMap(app =>
        BlazeServerBuilder[F](pools.restEC)
          .bindHttp(cfg.bind.port, cfg.bind.address)
          .withHttpApp(app.httpApp)
          .withoutBanner
          .serveWhile(app.termSig, app.exitRef)
      )

  }.drain
} 
Example 4
Source File: Tracer.scala    From http4s-tracer   with Apache License 2.0 5 votes vote down vote up
package dev.profunktor.tracer

import cats.Applicative
import cats.data.Kleisli
import cats.effect.Sync
import cats.syntax.all._
import org.http4s.syntax.StringSyntax
import org.http4s.{Header, HttpApp, Request}


object Tracer extends StringSyntax {

  private[tracer] val DefaultTraceIdHeader = "Trace-Id"

  final case class TraceId(value: String) extends AnyVal {
    override def toString = s"[Trace-Id] - [$value]"
  }

  def apply[F[_]](implicit ev: Tracer[F]): Tracer[F] = ev

  def create[F[_]](headerName: String = DefaultTraceIdHeader): Tracer[F] = new Tracer[F](headerName)

}

class Tracer[F[_]] private (headerName: String) {

  import Trace._, Tracer._

  def middleware(
      http: HttpApp[F],
      logRequest: Boolean = false,
      logResponse: Boolean = false
  )(implicit F: Sync[F], L: TracerLog[Trace[F, ?]]): HttpApp[F] =
    Kleisli { req =>
      val createId: F[(Request[F], TraceId)] =
        for {
          id <- GenUUID.make[F]
          tr <- F.delay(req.putHeaders(Header(headerName, id.value)))
        } yield (tr, id)

      for {
        mi       <- getTraceId(req)
        (tr, id) <- mi.fold(createId)(id => (req, id).pure[F])
        _        <- if (logRequest) L.info[Tracer[F]](s"$req").run(id) else F.unit
        rs       <- http(tr).map(_.putHeaders(Header(headerName, id.value)))
        _        <- if (logResponse) L.info[Tracer[F]](s"$rs").run(id) else F.unit
      } yield rs
    }

  def loggingMiddleware(
      http: HttpApp[F]
  )(implicit F: Sync[F], L: TracerLog[Trace[F, ?]]): HttpApp[F] =
    middleware(http, logRequest = true, logResponse = true)

  def getTraceId(request: Request[F])(implicit F: Applicative[F]): F[Option[TraceId]] =
    F.pure(request.headers.get(headerName.ci).map(h => TraceId(h.value)))

} 
Example 5
Source File: SparqlClientSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.clients

import cats.effect.IO
import cats.implicits._
import ch.epfl.bluebrain.nexus.cli.{AbstractCliSpec, Console}
import ch.epfl.bluebrain.nexus.cli.CliError.ClientError.{ClientStatusError, ServerStatusError}
import ch.epfl.bluebrain.nexus.cli.config.{AppConfig, EnvConfig}
import ch.epfl.bluebrain.nexus.cli.sse._
import ch.epfl.bluebrain.nexus.cli.utils.Http4sExtras
import izumi.distage.model.definition.ModuleDef
import org.http4s.circe.CirceEntityEncoder._
import org.http4s.client.Client
import org.http4s.dsl.io._
import org.http4s.headers.`Content-Type`
import org.http4s.{HttpApp, Response, Status, Uri}
import org.scalatest.OptionValues

class SparqlClientSpec extends AbstractCliSpec with Http4sExtras with OptionValues {

  private val sparqlResultsJson = jsonContentOf("/templates/sparql-results.json")
  private val sparqlResults     = sparqlResultsJson.as[SparqlResults].toOption.value
  private val query             = "SELECT * {?s ?p ?o} LIMIT 10"

  override def overrides: ModuleDef =
    new ModuleDef {
      include(defaultModules)
      make[Client[IO]].from { cfg: AppConfig =>
        val token   = cfg.env.token
        val ct      = `Content-Type`(SparqlClient.`application/sparql-query`)
        val view    = cfg.env.defaultSparqlView.renderString
        val httpApp = HttpApp[IO] {
          // success
          case req @ POST -> `v1` / "views" / OrgLabelVar(`orgLabel`) / ProjectLabelVar(
                `projectLabel`
              ) / `view` / "sparql" contentType `ct` optbearer `token` =>
            req.as[String].flatMap {
              case `query` => Response[IO](Status.Ok).withEntity(sparqlResultsJson).pure[IO]
              case _       => Response[IO](Status.BadRequest).pure[IO]
            }
          // unknown view id
          case req @ POST -> `v1` / "views" / OrgLabelVar(`orgLabel`) / ProjectLabelVar(
                `projectLabel`
              ) / (_: String) / "sparql" contentType `ct` optbearer `token` =>
            req.as[String].flatMap {
              case `query` => Response[IO](Status.NotFound).withEntity(notFoundJson).pure[IO]
              case _       => Response[IO](Status.BadRequest).pure[IO]
            }
          // unknown token
          case req @ POST -> `v1` / "views" / OrgLabelVar(`orgLabel`) / ProjectLabelVar(
                `projectLabel`
              ) / `view` / "sparql" contentType `ct` optbearer (_: Option[
                BearerToken
              ]) =>
            req.as[String].flatMap {
              case `query` => Response[IO](Status.Forbidden).withEntity(authFailedJson).pure[IO]
              case _       => Response[IO](Status.BadRequest).pure[IO]
            }
          // other - internal error
          case req @ POST -> "v1" /: (_: Path) contentType `ct` optbearer `token` =>
            req.as[String].flatMap {
              case `query` => Response[IO](Status.InternalServerError).withEntity(internalErrorJson).pure[IO]
              case _       => Response[IO](Status.BadRequest).pure[IO]
            }
        }
        Client.fromHttpApp(httpApp)
      }
    }

  "A SparqlClient" should {
    "return sparql results" in { (client: Client[IO], console: Console[IO], env: EnvConfig) =>
      val cl = SparqlClient(client, env, console)
      for {
        results <- cl.query(orgLabel, projectLabel, query)
        _        = results shouldEqual Right(sparqlResults)
      } yield ()
    }
    "return not found" in { (client: Client[IO], console: Console[IO], env: EnvConfig) =>
      val cl = SparqlClient(client, env, console)
      for {
        results <- cl.query(orgLabel, projectLabel, Uri.unsafeFromString(genString()), query)
        _        = results shouldEqual Left(ClientStatusError(Status.NotFound, notFoundJson.noSpaces))
      } yield ()
    }
    "return internal error" in { (client: Client[IO], console: Console[IO], env: EnvConfig) =>
      val cl = SparqlClient(client, env, console)
      for {
        results <- cl.query(orgLabel, ProjectLabel(genString()), Uri.unsafeFromString(genString()), query)
        _        = results shouldEqual Left(ServerStatusError(Status.InternalServerError, internalErrorJson.noSpaces))
      } yield ()
    }
    "return bad token" in { (client: Client[IO], console: Console[IO], env: EnvConfig) =>
      val cl = SparqlClient(client, env.copy(token = Some(BearerToken("bad"))), console)
      for {
        results <- cl.query(orgLabel, projectLabel, query)
        _        = results shouldEqual Left(ClientStatusError(Status.Forbidden, authFailedJson.noSpaces))
      } yield ()
    }

  }
} 
Example 6
Source File: ProjectClientSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.clients

import java.util.UUID

import cats.effect.IO
import cats.effect.concurrent.Ref
import cats.implicits._
import ch.epfl.bluebrain.nexus.cli.{AbstractCliSpec, Console}
import ch.epfl.bluebrain.nexus.cli.CliError.ClientError.ClientStatusError
import ch.epfl.bluebrain.nexus.cli.config.{AppConfig, EnvConfig}
import ch.epfl.bluebrain.nexus.cli.sse._
import ch.epfl.bluebrain.nexus.cli.utils.Http4sExtras
import izumi.distage.model.definition.ModuleDef
import org.http4s.circe.CirceEntityEncoder._
import org.http4s.client.Client
import org.http4s.dsl.io._
import org.http4s.{HttpApp, Response, Status}

class ProjectClientSpec extends AbstractCliSpec with Http4sExtras {

  private val projectJson = jsonContentOf("/templates/project.json", replacements)

  type Cache    = Map[(OrgUuid, ProjectUuid), (OrgLabel, ProjectLabel)]
  type CacheRef = Ref[IO, Cache]

  override def overrides: ModuleDef =
    new ModuleDef {
      include(defaultModules)
      make[Client[IO]].from { cfg: AppConfig =>
        val token   = cfg.env.token
        val httpApp = HttpApp[IO] {
          case GET -> `v1` / "projects" / OrgUuidVar(`orgUuid`) / ProjectUuidVar(`projectUuid`) optbearer `token` =>
            Response[IO](Status.Ok).withEntity(projectJson).pure[IO]
          case GET -> `v1` / "projects" / OrgUuidVar(_) / ProjectUuidVar(_) optbearer `token`                     =>
            Response[IO](Status.NotFound).withEntity(notFoundJson).pure[IO]
          case GET -> `v1` / "projects" / OrgUuidVar(_) / ProjectUuidVar(_) bearer (_: BearerToken)               =>
            Response[IO](Status.Forbidden).withEntity(authFailedJson).pure[IO]
        }
        Client.fromHttpApp(httpApp)
      }
      make[CacheRef].fromEffect {
        Ref.of[IO, Cache](Map.empty)
      }
    }

  "A ProjectClient" should {
    "resolve a known (orgUuid, projUuid) pair" in {
      (client: Client[IO], console: Console[IO], cache: CacheRef, env: EnvConfig) =>
        val cl = ProjectClient[IO](client, env, cache, console)
        for {
          labels <- cl.labels(orgUuid, projectUuid)
          _       = labels shouldEqual Right((orgLabel, projectLabel))
        } yield ()
    }
    "resolve from cache a known (orgUuid, projUuid) pair" in {
      (client: Client[IO], console: Console[IO], cache: CacheRef, env: EnvConfig) =>
        val errClient = Client.fromHttpApp(HttpApp[IO] { case GET -> Root => IO.pure(Response[IO](Status.NotFound)) })
        for {
          _      <- ProjectClient[IO](client, env, cache, console).labels(orgUuid, projectUuid)
          labels <- ProjectClient[IO](errClient, env, cache, console).labels(orgUuid, projectUuid)
          _       = labels shouldEqual Right((orgLabel, projectLabel))
        } yield ()
    }
    "fail to resolve an unknown (orgUuid, projUuid) pair" in {
      (client: Client[IO], console: Console[IO], cache: CacheRef, env: EnvConfig) =>
        val cl = ProjectClient[IO](client, env, cache, console)
        for {
          labels <- cl.labels(OrgUuid(UUID.randomUUID()), projectUuid)
          _       = labels shouldEqual Left(ClientStatusError(Status.NotFound, notFoundJson.noSpaces))
        } yield ()
    }
    "fail to resolve a known (orgUuid, projUuid) pair with bad credentials" in {
      (client: Client[IO], console: Console[IO], cache: CacheRef, env: EnvConfig) =>
        val cl = ProjectClient[IO](client, env.copy(token = Some(BearerToken("bad"))), cache, console)
        for {
          labels <- cl.labels(orgUuid, projectUuid)
          _       = labels shouldEqual Left(ClientStatusError(Status.Forbidden, authFailedJson.noSpaces))
        } yield ()
    }
  }
} 
Example 7
Source File: SagaEndpoint.scala    From zio-saga   with MIT License 5 votes vote down vote up
package com.vladkopanev.zio.saga.example.endpoint

import com.vladkopanev.zio.saga.example.{ OrderSagaCoordinator, TaskC }
import com.vladkopanev.zio.saga.example.model.OrderInfo
import org.http4s.circe._
import org.http4s.dsl.Http4sDsl
import org.http4s.implicits._
import org.http4s.{ HttpApp, HttpRoutes }
import zio.interop.catz._

final class SagaEndpoint(orderSagaCoordinator: OrderSagaCoordinator) extends Http4sDsl[TaskC] {

  private implicit val decoder = jsonOf[TaskC, OrderInfo]

  val service: HttpApp[TaskC] = HttpRoutes
    .of[TaskC] {
      case req @ POST -> Root / "saga" / "finishOrder" =>
        for {
          OrderInfo(userId, orderId, money, bonuses) <- req.as[OrderInfo]
          resp <- orderSagaCoordinator
                   .runSaga(userId, orderId, money, bonuses, None)
                   .foldM(fail => InternalServerError(fail.getMessage), _ => Ok("Saga submitted"))
        } yield resp
    }
    .orNotFound
} 
Example 8
Source File: LoginTest.scala    From scala-pet-store   with Apache License 2.0 5 votes vote down vote up
package io.github.pauljamescleary.petstore
package infrastructure.endpoint

import cats.data.Kleisli
import cats.effect.IO
import domain.authentication.{LoginRequest, SignupRequest}
import domain.users.{Role, User}
import org.http4s.circe.{jsonEncoderOf, jsonOf}
import org.http4s.client.dsl.Http4sClientDsl
import org.http4s.{EntityDecoder, EntityEncoder, HttpApp, Request, Response}
import org.http4s.implicits._
import org.http4s.headers.Authorization
import io.circe.generic.auto._
import org.http4s.dsl.Http4sDsl

trait LoginTest extends Http4sClientDsl[IO] with Http4sDsl[IO] {
  implicit val userEnc: EntityEncoder[IO, User] = jsonEncoderOf
  implicit val userDec: EntityDecoder[IO, User] = jsonOf

  implicit val signUpRequestEnc: EntityEncoder[IO, SignupRequest] = jsonEncoderOf
  implicit val signUpRequestDec: EntityDecoder[IO, SignupRequest] = jsonOf

  implicit val loginRequestEnc: EntityEncoder[IO, LoginRequest] = jsonEncoderOf
  implicit val loginRequestDec: EntityDecoder[IO, LoginRequest] = jsonOf

  def signUpAndLogIn(
      userSignUp: SignupRequest,
      userEndpoint: HttpApp[IO],
  ): IO[(User, Option[Authorization])] =
    for {
      signUpRq <- POST(userSignUp, uri"/users")
      signUpResp <- userEndpoint.run(signUpRq)
      user <- signUpResp.as[User]
      loginBody = LoginRequest(userSignUp.userName, userSignUp.password)
      loginRq <- POST(loginBody, uri"/users/login")
      loginResp <- userEndpoint.run(loginRq)
    } yield {
      user -> loginResp.headers.get(Authorization)
    }

  def signUpAndLogInAsAdmin(
      userSignUp: SignupRequest,
      userEndpoint: Kleisli[IO, Request[IO], Response[IO]],
  ): IO[(User, Option[Authorization])] =
    signUpAndLogIn(userSignUp.copy(role = Role.Admin), userEndpoint)

  def signUpAndLogInAsCustomer(
      userSignUp: SignupRequest,
      userEndpoint: Kleisli[IO, Request[IO], Response[IO]],
  ): IO[(User, Option[Authorization])] =
    signUpAndLogIn(userSignUp.copy(role = Role.Customer), userEndpoint)
} 
Example 9
Source File: BidderHttpAppBuilder.scala    From scala-openrtb   with Apache License 2.0 5 votes vote down vote up
package com.powerspace.openrtb.examples.rtb.http4s.bidder

import com.google.openrtb.BidRequest
import com.powerspace.openrtb.examples.rtb.http4s.common.ExampleSerdeModule
import io.circe.Decoder
import monix.eval.Task
import org.http4s.dsl.Http4sDsl
import org.http4s.{EntityDecoder, HttpApp}

object BidderHttpAppBuilder {

  private val bidder = new Bidder[Task]
  private val dsl = Http4sDsl[Task]
  private val serdeModule = ExampleSerdeModule

  
  private def handleBid(bidRequest: BidRequest) = {
    import dsl._
    import org.http4s.circe._

    bidder
      .bidOn(bidRequest)
      .flatMap {
        case Some(bidResponse) =>
          // encode the bidResponse to a json object as part of the http response body
          Ok(serdeModule.bidResponseEncoder(bidResponse))
        case None =>
          Ok()
      }
  }
} 
Example 10
Source File: Main.scala    From http4s-poc-api   with MIT License 5 votes vote down vote up
package server

import java.util.concurrent.Executors

import com.github.ghik.silencer.silent
import external.{TeamOneHttpApi, TeamThreeCacheApi, TeamTwoHttpApi}
import io.circe.generic.auto._
import log.effect.zio.ZioLogWriter._
import model.DomainModel._
import org.http4s.circe._
import org.http4s.server.Router
import org.http4s.server.blaze.BlazeServerBuilder
import org.http4s.syntax.kleisli._
import org.http4s.{EntityDecoder, EntityEncoder, HttpApp}
import service.PriceService
import zio.interop.catz._
import zio.interop.catz.implicits._
import zio.{ExitCode, RIO, Task, ZEnv, ZIO}

import scala.concurrent.ExecutionContext
import model.DomainModelCodecs._

@silent
object Main extends zio.interop.catz.CatsApp with Pools with Codecs {
  private[this] val priceService: RIO[String, PriceService[Task]] =
    log4sFromName map { log =>
      PriceService[Task](
        TeamThreeCacheApi.productCache,
        TeamOneHttpApi(),
        TeamTwoHttpApi(),
        log
      )
    }

  private[this] val httpApp: RIO[PriceService[Task], HttpApp[Task]] =
    ZIO.access { ps =>
      Router(
        "/pricing-api/prices"       -> PriceRoutes[Task].make(ps),
        "/pricing-api/health-check" -> HealthCheckRoutes[Task].make(ps.logger)
      ).orNotFound
    }

  private[this] val runningServer: RIO[HttpApp[Task], Unit] =
    ZIO.accessM { app =>
      BlazeServerBuilder[Task](serverPool)
        .bindHttp(17171, "0.0.0.0")
        .withConnectorPoolSize(connectorPoolSize)
        .enableHttp2(true)
        .withHttpApp(app)
        .serve
        .compile
        .drain
    }

  private[this] val serviceRuntime: RIO[String, Unit] =
    priceService >>> httpApp >>> runningServer

  def run(args: List[String]): ZIO[ZEnv, Nothing, ExitCode] =
    serviceRuntime.fold(_ => ExitCode.failure, _ => ExitCode.success) provide "App log"
}

sealed trait Pools {

  protected val connectorPoolSize = Runtime.getRuntime.availableProcessors() * 2
  protected val mainThreadNumber  = Runtime.getRuntime.availableProcessors() + 1

  protected val serverPool = ExecutionContext.fromExecutor(
    Executors.newWorkStealingPool(mainThreadNumber)
  )
}

sealed trait Codecs {
  implicit val priceRequestPayloadDecoder: EntityDecoder[Task, PricesRequestPayload] =
    jsonOf[Task, PricesRequestPayload]

  implicit val priceResponsePayloadEncoder: EntityEncoder[Task, List[Price]] =
    jsonEncoderOf[Task, List[Price]]

  implicit val healthCheckResponsePayloadEncoder: EntityEncoder[Task, ServiceSignature] =
    jsonEncoderOf[Task, ServiceSignature]
} 
Example 11
Source File: Http4sRoutingModule.scala    From scala-server-toolkit   with MIT License 5 votes vote down vote up
package com.avast.sst.example.module

import cats.implicits._
import com.avast.sst.example.service.RandomService
import com.avast.sst.http4s.server.Http4sRouting
import com.avast.sst.http4s.server.micrometer.MicrometerHttp4sServerMetricsModule
import org.http4s.client.Client
import org.http4s.dsl.Http4sDsl
import org.http4s.{HttpApp, HttpRoutes}
import zio.Task
import zio.interop.catz._

class Http4sRoutingModule(
    randomService: RandomService,
    client: Client[Task],
    serverMetricsModule: MicrometerHttp4sServerMetricsModule[Task]
) extends Http4sDsl[Task] {

  import serverMetricsModule._

  private val helloWorldRoute = routeMetrics.wrap("hello")(Ok("Hello World!"))

  private val routes = HttpRoutes.of[Task] {
    case GET -> Root / "hello"           => helloWorldRoute
    case GET -> Root / "random"          => randomService.randomNumber.map(_.show).flatMap(Ok(_))
    case GET -> Root / "circuit-breaker" => client.expect[String]("https://httpbin.org/status/500").flatMap(Ok(_))
  }

  val router: HttpApp[Task] = Http4sRouting.make {
    serverMetrics {
      routes
    }
  }

} 
Example 12
Source File: Http4sBlazeServerModule.scala    From scala-server-toolkit   with MIT License 5 votes vote down vote up
package com.avast.sst.http4s.server

import java.net.{InetSocketAddress, StandardSocketOptions}

import cats.effect.{ConcurrentEffect, Resource, Timer}
import org.http4s.HttpApp
import org.http4s.server.Server
import org.http4s.server.blaze.BlazeServerBuilder

import scala.concurrent.ExecutionContext
import scala.concurrent.duration.Duration

object Http4sBlazeServerModule {

  
  def make[F[_]: ConcurrentEffect: Timer](
      config: Http4sBlazeServerConfig,
      httpApp: HttpApp[F],
      executionContext: ExecutionContext
  ): Resource[F, Server[F]] = {
    for {
      inetSocketAddress <- Resource.liftF(
        ConcurrentEffect[F].delay(
          InetSocketAddress.createUnresolved(config.listenAddress, config.listenPort)
        )
      )
      server <-
        BlazeServerBuilder[F](executionContext)
          .bindSocketAddress(inetSocketAddress)
          .withHttpApp(httpApp)
          .withoutBanner
          .withNio2(config.nio2Enabled)
          .withWebSockets(config.webSocketsEnabled)
          .enableHttp2(config.http2Enabled)
          .withResponseHeaderTimeout(Duration.fromNanos(config.responseHeaderTimeout.toNanos))
          .withIdleTimeout(Duration.fromNanos(config.idleTimeout.toNanos))
          .withBufferSize(config.bufferSize)
          .withMaxRequestLineLength(config.maxRequestLineLength)
          .withMaxHeadersLength(config.maxHeadersLength)
          .withChunkBufferMaxSize(config.chunkBufferMaxSize)
          .withConnectorPoolSize(config.connectorPoolSize)
          .withChannelOption[java.lang.Boolean](StandardSocketOptions.TCP_NODELAY, config.socketOptions.tcpNoDelay)
          .resource
    } yield server
  }
}