Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support flag query parameters #2091

Closed
adamw opened this issue Apr 29, 2022 · 1 comment · Fixed by #2113
Closed

Support flag query parameters #2091

adamw opened this issue Apr 29, 2022 · 1 comment · Fixed by #2113
Assignees
Milestone

Comments

@adamw
Copy link
Member

adamw commented Apr 29, 2022

Currently we don't support flag-like query parameters.

query[Option[String]]("flag") decodes ?flag into a None and ?flag= into a Some("")

I'm not sure how this should be represented in an OpenAPI spec. There is the allowEmptyValues field (see https://swagger.io/specification/), but it's deprecated and shouldn't be used. There is a large discussion here: OAI/OpenAPI-Specification#1573, but I think it doesn't reach a conclusion as to how to represent this in OpenAPI. So more research would be needed.

On the tapir side, I think we'll need to add a new field to Query which would store the value, that should be used for the query parameter, in case no value is provided. Sth like query[String]("flag").valueWhenNoValue("true"), except with a better name :)

@adamw adamw added this to the 1.0.0 milestone Apr 29, 2022
@eikek
Copy link

eikek commented Apr 29, 2022

For the time being a possible workaround would be to combine two definitions:

def queryFlag(name: String, description: String = "") = {
  // this is false when the query parameter exists without a value
  val a = query[Option[Boolean]](name)
    .description(description)
    .example(EndpointIO.Example(true.some, "true".some, None))
    .example(EndpointIO.Example(false.some, "false".some, None))

  // this is true when the query parameter exists without a value, but same as (a) otherwise
  // but it is not added to the documentation
  val b = queryParams
    .map(qp => qp.getMulti(name).exists(_.forall(_.equalsIgnoreCase("true"))))(flag =>
      QueryParams.fromMap(Map(name -> flag.toString))
    )

  // combining both does the job…
  (a / b).map(_._2)(flag => (flag.some, flag))
}

@adamw adamw self-assigned this May 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants