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

Can't get Swagger UI to provide interface for arbitrary query params #455

Open
aneilbaboo opened this issue Jan 27, 2022 · 2 comments
Open

Comments

@aneilbaboo
Copy link

aneilbaboo commented Jan 27, 2022

Library Version(s)

2.0.0-alpha31

Problem

Swagger can display a UI for setting dynamic query parameters, but I can't figure out how to do it with compojure-api.

I have a /find endpoint which needs to receive arbitrary query parameters.

E.g., Given /api/find?x=1&y=2&z=3 I want to receive a map {:x 1, :y 2, :3} somewhere in my handler. The keys are chosen by the requester.

(ns myns (:require [schema.core :as scm]))

(def myapp
   (api ...
       (GET "/find" [& fields]
                  :return scm/Any
           (ok fields))

This works:

 curl 'localhost:8080/api/runs/find?a=1&b=2'
{"a":"1","b":"2"}%     

But the Swagger UI does not provide a way to set the query parameters:
image

I've tried variants of the route, providing

:query [fields scm/Any]

And many other things. I can't seem to find documentation for the arguments to :query. (Also, does anyone understand what :- is for?)

If I use a schema that starts with schema.core/maybe...

(scm/defschema QueryArgs (scm/maybe (scm/cond-pre scm/Num scm/Str scm/Bool scm/Keyword scm/Uuid)))

and provide this to :query...

  (GET "/find" [& fields]
         :return scm/Any
         :query [fields QueryArgs]
      (ok))

Swagger at least shows a box that allows me to assign several values inside another parameter, but it's not the one I want:
image

It produces a URL like this:

curl -X GET --header 'Accept: application/json' 'http://localhost:8080/api/runs/find?schemas=a%3D1&schemas=b%3D2'

But I want

curl -X GET --header 'Accept: application/json' 'http://localhost:8080/api/runs/find?a=1&b=2'
@aneilbaboo
Copy link
Author

aneilbaboo commented Mar 21, 2023

@ikitommi - This issue was a bit long. Here's a TL;DR. Thanks in advance for any help!

I'm trying to write a search API where query parameters are dynamic.

GET /docs?foo=1&bar=2

Where foo and bar are runtime-generated keys.

Any thoughts on how to get a map of all query parametrs passed by the user, and present a UI in Swagger that allows setting them?

@aneilbaboo
Copy link
Author

FWIW, for anyone else encountering this issue, I solved it by capturing query parameters two different ways, one capturing the raw URL query parameters, and another which enables inputing values through the swagger UI. In the box, the user will enter key-value pairs like:

foo=123
baz=abc

Which in the following behaves the same as a query using /my-route?foo=123&baz=abc

The handler looks like this.:

  (GET "/" [& params] ;; fields captures URL query params
    ;; query enables an input box in the Swagger UI
    :query-params [{query :- [scm/Str] []}]  
    (let [params (dissoc params query)
            processed-query  (into {} (map #(let [[lhs rhs] (str/split % #"=")] [(keyword lhs) rhs]) query))
            params (merge params query)]
       ;; here params is the same for normal query parameters or the Swagger UI

The var params will be a map containing the query variables:

(println params) ; => {:foo "123" :baz "abc"}

Coercion is left up to you. Hope that helps.

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

No branches or pull requests

1 participant