Giter Club home page Giter Club logo

http4s-stir's Introduction

http4s-stir

Welcome to http4s-stir, a library designed to bridge the gap between Pekko HTTP (Akka HTTP) and http4s. This README provides an overview of the library, its usage, project status, and more.

http4s-stir offers Pekko HTTP-style (Akka HTTP-style) DSL directives for http4s using cats-effect's IO as an effect system. About 85% of all directives have been ported. Some were omitted due to a lack of support in http4s, while others were modified to fit http4s' distinct architecture. For specifics, refer to the Missing section below.

Additionally, there's a compatibility layer, Http4sDirectives, for http4s-dsl routes.

http4s-stir also furnishes a test kit akin to Pekko's (Akka's).

How to use it

Installation

In SBT:

libraryDependencies += "pl.iterators" %% "http4s-stir" % "0.2"
libraryDependencies += "pl.iterators" %% "http4s-stir-testkit" % "0.2" % Test // if you need this

For scala-cli see this example.

Example

Here's an example in Scala 3 that you can run using scala-cli:

// Main.scala
//> using dep org.typelevel::cats-effect:3.5.1
//> using dep org.http4s::http4s-dsl:0.23.23
//> using dep org.http4s::http4s-ember-server:0.23.23
//> using dep org.http4s::http4s-circe:0.23.23
//> using dep io.circe::circe-core:0.14.5
//> using dep io.circe::circe-generic:0.14.5
//> using dep pl.iterators::http4s-stir:0.2

import org.http4s.Status
import org.http4s.ember.server.EmberServerBuilder
import org.http4s.circe.CirceEntityEncoder.*
import org.http4s.circe.CirceEntityDecoder.*
import io.circe.*
import io.circe.generic.semiauto.*
import cats.effect.IO
import pl.iterators.stir.server.*
import pl.iterators.stir.server.Directives.*
import cats.effect.IOApp

// example rewritten from https://pekko.apache.org/docs/pekko-http/current/introduction.html#using-apache-pekko-http
var orders: List[Item] = Nil

// domain model
final case class Item(name: String, id: Long)
final case class Order(items: List[Item])

// formats for unmarshalling and marshalling
given Codec[Item] = deriveCodec[Item]
given Codec[Order] = deriveCodec[Order]

// (fake) async database query api
def fetchItem(itemId: Long): IO[Option[Item]] = IO.delay {
  orders.find(o => o.id == itemId)
}
def saveOrder(order: Order): IO[List[Item]] = {
  orders = order.items ::: orders
  IO.delay(orders)
}

val route: Route =
  concat(
    get {
      pathPrefix("item" / LongNumber) { id =>
        // there might be no item for a given id
        val maybeItem: IO[Option[Item]] = fetchItem(id)

        onSuccess(maybeItem) {
          case Some(item) => complete(item)
          case None       => complete(Status.NotFound)
        }
      }
    },
    post {
      path("create-order") {
        entity(as[Order]) { order =>
          val saved: IO[List[Item]] = saveOrder(order)
          onSuccess(saved) {
            _ => // we are not interested in the result value `Done` but only in the fact that it was successful
              complete("order created")
          }
        }
      }
    }
  )

object Main extends IOApp.Simple {
  val run = EmberServerBuilder
    .default[IO]
    .withHttpApp(route.toHttpRoutes.orNotFound)
    .build
    .use(_ => IO.never)
}
// Main.test.scala
//> using test.dep org.specs2::specs2-core:4.19.2
//> using test.dep pl.iterators::http4s-stir-testkit:0.2

import org.http4s.Status
import org.http4s.circe.CirceEntityEncoder.*
import org.http4s.circe.CirceEntityDecoder.*
import cats.effect.IO
import cats.effect.unsafe.IORuntime
import org.specs2.mutable.Specification
import pl.iterators.stir.testkit.Specs2RouteTest

class MainRoutesSpec extends Specification with Specs2RouteTest {
    override implicit val runtime: IORuntime = IORuntime.global

    sequential
    "The routes" should {
        "create order" in {
            Post("/create-order", Order(List(Item("foo", 42)))) ~> route ~> check {
                responseAs[String] must contain("order created")
                orders.head must beEqualTo(Item("foo", 42))
            }
        }
        "retrieve an item if present" in {
            orders = List(Item("foo", 42))
            Get("/item/42") ~> route ~> check {
                responseAs[Item] must beEqualTo(Item("foo", 42))
            }
        }
        "return 404 if item is not present" in {
            orders = List.empty
            Get("/item/42") ~> route ~> check {
                status must beEqualTo(Status.NotFound)
            }
        }
    }
}

For a more comprehensive example showcasing additional directives see examples.

Why this library?

Here's why I embarked on this project:

  • After the license change for Akka, many contemplated transitioning to http4s and the Typelevel stack. I wanted to simplify this migration.
  • While I'm a fan of cats-effect, I find the http4s DSL verbose and clunky. Marrying Pekko HTTP (Akka HTTP) with cats-effect seemed inelegant, so http4s-stir could be the remedy.
  • I was curious about the internals of both Pekko HTTP and http4s and wanted to determine the feasibility of this project.
  • And, of course, a bit of playful provocation - see the next section.

What's with the name?

stir something up (pv)

to cause an unpleasant emotion or problem to begin or grow

There are folks who adore http4s but detest Pekko's (or Akka's) DSL. Conversely, there are those who champion Pekko's (or Akka's) but disdain http4s DSL. I aimed to ruffle feathers from both camps with a hybrid library.

Project status

This library is in preview, intended to collect initial feedback. Yet, I am dedicated to its ongoing maintenance and enhancement, especially as it undergoes real-world testing. Contributions are very welcome.

Missing

Certain directives from the original are either absent or have been modified:

  • Assuming and converting to/from strict entity
  • CacheConditionDirectives
  • CodingDirectives
  • directory listing in FileAndResourceDirectives
  • RangeDirectives
  • checkSameOrigin in HeaderDirectives
  • handling of multipart forms in FormFieldDirectives (but I don't like it anyway)
  • Some of how akka configures things
    • withSizeLimit
    • withoutSizeLimit
    • requestEntityEmpty
    • requestEntityPresent
    • rejectEmptyResponse
    • extractRequestTimeout
    • withRequestTimeoutResponse
  • AttributeDirectives
  • FramedEntityStreamingDirectives
  • WebSocketDirectives in large part
  • Testkit needed significant changes
    • Not async anymore
    • Chunks not supported
    • Request building incomplete (missing some minor header methods)
    • All websocket thingies
    • Some logic of transparent headers and default host info

Support

Encountering a Problem?

If you run into any issues, unexpected behavior, or errors, we encourage you to report them. Your feedback is invaluable and helps us improve.

Have a Feature Request?

If there's a feature you'd like to see, or if you have an idea that would make this project even better, we'd love to hear about it!

How to Report an Issue or Feature Request

Please create a new issue in our http4-stir. Ensure you provide as much detail as possible:

  1. For issues:
  • Describe the issue you're facing.
  • Steps to reproduce.
  • Expected behavior.
  • Actual behavior.
  1. For feature requests:
  • Describe the feature and why you believe it would be useful.
  • Any reference or example from other projects/tools, if applicable.

By providing detailed information, you'll help us address your concerns more efficiently.

Thank you for your contributions and for helping make this project better for everyone!

License

http4s-stir is under the Apache License, Version 2.0 ("the License"). You must comply with this License to use this software. A full license text is available in the repository.

Acknowledgements

http4s-stir incorporates significant portions of code adapted from Pekko HTTP, a fork of Akka HTTP.

http4s-stir's People

Contributors

luksow avatar pk044 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

http4s-stir's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.