I find that incremental development tends to break when coding for Hunchentoot.
For example, I might write a web page that is composed of a few functions. If one of these inner functions contains a call to - say - hunchentoot:post-parameters* then I can't easily test the function in the REPL. It'll error out because *request* doesn't exist unless the page is called by a web client.
It would be nice if some function-or-other-source existed such that I could test my-function thus:
>(let* ((*request* (get-previous-request-from-somewhere))
(*session* (slot-value *request* 'hunchentoot:session)))
(my-function <whatever params>))
Does it or something similar exist? Am I overlooking a better approach to debugging?
My interim solution looks something like this:
(defparameter *save-last-request* t)
(defvar *last-request* nil)
(defun store-request ()
(when *save-last-request*
(setf *last-request* *request*)))
(defmacro with-last-request (&body body)
`(let* ((*request* *last-request*)
(*session* (slot-value *request* 'hunchentoot:session)))
,#body))
It works fine with the caveat that each handler needs to make a call to store-request.
I think the simplest thing to do might be to use a custom request class that introduces a way to persist requests somewhere into the initializer chain.
Here's a trivial example of one approach. A custom subclass of request which saves it's state, in a global stack.
You can set your acceptors to use custom request-classes using
(setf (acceptor-request-class acceptor ) new-value)
so something like this
(defparameter *requests* nil)
(defclass my-request (hunchentoot:request) ())
(defmethod initialize-instance :after ((req my-request) &key)
(push req *requests*))
and then set the acceptor request class to use this when you make your acceptor e.g.
(setf (hunchentoot:acceptor-request-class
(make-instance 'hunchentoot:easy-acceptor)) 'my-request)
Every time a request is created by this acceptor to pass to the handler, it will be added to the *requests* list.
if you use a variable to specify the request class name you could toggle this class on and off for development/debugging.
You could then take requests from this stack in your test binding.
Related
I'm working on a simple project that shows some data that I'd like to see everyday. This will go on to my raspberry-pi. I'm using a free api that has a limit on requests so I thought I'd cache the requests so I don't spam the API. Here is what I've got so far:
(def KEY "Cache-Key")
(def CF (cache/ttl-cache-factory {} :ttl 43200)) ; 12 hour cache
(defn get-data-from-api
[url]
(let [response {:cache true :value 1}]
(println "---> getting from http")
response))
(defn get-data
[url]
(cache/lookup-or-miss CF KEY (get-data-from-api url)))
According to this link, this is all that is required. Except:
my get-data function always gets it from the api (the println I added to debug gets printed always). The cache is being added just fine, just doesn't seem to fetch and return
The get-data doesn't return anything. So when I do curl http://localhost:3001/display I get an empty response.
Am I using the cache correctly please?
The last value to lookup-or-miss must be a function that will be called on a cache miss. In your code, you're first calling the function and then pass its result to the lookup function, so your function will be called unconditionally (after all, lookup-or-miss is a regular function itself and not a macro - it can't dictate when its arguments are evaluated).
Even in the article you link to, they pass http-get directly and the url serves as the key, which lookup-or-miss will use as an argument for http-get by default on a cache miss.
Suppose I need widget data and widget parts data. I need to retrieve the widget data via http request to get its parts-numbers. I use those parts-numbers to make more http requests to get parts data.
Using https://github.com/Day8/re-frame-http-fx, it'd look like:
(reg-event-fx
:foo/get-widget
(fn [{:keys [db]} [_]]
{:http-xhrio {:method :get
:uri "foobar.com/widget"
:format (ajax/transit-request-format)
:response-format (ajax/json-response-format)
:on-success [:foo/load-widget]
:on-failure [:foo/set-error]}}))
(reg-event-fx
:foo/get-widget-part
(fn [{:keys [db]} [_ part-number]]
{:http-xhrio {:method :get
:uri (str "foobar.com/part/" part-number)
:format (ajax/transit-request-format)
:response-format (ajax/json-response-format)
:on-success [:foo/load-part]
:on-failure [:foo/set-error]}}))
How would I initialize my parts data for my page? The most straightforward method I can come up with is to wrap get-widget and get-widget-part by writing another handler get-widget-then-widget-parts by doing a http request for the widget and on success take that data and retrieve parts data. My issue with that is that it isn't very composable. I need to create another handler. At the same time I can't just (dispatch [:foo/get-widget]) and feed the result into (dispatch [:foo/get-widget-part]) (as far as I know).
If I understand correctly, your aim is to create multiple get-widget-part requests after get-widget returns the widget data with part ids. You could write an event handler that looks up the ids, and dispatches multiple :foo/get-widget-part events.
(reg-event-fx
:foo/load-widget ;Your :on-success event
(fn [{:keys [db]} [_ widget-data]]
(let [ids (get-part-ids widget-data)
missing-ids (remove #(get-part-with-id db %) ids)] ;Load only missing parts
{:db (set-widget-data db widget-data)
:dispatch-n (map (fn [id] [:foo/get-widget-part id]) missing-ids)})))
You likely don't want to fetch the parts "eagerly" every time. So, you could either A) provide a separate argument (e.g., :fetch-eager) and merge the :dispatch-n conditionally depending on that, or B) create separate events for lazy and eager fetching (say, :foo/get-widget and :foo/get-widget-with-parts). I would prefer the latter option B, as it easier to build upon, for example, when a dedicated API endpoint is added for fetching the widget with parts.
You can compose the creation of the effect map returned from the event handler. In the above example, lazy fetch action would create just a :db effect (e.g., mk-db-widget-data), while the eager version would be composed of both the :dbupdate and the :get-widget-part events (e.g., mk-dispatch-get-widget-parts).
I have code that looks something like the below:
(defn on-message [event]
(do-stuff))
(defn build-websocket []
(let [ws (js.window.WebSocket. "ws://localhost:8888/ws/")]
(set! (.-onopen ws) on-open)
(set! (.-onclose ws) on-close)
(set! (.-onerror ws) on-error)
(set! (.-onmessage ws) on-message)
ws))
I'm using figwheel. I have noticed that when I change my callbacks (on-message, on-error, etc), the app does reload, but old versions of these functions still get called.
(defn on-message [event]
; Changed. Requires hard reload to be called on websocket message.
(do-other-stuff))
I understand that this is because the old version of the function is still referenced by the websocket.
Is there a pattern that would make this code reloadable? Perhaps I should be using core/async? If so, what would that look like?
Perhaps your code is not reloadable. Another thing to look at, for quick fix, is to always reload the namespace when you save from your editor/IDE:
(ns ^:figwheel-always my.namespace
(:require [clojure.string :as str])
Notice the ^:figwheel-always metadata.
For more on writing reloadable code see here.
I have a compojure app that uses the ring session wrapper to store the OAuth token associated with the current user. I would like for this token to remain available when the server restarts, so that I don't have to go through the auth process each time.
I assumed that using the cookie-store instead of the default memory-store would help, but it does not. What am I missing?
This is the relevant part of the code:
(defn auth-callback-handler
[session {code :code}]
(let [token (retrieve-token code)]
(-> (redirect "/") (assoc :session (assoc session :token token)))))
(defroutes app-routes
(GET "/" {session :session} (root-handler session))
(GET "/auth-callback" {session :session params :params} (auth-callback-handler session params))
(route/not-found "Not Found"))
(def app
(-> (handler/site app-routes)
(wrap-session {:store (cookie-store {:key "a 16-byte secret"})})))
The function root-handler uses the token to decide if someone is logged in or not, but does not return anything in the way of session info.
The issue is that you have 2 wrap-session middlewares in your app, as the handler/site comes with one. This is causing the encrypt/decrypt to be run twice. To configure the compojure session handle use:
(def app
(site app-routes {:session {:store (cookie-store {:key "a 16-byte secret"})}}))
Also, perhaps you would be interested on some of these projects, which implement the ring SessionStore protocol:
https://github.com/sritchie/couch-session
https://github.com/wuzhe/clj-redis-session
https://github.com/rmarianski/servlet-session-store
To make the last one persistent you will need to check the documentation of your servlet container of choice.
I'm new to clojurescript and would like to do a deeper dive by implementing a previously written application purely in clojurescript, but am at a loss with respect to to implement an ajax call. Can anyone point me to an example online or provide me with a code snippet or two?
January 22, 2016 update
Although it still works, the original answer is from a time when there was a general lack of ClojureScript solutions with more than 1 contributor. Rather than leveraging XhrIo directly, definitely consider using a well-maintained, feature-rich solution that wrappers it instead like cljs-ajax, as suggested by Mikhail D below!
Okay, So given that Clojurescript leverages Google's Closure JavaScript library, a quick search of the Closure Documentation yielded xhrIo as the proper method for generating AJAX calls:
Example using Closure's Asynchronous XMLHttpRequests with XhrIo
goog.net.XhrIo.send(url, opt_callback, opt_method, opt_content,
opt_headers, opt_timeoutInterval)
A quick review of the Clojurescript source revealed the following function:
From src/cljs/clojure/browser/net.cljs in clojure / clojurescript
(defn xhr-connection
"Returns an XhrIo connection"
[]
(goog.net.XhrIo.))
So something along the lines of this should have the intended results:
(def xhr xhr-connection)
(defn myCallback [replyValue]
... Do Something with replyValue
... for example: (someJsonFunc (.getResponseJson (.target replyValue))))
(defn ajax-json [url]
(.send xhr url myCallback))
For JSONP, you can do something similar using the goog.net.Jsonp. See the link for details:
JSONP Closure API
Hope someone finds this helpful!
An another viable option could be https://github.com/JulianBirch/cljs-ajax
Since it's designed for ClojureScript, the syntax looks clearer and simpler. It also supports a lot of features out of the box (for example: transit, edn and json formats).
Some examples from a README:
(ns foo
(:require [ajax.core :refer [GET POST]]))
...
(GET "/hello" {:handler handler
:error-handler error-handler})
(POST "/send-message"
{:params {:message "Hello World"
:user "Bob"}
:handler handler
:error-handler error-handler})
The way I did it is slightly different. I don't know why the way that Marc suggested in his answer didn't work for me. Hopefully this is also useful.
I used goog.net.XhrIo directly, rather than the xhr-connection wrapper.
(defn callback [reply]
(let [v (js->clj (.getResponseJson (.-target reply)))] ;v is a Clojure data structure
(your-function-here v)))
(.send goog.net.XhrIo url callback)
The main difference that I can see is that I've used .-target to get the property of the JSON object, rather than calling target.
It's worth noting that maps in v that have been created from JSON objects are keyed by strings not keywords.