Where communities thrive

  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
Repo info
  • May 25 07:32
    scala-steward opened #687
  • May 24 19:41
    scala-steward closed #680
  • May 24 19:41
    scala-steward commented #680
  • May 24 19:41
    scala-steward opened #686
  • May 20 07:37
    scala-steward opened #685
  • May 13 22:40
    scala-steward closed #683
  • May 13 22:40
    scala-steward commented #683
  • May 13 22:40
    scala-steward opened #684
  • Apr 27 11:50
    hughlunt commented #492
  • Apr 21 08:50
    scala-steward closed #681
  • Apr 21 08:50
    scala-steward commented #681
  • Apr 21 08:50
    scala-steward opened #683
  • Apr 07 14:52
    scala-steward opened #682
  • Apr 07 03:14
    scala-steward closed #677
  • Apr 07 03:14
    scala-steward commented #677
  • Apr 07 03:14
    scala-steward opened #681
  • Apr 05 02:46
    scala-steward closed #675
  • Apr 05 02:46
    scala-steward commented #675
  • Apr 05 02:46
    scala-steward opened #680
  • Apr 04 16:35
    scala-steward closed #660
Kingsley Hendrickse
In my case it's quite common to have lists of int or long or string in the payload of POST and PUT requests
Gavin Bisesi
I think it does get specialized, maybe? I'd open a ticket
Kingsley Hendrickse
many of the endpoints were designed way before I started looking at Rho and how to auto generate the docs
yeah - I'm not sure how frequently things get picked up here - maybe I should take a look and send a pull request
thanks for your help :)
Yasuhide Hoshiko
Hi, is there a way to add descriptions to request body or headers? I can't find any documentation nor examples..
Kingsley Hendrickse
@Daenyth do you know if it's possible to write the generated yaml / json to a file as well as serving it? Currently the served yaml inherits the authorisation so can't be accessed unless authorised but we want to maybe write it to file and serve it from a non authed endpoint.
Hey all, quick (and potentially naive) question about using the API. After some digging as to why my swagger docs didn't cover any of the response types, I discovered that if I moved the response code (e.g. Ok(...)) into the body of new RhoRoutes[IO] { ... } then everything started working. So my next question is, how can we achieve this without requiring that everything be written in situ?
At the moment, my best guess is to pass new argument around everywhere (implicit responses: ResponseGeneratorInstances[IO]) and try and use this when declaring the routes? ... E.g. "Description of an endpoint" ** POST / "pathhere" ^ jsonOf[IO,MyType] |>> { (body: MyType) => myDef(body)(this) }
I feel like this can't possibly be the right way to go about it though
Kingsley Hendrickse
Ive just started using rho and i found that due to the way it works with implicits i have to put everyhing inside the new RhoRoutes - the only way i found as a workaround was to pass the rho routes into another class and import e.g. import rhoRoutes._ to get all the implicits
Hi all! I have POST endpoint with case classes for request and response. All fields in case classes in camelCase but circe configured to use snake_case. Rho generates definitions in camelCase. How to generate swagger.json with definitions in snake_case?
Hi. I have an API using authorization on some end points. I'm trying to integrate rho for swagger generation. Above I found a message that confirmed that for generating swagger spec, there is some plumbing required for APIs with authorization (cannot use SwaggerMiddleware). But I have even more problems (at least I think so, because I do not fully grasp everything). My authorized routes are nested within Routers. I'm under the impression that the authorization rho meta information does not compose through Routers. At least this is not implemented. Can someone please comment on my thoughts? I can also provide some more details, if required.
Alexandr Solodkyi
@jjcapper I solved it with next hack:
object Api extends ResponseGeneratorInstances[IO]
usage outside RhoRoutes:
Adriani Furtado
Hi All, could anyone point me in the right direction as to how I can specify the swagger format for a query param. I currently have a query parameter that I would like to be displayed as a UUID. I tried to have a look at the lib code but couldn't find any references to format
Adriani Furtado
I guess the question would be; is it possible to define something similar to a Model for query params?
Alexandr Solodkyi
@Adriani277 Can the query be anything other than a primitive value (int, string, double)?
Adriani Furtado
Hi @solo-rh , the query will always be a String. I noticed that we dont support UUID format. I fount formats for int and so on but no uuid.
On another note. I have defined some query parameters and custom query parsers. Howver i noticed that the swagger docs dont show the error responses that can be returned as a result of those query parsers failing. Is there a way to enforce this?
Jarrod Young
Hey there, having some trouble with Refined types. I saw that someone had posted an issue on it. They mentioned that adding their own StringParser solved their issues. I have done the same but cannot find a solution. My case class that used refined types doesn't have a successful definition in the Swagger UI.
Even after adding a custom StringParser.
Jarrod Young
Nevermind I found the issue. Method paramSymToProp was throwing an exception that Refined types are not a class. A custom fieldSerializer fixed it.
Hello! I am brand new to using rho. I have an existing http4s application that under certain error conditions returns status code 470 or 471. These are custom codes that have particular business meaning. I don't understand how to write the rho DSL that will allow custom response codes. It seems like the type structure of Result locks you into only the "common" status codes.
Jonas Natten
Hello smart people!
Could anyone explain to me how i can generalize my authentication response?
I wrote this, and used in in a route. It works, but the swagger field for the responses part is not generated at all.
def doOrAccessDenied(user: Option[UserInfo], w: => F[Result.BaseResult[F]])(
    implicit F: Monad[F],
): F[Result.BaseResult[F]] = {
  user match {
    case Some(user) if user.canWrite => w
    case Some(_)                     => Forbidden(Error.forbidden)
    case None                        => Unauthorized(Error.unauthorized)
Looks like BaseResult is the reason. Here is an example that works for me:
def withAuth[T >: F[FORBIDDEN[ErrorMessage]], A <: T](auth: UserDetails, f: UserDetails => A)(implicit c: Concurrent[F]): T = {
  if (isAllowed(auth)) {
  } else {
    Forbidden(ErrorMessage("Some error message"))

Hi folks!
Could anybody please share an example to generate a classical Swagger file upload?

       summary: Uploads a file.
         - multipart/form-data
         - in: formData
           name: upfile
           type: file
           description: The file to upload.

I didn't notice this feature in the sources. Is it possible at all?
If not, could you please share your thoughts about how it "should be" implemented?

Maxim Miholap

Hi! Does anyone know, is it possible to match route by header in rho?

GET / "check" >>> matchHeader("header.key1","value") |>> ...
GET / "check" >>> matchHeader("header.key2","value2") |>> ...

Hi, @maxmiholap
How about this:
  test("A RhoDsl bits should match route by header") {
    import org.typelevel.ci._
    import cats.implicits._

    case class `header.key1`(value: String)
    implicit val h1: Header[`header.key1`, Header.Single] =
      Header.create[`header.key1`, Header.Single](
        s => `header.key1`(s).asRight[ParseFailure]
    implicit val h1Select = Header.Select.singleHeaders[`header.key1`](h1)

    case class `header.key2`(value: String)
    implicit val h2: Header[`header.key2`, Header.Single] =
      Header.create[`header.key2`, Header.Single](
        s => `header.key2`(s).asRight[ParseFailure]
    implicit val h2Select = Header.Select.singleHeaders[`header.key2`](h2)

    val srvc = new RhoRoutes[IO] {
      GET / "check" >>> H[`header.key1`].capture |>> { (h: `header.key1`) =>
        Ok(s"Header #1: ${h.value}")
      GET / "check" >>> H[`header.key2`].capture |>> { (h: `header.key2`) =>
        Ok(s"Header #2: ${h.value}")

    val reqDefault = Request[IO](GET, uri = uri"/check")

    val h1Req = reqDefault.withHeaders(Header.Raw.apply(ci"header.key1", "value"))
    val h2Req = reqDefault.withHeaders(Header.Raw.apply(ci"header.key2", "value2"))

    assertIOBoolean(srvc(h1Req).flatMap(_.as[String].map(_ == "Header #1: value"))) *>
      assertIOBoolean(srvc(h2Req).flatMap(_.as[String].map(_ == "Header #2: value2")))
Eduardo Ulibarri Toledo

Hello there!
Does anyone know if it is possible to customize error messages when decoding POST form data? No matter the reason, whenever a DecodingFailure occurs because the user-uploaded data is "bad", the server response is always "The request body was invalid".

I'd rather return a more detailed error to the user

I can't seem to find the answer anywhere, so apologies if it's already been asked.
Is there a way to statically generate the swagger.json file? I want to be able to generate it at build time, commit it into source control, and upload it to another internal docs system.
2 replies
Alexey Lykov

Hi! Is it possible to somehow use rho with http4s 1.0-232-85dadc2? I've tried different versions of rho and got Symbol <...> is missing from the classpath. E.g. when using with rho 0.23.0-M1:

error: Symbol 'type org.http4s.Header.Select' is missing from the classpath. This symbol is required by 'method org.http4s.rho.RhoDslHeaderExtractors.H'. Make sure that type Select is in your classpath and check for conflicting dependencies with-Ylog-classpath. A full rebuild may help if 'RhoDslHeaderExtractors.class' was compiled against an incompatible version of org.http4s.Header. Uri(path = Root / Segment(s"$SwaggerUriSegment?url=/api/${apiVersion.name}/swagger.json")) ^

Hi - in the process of upgrading to cats-effect-3 (and therefore http4s 0.23) some tests started failing and I wondered if the reason was a bug in Rho or whether the behaviour we used in 0.22 is no longer supported. Here's a minimal(ish) example:
package com.kiwipowered.stakzcore.apidocs.rho

import cats.effect.{Async, IO, IOApp}
import org.http4s.circe.CirceEntityEncoder
import org.http4s.rho.RhoRoutes
import org.http4s.rho.swagger.models.{Info, Tag}
import org.http4s.rho.swagger.{SwaggerMetadata, SwaggerSupport, SwaggerSyntax}
import org.log4s.getLogger
import org.http4s.blaze.server.BlazeServerBuilder
import org.http4s.rho.swagger.syntax.{io => ioSwagger}

class MinimalExample [F[+_]: Async](swaggerSyntax: SwaggerSyntax[F])
  extends RhoRoutes[F]
    with CirceEntityEncoder {

  import swaggerSyntax._

  "Simple hello world route works with a path" **
    GET / "a" |>> Ok("Hello world!") // curl localhost:8080/a - gives Hello World!

  "Not happy when root" **
    GET / root |>> Ok("Hello world!") // curl localhost:8080 - gives not found

object Main extends IOApp.Simple {
  private val logger = getLogger

  private val port: Int = Option(System.getenv("HTTP_PORT"))

  logger.info(s"Starting Swagger example on '$port'")

  def run: IO[Unit] = {
    val metadata = SwaggerMetadata(
      apiInfo = Info(title = "Rho demo", version = "1.2.3"),
      tags = List(Tag(name = "hello", description = Some("These are the hello routes.")))

    val swaggerUiRhoMiddleware =
      SwaggerSupport[IO].createRhoMiddleware(swaggerMetadata = metadata)

    val myRoutes = new MinimalExample[IO](ioSwagger).toRoutes(swaggerUiRhoMiddleware)

Seems like PathTree.splitPath is now returning 2 elements .. whereas before it returned one. This seems related to endsWithSlash now being true for empty path whereas it used ot be false