All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.malliina.http4s.BasicService.scala Maven / Gradle / Ivy

package com.malliina.http4s

import cats.Applicative
import cats.data.NonEmptyList
import cats.effect.Sync
import cats.implicits.toFlatMapOps
import cats.syntax.all.toFunctorOps
import com.malliina.http.{CSRFToken, Errors}
import com.malliina.http4s.BasicService.noCache
import com.malliina.http4s.FeedbackSupport
import io.circe.syntax.EncoderOps
import org.http4s.CacheDirective.*
import org.http4s.circe.CirceInstances
import org.http4s.dsl.Http4sDsl
import org.http4s.headers.{Location, `Cache-Control`}
import org.http4s.server.middleware.CSRF
import org.http4s.{EntityEncoder, Request, Response, Uri, syntax}

import scala.concurrent.duration.FiniteDuration

object BasicService:
  val noCacheDirectives = NonEmptyList.of(`no-cache`(), `no-store`, `must-revalidate`)
  val noCache = `Cache-Control`(noCacheDirectives)

  def cached(duration: FiniteDuration) = `Cache-Control`(
    NonEmptyList.of(`max-age`(duration), `public`)
  )

trait BasicService[F[_]: Applicative]
  extends syntax.AllSyntax
  with Http4sDsl[F]
  with CirceInstances
  with FeedbackSupport[F]:
  def ok[A](a: A)(using EntityEncoder[F, A]) = Ok(a, noCache)

  def seeOther(uri: Uri): F[Response[F]] =
    SeeOther(Location(uri)).map(_.putHeaders(noCache))

  def notFound(req: Request[F]): F[Response[F]] =
    notFoundWith(s"Not found: '${req.uri}'.")

  def notFoundWith(message: String): F[Response[F]] =
    NotFound(Errors.single(message).asJson, noCache)

  def serverError(using Applicative[F]): F[Response[F]] =
    serverErrorWith("Server error.")

  def serverErrorWith(message: String)(using Applicative[F]): F[Response[F]] =
    InternalServerError(Errors.single(message).asJson, noCache)

  def badRequest[A](a: A)(using EntityEncoder[F, A]): F[Response[F]] =
    BadRequest(a, noCache)

trait CSRFSupport[F[_]: Sync]:
  this: BasicService[F] =>
  def csrf: CSRF[F, F]

  def csrfOk[A](content: CSRFToken => A)(using EntityEncoder[F, A]) =
    csrf
      .generateToken[F]
      .flatMap: token =>
        ok(content(CSRFUtils.toToken(token))).map: res =>
          csrf.embedInResponseCookie(res, token)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy