How do I set a response status code with caveman2?

117 Views Asked by At

I'm trying to create an endpoint that will send a status code using caveman2.

(defroute "/books/" ()
  (render-json "Hello"))

I have found the function throw-code which enables me to send a status code, but it won't let me send a response body as well. It seems it was meant for handling errors.

(import 'caveman2:throw-code)
    (defroute "/books/" ()
      (throw-code 403)
      ;; This will not respond with "Hello"
      (render-json "Hello"))

The caveman2 github page talks about responding with specific status codes:

Set HTTP headers or HTTP status

There are several special variables available during a HTTP request. request and response represent a request and a response. If you are familiar with Clack, these are instances of subclasses of Clack.Request and Clack.Response.

(use-package :caveman2)

;; Get a value of Referer header.
(http-referer *request*)

;; Set Content-Type header.
(setf (getf (response-headers *response*) :content-type) "application/json")

;; Set HTTP status.
(setf (status *response*) 304)

However, I do not know how to instantiate these objects or how to import them. I couldn't find a working example and when I put this in as is in my code it won't compile.

How can I accomplish this?

2

There are 2 best solutions below

0
On BEST ANSWER

The *response* variable is bound to an instance while the request is being processed (it is a special variable). You can experiment with the following short example:

You need these systems:

(ql:quickload '(:clack :caveman2))

Then:

(defpackage :test-caveman2 (:use :cl))
(in-package :test-caveman2)


(defparameter *web* (make-instance 'caveman2:<app>))

(caveman2:defroute "/hello/" ()
  "Hello")

(defparameter *server* (clack:clackup *web*))

With the above code executed, you should be able to see a simple Hello page at address localhost:5000/hello/

Now, let's make a page with a body but a different status:

(caveman2:defroute "/bye/" ()
  ;; here *response* is bound to a response object
  ;; let's change its status
  (setf (caveman2:response-status caveman2:*response*) 403)
  "403 - Nope")

If you inspect with your browser, e.g. F12 in Firefox, the Network tab, you can see that the response status is 403 for /bye/, but that the page displays also a body.

2
On

You don't have to instantiate them. These are special variables that are already bound within the context of the defroute function. So, you can just do:

(defroute "/books/" ()
  (setf (caveman2:response-status caveman2:*response*) 403)
  (render-json "Hello"))

or you can import caveman2:*response* and caveman2:response-status in your package definition and use it similarly to other caveman2 symbols like defroute or render-json:

(defroute "/books/" ()
  (setf (response-status *response*) 403)
  (render-json "Hello"))