cbdallavalle
cbdallavalle

Reputation: 23

Performing a get curl request in Clojure

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

Answers (2)

edvorg
edvorg

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

Alan Thompson
Alan Thompson

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

Related Questions