Skip to content

oneOf inputs with different types for different formats #4971

@LaurenceWarne

Description

@LaurenceWarne

Hi, I have a situation where I'd like to vary the input type based on the media type - ordinarily I'd just use another endpoint but unfortunately this is a webhook so there's limited control over it. As in https://tapir.softwaremill.com/en/latest/endpoint/oneof.html#oneofbody-inputs-outputs, this works:

case class User(name: String)

object User {
  given Schema[User] = Schema.derived
}

val same = oneOfBody[User](
  formBody[User],
  multipartBody[User]
)

But if I need more information in the multipart case, for example:

case class User(name: String)

object User {
  given Schema[User] = Schema.derived
}

case class UserPart(name: Part[String])

object UserPart {
  given Schema[UserPart] = Schema.derived
}

val either = oneOfBody[Either[User, UserPart]](
  formBody[Either[User, UserPart]],
  multipartBody[Either[Part, UserPart]],
)

Then this fails to compile (I believe!) owing to no Codec for Part in the form case.

A workaround is to formBody[User].map[Either[User,UserPart]](_.asLeft)(either => either.fold(identity, throw new Exception("invalid format"))) but that's not so great 😅...

Intuitively I feel like:

val either: EndpointInput[Either[L, R]] = oneOfEither[L, R](
  formBody[L],
  multipartBody[R]
)

Would make sense, of course please point out if there is already a way to do this 😅, otherwise I guess consider this a feature request.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions