Response
March 31, 2019 ยท View on GitHub
This guide outlines how to use the response map to respond to incoming requests.
Coast passes the current HTTP response map as part of the request-lifecycle which is sent to all route handlers and middleware.
; routes.clj
(def routes
(coast/routes
[:get "/" :home/index]))
; src/home.clj
(defn index [request]
{:status 200 :body "this returns a string"})
The above example returns a string with a content type of text/plain
Basic Example
The following example returns an array of customers in JSON format:
; routes.clj
[:get "/customers" :customer/index]
; src/customer.clj
(defn index [request]
(let [customers [{:customer/id 1 :customer/name "Sean"}
{:customer/id 2 :customer/name "Johnny"}
{:customer/id 2 :customer/name "Felix"}
{:customer/id 2 :customer/name "Gloria"}]]
{:status 200 :body customers :headers {"Content-Type" "application/json"}}))
The coast/ok function can also be used instead of a map:
(defn index [request]
(let [customers [{:customer/id 1 :customer/name "Sean"}
{:customer/id 2 :customer/name "Johnny"}
{:customer/id 2 :customer/name "Felix"}
{:customer/id 2 :customer/name "Gloria"}]]
(coast/ok customers :json)))
Making responses
Coast has common functions for the most common http responses:
- ok (200)
- created (201)
- accepted (202)
- no-content (204)
- bad-request (400)
- unauthorized (401)
- not-found (404)
- forbidden (403)
- server-error 500
They accept either a keyword as the last argument, :html or :json.
(coast/created {:customer/id 1} :json)
(coast/ok [:h1 "hello world"] :html)
Headers
They also accept headers as well:
(coast/created {:customer/id 1} {"Content-Type" "application/json"})
(coast/ok [:h1 "hello world"] {"Content-Type" "text/html"})
Coast by default returns {"Content-Type" "application/octet-stream"}
Cookies
Use the following keys to set/remove response cookies.
cookie
Set a cookie value:
{:status 200
:body ""
:cookies {"cart-total" {:value "20"}}}
clearing a cookie
Remove an existing cookie value (by setting its expiry in the past):
{:status 200
:body ""
:cookies {"cart-total" {:expires (coast/time 1 :second/ago)}}}
As well as setting the value of the cookie, you can also set additional keys:
Shamelessly stolen from the ring docs
:domain- restrict the cookie to a specific domain:path- restrict the cookie to a specific path:secure- restrict the cookie to HTTPS URLs if true:http-only- restrict the cookie to HTTP if true (not accessible via e.g. JavaScript):max-age- the number of seconds until the cookie expires:expires- a specific date and time the cookie expires:same-site- Specify :strict or :lax to determine whether cookies should be sent with cross-site requests
Redirects
Use one of the following functions to redirect requests to a different URL.
redirect
Redirect request to a different url (by default it will set the status as 302):
(defn view [request])
(defn create [request]
(coast/redirect (coast/url-for ::view)))
You can also skip the url-for like so:
(defn create [request]
(coast/redirect-to ::view))
Or you can redirect to any url:
(coast/redirect "https://coastonclojure.com")
flash
Coast also has a handy flash function which will append a value to the next request after the redirect:
(-> (coast/redirect-to ::view)
(coast/flash "Item created successfully!"))
This flash value now resides in the next function's request map under the :flash key
Extending Response
It is also possible to extend the response map by adding your own keys:
(defn index [request])
(-> (coast/ok "Annie are you ok, are you ok, Annie?")
(assoc :my-custom-key-for-my-custom-middleware "hello")