softwaremill / softwaremill/tapir

[BUG] RejectHandler doesn't works for Vertx web server

Open
#4,870 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Scala
Stars
1.5k
Forks
468
Avg merge
5h 37m
Merged PRs (30d)
34

Description

Tapir version: 1.11.49

Scala version: 2.13.1

Describe the bug

tapir reject handler doesn't works for Vertx web server

How to reproduce?

//> using scala 2.13.16
//> using dep org.typelevel::cats-effect:3.6.3
//> using dep com.softwaremill.sttp.tapir::tapir-vertx-server-cats:1.11.49
//> using dep com.softwaremill.sttp.tapir::tapir-http4s-server:1.11.49
//> using dep org.http4s::http4s-ember-server:0.23.32

import cats.effect._
import cats.effect.std.Dispatcher
import com.comcast.ip4s.Port
import io.vertx.core.Vertx
import io.vertx.ext.web.Router
import org.http4s.ember.server.EmberServerBuilder
import sttp.model.StatusCode
import sttp.tapir._
import sttp.tapir.server.ServerEndpoint
import sttp.tapir.server.http4s.{Http4sServerInterpreter, Http4sServerOptions}
import sttp.tapir.server.interceptor.CustomiseInterceptors
import sttp.tapir.server.interceptor.reject.DefaultRejectHandler
import sttp.tapir.server.model.ValuedEndpointOutput
import sttp.tapir.server.vertx.cats.VertxCatsServerInterpreter._
import sttp.tapir.server.vertx.cats.{VertxCatsServerInterpreter, VertxCatsServerOptions}

object App extends IOApp {
  private val responseEndpoint: ServerEndpoint[Any, IO] =
    endpoint
      .get
      .in("response")
      .in(query[String]("key"))
      .out(plainBody[String])
      .serverLogicSuccessPure(req => s"Response: $req")

  private val okEndpoint: ServerEndpoint[Any, IO] =
    endpoint
      .get
      .in("ok")
      .out(plainBody[String])
      .serverLogicSuccessPure(_ => "OK")

  private val endpoints: List[ServerEndpoint[Any, IO]] = List(responseEndpoint, okEndpoint)

  private def addNotFoundHandler[O]: CustomiseInterceptors[IO, O] => CustomiseInterceptors[IO, O] =
    _
      .rejectHandler(
        DefaultRejectHandler[IO](
          (sc: StatusCode, m: String) => ValuedEndpointOutput(statusCode.and(stringBody), (sc, m)),
          Some((StatusCode.Ok, "Custom Not Found Response"))
        )
      )

  def runAsVertx: IO[Nothing] =
    Dispatcher.parallel[IO].flatMap { dispatcher =>
      Resource
        .make(
          IO.delay {
            val vertx  = Vertx.vertx()
            val server = vertx.createHttpServer()
            val router = Router.router(vertx)

            val options =
              addNotFoundHandler(VertxCatsServerOptions.customiseInterceptors[IO](dispatcher))
                .options

            endpoints.foreach(VertxCatsServerInterpreter[IO](options).route(_)(router))
            server.requestHandler(router).listen(8080)
          }.flatMap(_.asF[IO])
        ) { server =>
          IO.delay(server.close).flatMap(_.asF[IO].void)
        }
    }
      .use(_ => IO.println("Server started on port 8080") >> IO.never)

  def runAsHttp4s: IO[Nothing] = {
    val options =
      addNotFoundHandler(Http4sServerOptions.customiseInterceptors[IO])
        .options

    EmberServerBuilder
      .default[IO]
      .withHttpApp(Http4sServerInterpreter[IO](options).toRoutes(endpoints).orNotFound)
      .withPort(Port.fromInt(8080).get)
      .build
      .use(_ => IO.println("Server started on port 8080") >> IO.never)
  }

  override def run(args: List[String]): IO[ExitCode] = runAsVertx // runAsHttp4s

}

First run with runAsVertx, second run with runAsHttp4s. Then call:

curl http://localhost:8080/something
  • With runAsVertx , I got 404 response (default vertx response, but I expects 200 with Custom Not Found Response):
    <html><body><h1>Resource not found</h1></body></html>
    
  • With runAsHttp4s , I got 200 response (as expected):
    Custom Not Found Response
    

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the VertxCatsServerInterpreter and VertxCatsServerOptions.customiseInterceptors usage in the reproduction, then compare it with Http4sServerInterpreter and Http4sServerOptions. Run the provided application with runAsVertx and curl /something, and verify that the Vertx server uses the configured reject handler and returns the expected 200 response.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.