I am using SBCL, Emacs, and Slime. In addition, I am using the library Dexador.
Dexador documentation provides an example on how to handle failed HTTP requests.
From the official documentation, it says:
;; Handles 400 bad request
(handler-case (dex:get "http://lisp.org")
(dex:http-request-bad-request ()
;; Runs when 400 bad request returned
)
(dex:http-request-failed (e)
;; For other 4xx or 5xx
(format *error-output* "The server returned ~D" (dex:response-status e))))
Thus, I tried the following. It must be highlighted that this is part of a major system, so I am simplifying it as:
;;Good source to test errors: https://httpstat.us/
(defun my-get (final-url)
(let* ((status-code)
(response)
(response-and-status (multiple-value-bind (response status-code)
(handler-case (dex:get final-url)
(dex:http-request-bad-request ()
(progn
(setf status-code
"The server returned a failed request of 400 (bad request) status.")
(setf response nil)))
(dex:http-request-failed (e)
(progn
(setf status-code
(format nil
"The server returned a failed request of ~a status."
(dex:response-status e)))
(setf response nil))))
(list response status-code))))
(list response-and-status response status-code)))
My code output is close to what I want. But I do not understand it is output.
When the HTTP request is successful, this is the output:
CL-USER> (my-get "http://www.paulgraham.com")
(("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html><script type=\"text/javascript\">
<!--
... big HTML omitted...
</script>
</html>"
200)
NIL NIL)
I was expecting (or wished) the output to be something like: '(("big html" 200) "big html" 200)
.
But, things happen to be even weirder when the HTTP request fails. For instance:
CL-USER> (my-get "https://httpstat.us/400")
((NIL NIL) NIL
"The server returned a failed request of 400 (bad request) status.")
I was expecting: '((NIL "The server returned a failed request of 400 (bad request) status.") NIL "The server returned a failed request of 400 (bad request) status.")
Or:
CL-USER> (my-get "https://httpstat.us/425")
((NIL NIL) NIL "The server returned a failed request of 425 status.")
Again, I was expecting: ((NIL "The server returned a failed request of 425 status.") NIL "The server returned a failed request of 425 status.")
I am afraid there is a variable overshadowing problem happening - not sure, though.
How can I create a function so that I can safely store in variables the response and the status-code independent of being a failed or successful request?
If the request is successful, I have ("html" 200)
. If it fails, it would be: (nil 400)
or other number (nil 425)
- depending on the error message.