I'm making a toy API using the Yada library in Clojure. It searches a database for city names starting with the given characters and returns some info about it.
I want a URI of the form: /cities/:name?count=:count
so for example /cities/ber?count=4
will return the top 4 matches. But I also want /cities/ber
without the ?count=
parameter to return a default number of results (say just the first).
I've defined my route and yada handler like this:
(defn city-search-fn
[ctx]
(let [name (get-in ctx [:parameters :path :name])
count (get-in ctx [:parameters :query :count] 1)]
(city->geoposition name count)))
(def cities (yada/handler (yada/resource
{:methods
{:get
{:parameters {:path {:name String}
:query {:count Long}}
:produces ["application/json"
"application/edn"]
:response city-search-fn}}})))
(def routes
[["/cities/" :name] cities])
(def server
(yada/listener routes {:port 30000}))
This works fine if I supply the ?count=
query parameter:
$ curl -i 'http://localhost:30000/cities/ber?count=2'
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Length: 259
Content-Type: application/json
Vary: accept
Server: Aleph/0.4.4
Connection: Keep-Alive
Date: Mon, 09 Sep 2019 16:01:45 GMT
[{"name":"Berlin","state":"Berlin","countrycode":"DE","timezone":"Europe/Berlin","latitude":52.52437,"longitude":13.41053},{"name":"Berbera","state":"Woqooyi Galbeed","countrycode":"SO","timezone":"Africa/Mogadishu","latitude":10.43959,"longitude":45.01432}]
But I get status 400 ({:status 400, :errors ([:query {:error {:count missing-required-key}}])}
) if I don't supply it:
$ curl -i 'http://localhost:30000/cities/ber'
HTTP/1.1 400 Bad Request
Content-Length: 77
Content-Type: text/plain;charset=utf-8
Server: Aleph/0.4.4
Connection: Keep-Alive
Date: Mon, 09 Sep 2019 16:06:56 GMT
{:status 400, :errors ([:query {:error {:count missing-required-key}}])}
The documentation of yada says it supports optional query parameters using the "schema" library. So I found in schema's documentation that there exists a schema.core/maybe
function. I tried to modify my yada resource as follows:
:parameters {:path.....
:query (schema/maybe {:count Long})}
this doesn't work (same 400 error).
Then I tried:
:parameters {:path.....
:query {:count (schema/maybe Long)}}
this also didn't work.
So my question is: what is the correct way to have an optional query parameter in yada?
To answer my own question, digging more into Schema documentation, here is the correct way:
The key itself needs to be marked as optional.