marcinzh / enterprise   0.2.0

MIT License GitHub

Serve HTTP using Algebraic Effects and Handlers

Scala versions: 3.x

Maven Central javadoc

Enterprise

Minimalist library for creating HTTP services, using algebraic effects and handlers.

  • βš—οΈ πŸ”¬ πŸ§ͺ Β  𝑷𝑹𝑢𝑻𝑢𝑻𝒀𝑷𝑬 Β  🚧 WIP 🚧
  • Uses Scala 3.
  • Uses Turbolift as effect system.
  • Adapts parts of design of preexisting purely-functional HTTP libraries (Http4s, ZIO-Http) for the new effect system.

Design

Services are defined as values of type:

type MyHttpService = Response !! (Request.Fx & IO)

Which should be read as: "Computation, that returns Response and requests 2 effects: Request.Fx and IO".

Request.Fx is an instance of Turbolift's Reader effect, predefined in Enterprise.

Services can also request other effects than these 2. However, they must be handled (eliminated) by the user, before submitting the service to server. Multiple handlers can be chained, using Turbolift's &&&! operator.

Examples of such optional effects, predefined in Enterprise, are:

  • ErrorResponse.Fx- An instance of Turbolift's Error effect. Allows interruption of processing of the request, returning given Response value.
  • Router.Fx - An instance of Turbolift's Choice effect. Allows defining routes by partial functions. Composition can be done with Turbolift's ++! operator (similar to <|> of Alternative).

With future version of Turbolift, service will be able to use any number of effects that are handled outside the server scope.

Example

Run the server with scala-cli:

//> using scala "3.3.1"
//> using dep "io.github.marcinzh::enterprise-core:0.2.0"
import turbolift.!!
import turbolift.Extensions._
import enterprise.{Response, Router}
import enterprise.server.{Server, Config}
import enterprise.DSL._

@main def main =
  Server.serve:
    Router:
      case GET / "sarcastic" / text =>
        val text2 = text.zipWithIndex.map((c, i) => if i % 2 == 0 then c.toLower else c.toUpper).mkString
        Response.text(text2).pure_!!
    .handleWith:
      Router.handler
  .handleWith:
    Server.undertow &&&!
    Config.localhost(9000).toHandler
  .unsafeRunST

Query the server with httpie:

http GET http://localhost:9000/sarcastic/assimilate

See examples folder for more.