Reputation: 23
I am new to Clojure and am wondering if I am setting up this curl call correctly. In the file's name space I define the use to run the clojure.java.shell as the variable sh and then call sh to with the command curl and the complete url to perform a GET curl request.
ns my-exercise.search
(:require [hiccup.page :refer [html5]])
(:use [clojure.java.shell :only [sh]]))
(def response (sh "curl" completeURL))
(println response)
When I print the response in my terminal, I get back a table that looks like it has data on the performance of the response. However, the output is empty parens.
Am I correctly calling the curl command since I am getting a response in the terminal?
{:exit 0, :out (), :err % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2 100 2 0 0 7 0 --:--:-- --:--:-- --:--:-- 7
}
If so, then I have another question. I am receiving an empty parens as the output response. Even when I make the call using Postman I receive a status 200 with the data being empty parens. Does that mean the api is not sending me information?
My last question, lets say I do get it to work and get a response with an output. How do can I get that output and assign it to a variable?
Thanks!
Upvotes: 2
Views: 1994
Reputation: 81
May I suggest an alternative and more idiomatic solution - to use http library? I use clj-http/cljs-http and it really rocks, as it's aware about Clojure data structures and allows you to choose from different serialization options. Here is how I would spawn the same request in clj-http.
add clj-http to dependencies in project.clj
[clj-http "3.7.0"]
require clj-http in ns form:
[clj-http.client :as http]
request code:
(http/get completeURL {:query-params {} ;; you can submit query params here
:as :json}) ;; decode response as json
;; other options are
;; :byte-array - to get response as byte array
;; "UTF-16" - to get response as UTF-16 string
;; :transit+json - to decode response using transit
;; or omit :as option to get response as default string
You can find complete documentation here https://github.com/dakrone/clj-http#output-coercion
Upvotes: 2
Reputation: 29958
Here is how I do it:
(defn run-shell-cmd
"Run a command represented as a string in an OS shell (default=/bin/bash).
Example: 'ls -ldF *' "
[cmd-str]
(let [result (shell/sh *os-shell* "-c" cmd-str)]
(if (= 0 (t/safe-> :exit result))
result
(throw (RuntimeException.
(str "shell-cmd: clojure.java.shell/sh failed. \n"
"cmd-str:" cmd-str "\n"
"exit status:" (:exit result) "\n"
"stderr:" (:err result) "\n"
"result:" (:out result) "\n"
))))))
(let [result (run-shell-cmd "ls -al")]
(newline)
(println :ls-cmd)
(println result))
with result:
:ls-cmd
{:exit 0, :out total 176
drwxrwxr-x 8 alan alan 4096 Mar 14 13:46 .
drwxr-xr-x 155 alan alan 4096 Mar 28 17:27 ..
drwxrwxr-x 8 alan alan 4096 Mar 28 17:29 .git
trying a curl
:
(let [result (run-shell-cmd "curl http://www.google.com")]
(newline)
(println :curl-cmd)
(println result))
)
with result:
:curl-cmd
{:exit 0, :out <!doctype html><html itemscope=""
itemtype="http://schema.org/WebPage" lang="en"><head><meta content="Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for."
name="description"><meta content="noodp" name="robots">
....<snip>
If you don't want to roll your own, you can find the above convenience function here.
Upvotes: 1