How to test http requests with cljs-http using lein doo phantom - clojure

While running my tests with lein doo phantom, I receive a -1 status response and an empty string as the body. However, when I run the test in the repl, I am able to retrieve the request data with a 200 status response and the appropriate data in the body. Is this because a manytomany channel is being returned first as mentioned below, thus giving me the inappropriate response? If so, how could I account for this?
https://github.com/r0man/cljs-http#async-response-handling
I also thought maybe I need to use a timeout to wait for the request to complete. If so, how would I apply that appropriately with my existing code? It looks like cljs-http has :timeout as a parameter but I haven't been ably to get it to work appropriately (assuming this is the cause of the issue).
(deftest test-async
(async done
(go (let [response (<! (http/get "http://localhost:3000/api/user/1"
{:with-credentials? false
:query-params {"id" 1}}))]
(is (= {:status 200}
(select-keys response [:status]))))
(done))))

Since you are running your test under phantomjs. Phantomjs default disable cross domain XHR access and your tests js are running on localhost,all external ajax calls are denied.
you can set the --web-security=false to allow your test to do cross domain ajax.
In your project.clj add this
:doo {:paths {:phantom "phantomjs --web-security=false"}}
more info about phantomjs
http://phantomjs.org/api/command-line.html

Related

How to listen to slack messages using clojure?

I am using clj-slack start method for getting the web-socket url and then passing it to the connect method of gniazdo for listening to the web-socket.
(require '[clj-slack.rtm :as slack])
(require '[gniazdo.core :as ws])
(def connection {:api-url "https://slack.com/api" :token "your token"})
(defn reset-conn [options]
(def socket
(ws/connect
(:url (slack/start options))
:on-receive #(prn 'received %))))
(reset-conn connection)
This code is working fine but it only provides information about who is active or away for slack:
received"{\"type\":\"presence_change\",\"presence\":\"active\",\"user\":\"U7BCQHWHY\"}"
But I also want to listen to the messages.
I don't know why messages are not printed though it was stated in slack-api documentation that rtm(real time messaging) is for messaging session.

Datomic deletes databases

I deployed my Clojure app to AWS and I also have Datomic Transactor(EC2) with DynamoDB when my users started to use my app something happened after a while and Datomic Transactor rebooted(for some reason), my app became unresponsive so I re-started my application server(to re-establish transactor connection) then there were no users data, no data at all!?
I was using same URI("datomic:ddb://us-east-1/my-table/my-db"), also I don't call delete-db or some function like that.
I only call d/create-database and d/connect for connecting to Datomic.
It happened me on development but I did not care that time because I thought I did something wrong or something like that.
How can I restore that old data?
P.S: Also I can see that DynamoDB table has some storage size like 900KB I assume some how my data in there? There were just couple of users tho.
My Datomic Version: "0.9.5561"
Here is my code:
(defn establish-conn
[]
(try
;conf/get returns DB URI like: "datomic:ddb://us-east-1/my-table/my-db"
(d/create-database (conf/get :db-uri))
(reset! conn (d/connect (conf/get :db-uri)))
(catch Throwable t
(log/error "Could not establish db conn." t))))
Also I have this code for recovering connection from Transactor failure/unavailable etc.
(defn fix-if-conn-ex
;;getting exception's error message
[err-msg]
(when (any? (str/includes? err-msg %) [":db.error/connection-released"
":db.error/transactor-unavailable"])
(db/establish-conn)))
I could not reproduce the issue with the latest Datomic version "0.9.5561.56" on my staging environment, I assume it's resolved with that one.

XA context for immutant listener

I am trying to use immutant to manage transactions across HornetQ and mysql. As I understand the docs, to do this I must use XA transactions, because I am running a standalone app and not inside an app server.
However when I try and set :xa? for the context of my application, I get exceptions when tying to setup a listener.
(ns example
(:require [immutant.messaging :as msg]))
(def capture (atom nil))
(let [ctx (msg/context :host "localhost" :xa? true)
queue (msg/queue "example" :context ctx)]
(reset! capture nil)
(msg/listen queue (fn [m] (reset! capture m)))
(msg/publish queue {:my :msg}))
This throws "java.lang.IllegalStateException: You can't create a child context from an XA context." from the (msg/listen) invocation. What am I doing wrong?
I think you've discovered a bug, but in your case, I think there's a workaround: you only need that :xa? true option if your queue is remote. You can still create an XA transaction binding your HornetQ actions to MySQL in your listener handler using the immutant.transactions/transaction macro. See the docs for an example.

HTTP-Kit streaming and curl

I tried out the basic example for HTTP streaming of HTTP-Kit (http://www.http-kit.org/server.html#async), but if I curl to the endpoint I get all the messages at once, after the connection is closed (instead of getting them every 200ms, as it works in the browser). What's going on?
I also tried it like this:
(schedule-task (* id 200) ;; send a message every 200ms
(send! channel
{:status 200
:headers {"Content-Type" "text/event-stream"
"Connection" "keep-alive"}
:body (str "message from server #" id)}
false)) ; false => don't close after send
The behaviour is the same.
Seems to be an issue with curl and Streaming http. According to this post, the order of options is important
Also, try using the -N, --no-buffer option

How do i determine the correct filesystem path

I am working on an application that has to download some external resources and make them accessible through a public/static directory in Ring.
But.. I have a problem saving the resources into a static directory in my application, when developing I use the ring-jetty-adapter; the test & production servers are running Tomcat.
I added :web-content "public" to my leiningen project and added the public directory in the root of the project, then I have a download function using http-agent and duck-streams:
(defn download
[file-name url]
(h/http-agent url
:handler (fn [agnt]
(let [fname file-name]
(with-open [w (d/writer fname)]
(d/copy (h/stream agnt) w))))))
If I am booting Jetty from the REPL and use savepath: "public/my.file", the downloaded file is placed correctly in the public directory.
But when I deploy it using a .war file to Tomcat, it looks for a public directory in the Tomcat root directory, and not under the application context path.
I tried to add a middleware wrapper to determine the context path and from there build the correct save path, but I cannot find any way to access the HttpServlet or a way to determine if the application is running in the adapter or if it is deployed under a specific context.
Here the wrapper:
(defn wrap-context-info [handler]
(fn [req]
(let [resp (handler req)]
(assoc resp :servlet (:servlet req) :req (:servlet-request req)))))
both :servlet and :req are nil.
Looking at the ring-servlet source, it appears that the ring servlet adapter associates the HttpServlet, HttpServletRequest, and HttpServletResponse objects with the ring request map under :servlet, :servlet-request, and :servlet-response keys, accordingly.
It also adds a :servlet-context entry to the request map with the value of (.getServletContext servlet) for convenience.
Inside your handler, you might want to check for the presence of these keys in the request map, and then pull further information that you need from the associated objects.