Comma separated query parameters in plumber API

See here: Parameter Serialization

Consider this plumber.R file:

library(plumber)

#* Sort letters
#* @param letters:[]
#* @json
#* @get /letters
function(letters) {
  sort(letters)
}

How do I change the request from this:

http://127.0.0.1:9203/letters?letters=a&letters=b

To this:

http://127.0.0.1:9203/letters?letters=a,b


Referred here by rstudio/plumber

It is not supported by plumber. I think we decided it could lead to unfortunate behaviour, since the coma is a reserved character. I might be able to find the pull request detailing why we abandonned the idea.

If you check the openapi.json definition, it specifies hat the letters parameter is exploded:

{
  "servers": [
    {
      "url": ""
    }
  ],
  "openapi": "3.0.3",
  "info": {
    "description": "API Description",
    "title": "API Title",
    "version": "1.0.0"
  },
  "paths": {
    "/letters": {
      "get": {
        "summary": "Sort letters",
        "description": "",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "Default response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "letters",
            "in": "query",
            "required": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "style": "form",
           "explode": true
          }
        ]
      }
    }
  }
}

Thanks for the reply! Is it possible to override the behavior? I think I saw it's possible to pass your own openapi.json somewhere, maybe with pr_set_api_spec() or something.

openapi.json is a generated file. You can change the information in it with the method you mentioned, but it is not going to modify how plumber handles your query parameters. To do that, you would have to replace the default query parameters parser. Alternatively, you could explode the query string before plumber internal filter parses it. It is quite a lot more involved than doing a simple strsplit.

Here is one such example where the query string is modified before plumber process it.

library(plumber)

#* @plumber
function(pr) {
  interceptor <- function(req) {
    # Check if the query string contains non URL encoded coma
    if (grepl(",", req[["QUERY_STRING"]])) {
      # Split the query string by non URL encoded coma
      qs <- req[["QUERY_STRING"]] |> strsplit(",") |> .subset2(1)
      # Extract the keys from the query string, assuming keys are only alphanumeric
      keys <- gregexec("([A-z0-9]+)=[^=]+$", qs) |> regmatches(qs, m = _) |>
        lapply(\(x) tail(as.vector(x), 1))
      # Add the right key in front of the parameter value
      for (i in seq_len(length(qs)-1L)) {
        if (length(keys[[i]])) {
          k <- keys[[i]]
        }
        qs[1L+i] <- sprintf("&%s=%s", k, qs[1L+i])
      }
      # Rebuild the query string
      req[["QUERY_STRING"]] <- paste0(qs, collapse = "")
    }
  }
  # register interceptor to execute before plumber handle the request `preroute`
  interceptor |> list(preroute = _) |> pr[["registerHooks"]]()
  pr
}

#* Sort letters
#* @param letters:[]
#* @json
#* @get /letters
function(letters) {
  sort(letters)
}

Note that for it to work, the coma most not be URL encoded. But you can change all that depending on the behavior you want to achieve.

Thanks @meztez really appreciate your help :slight_smile:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.