softwaremill / tapir

Rapid development of self-documenting APIs
https://tapir.softwaremill.com
Apache License 2.0
1.36k stars 418 forks source link

Client interpreter: Endpoint to http4s's Request[F] #713

Closed adamw closed 3 years ago

adamw commented 4 years ago

From gitter:

hello folks, is there an easy way to turn an Endpoint into an org.http4s.Request[IO] that I can then run against an org.http4s.HttpApp[IO]? I need this for testing, but don't want to bind ports, I just want to create requests to just test that my error handling is all nice and proper :)
lightning95 commented 4 years ago

I'd like to implement this issue. Where should I look at first?

adamw commented 4 years ago

@lightning95 probably the sttp client interpreter will be a good starting point: https://github.com/softwaremill/tapir/tree/master/client/sttp-client/src/main/scala/sttp/tapir/client/sttp

together with the test suite: https://github.com/softwaremill/tapir/blob/master/client/tests/src/main/scala/sttp/tapir/client/tests/ClientTests.scala

MichalPawlicki commented 3 years ago

Hi! I'd like to work on the issue. From what I can see, Http4sBackend for the sttp client contains the logic to convert an sttp Request to an org.http4s.Request: https://github.com/softwaremill/sttp/blob/master/http4s-backend/src/main/scala/sttp/client3/http4s/Http4sBackend.scala#L38.

I think a good first step would be to extract this logic to a public class/method in the sttp.client3.http4s package. Then it could be used to implement a new tapir interpreter (e.g. Http4sRequestInterpreter) or just used directly by users, e.g.:

val helloEndpoint = endpoint.get.in("hello" / path[String]).out(stringBody)
val sttpRequest =
  SttpClientInterpreter.toRequest(helloEndpoint, None).apply("John")
val http4sRequest: org.http4s.Request[IO] =
  new SttpToHttp4sConverter[IO](blocker).sttpToHttp4sRequest(sttpRequest)

@adamw does it sound like a good idea?

adamw commented 3 years ago

@MichalPawlicki I think looking at inspiration from the Http4sBackend is definitely good idea, though I think I'd try to implement this directly, and avoid the sttp-client intermediate representation. It does give some code reuse, but it also introduces another dependency, so I'd think even if some code is duplicated, here it would be justified. What do you think?

MichalPawlicki commented 3 years ago

Right, this might be a better approach as the module could then depend just on http4s. The client test suite looks pretty comprehensive, so it should be possible to avoid obvious bugs in the new implementation. I'll try to find some time to draft a solution by next week.

Edit: I'm working on the feature on this branch: https://github.com/MichalPawlicki/tapir/tree/feature/http4s-client-interpreter. Still WIP.