r0man / cljs-http

A ClojureScript HTTP library.
582 stars 93 forks source link

** Usage

*** Imports

/cljs-http/ returns [[https://github.com/clojure/core.async][core.async]] channels, so you need to import the
=go= macro and the =<!= function.

#+BEGIN_SRC clojure
  (ns example.core
    (:require-macros [cljs.core.async.macros :refer [go]])
    (:require [cljs-http.client :as http]
              [cljs.core.async :refer [<!]]))
#+END_SRC

*** Async response handling

All HTTP functions in /cljs-http/ return a [[https://github.com/clojure/core.async][core.async]]
channel. When a request has completed or failed it is put on that
channel. You can take the response from that channel with the =<!=
function *within* a =go= block.

#+BEGIN_SRC clojure
  (go (let [response (<! (http/get "https://api.github.com/users"
                                   {:with-credentials? false
                                    :query-params {"since" 135}}))]
        (prn (:status response))
        (prn (map :login (:body response)))))
#+END_SRC

You can pass your own response channel. This is useful when using
a transducers.

#+BEGIN_SRC clojure
  (http/get "http://example.com" {:channel (chan 1 (map :body))})
#+END_SRC

*** Content type

/cljs-http/ can serialize the body of a request and set the
/Content-Type/ header accordingly. You can send the body params in
mutiple formats:

#+BEGIN_SRC clojure
  (http/post "http://example.com" {:edn-params {:foo :bar}})

  (http/post "http://example.com" {:json-params {:foo :bar}})
  ;;(JSON is auto-converted via `cljs.core/clj->js`)

  (http/post "http://example.com" {:transit-params {:key1 "value1" :key2 "value2"}})

  (http/post "http://example.com" {:form-params {:key1 "value1" :key2 "value2"}})
#+END_SRC

To send form parameters (an array of values):

#+BEGIN_SRC clojure
(http/post "http://example.com" {:form-params {:key1 [1 2 3] :key2 "value2"}})
#+END_SRC

To upload a file using Multipart parameters:

#+BEGIN_SRC clojure
(http/post "http://example.com" {:multipart-params [["key1" "value1"] ["my-file" my-file]]})
#+END_SRC

Where =my-file= can be a JavaScript [[https://developer.mozilla.org/en/docs/Web/API/Blob][Blob]] instance

#+BEGIN_SRC clojure
  (def my-file (js/Blob. #js ["<h1>Hello</h1>"] #js {:type "text/html"}))
#+END_SRC

or a HTML file input field.

#+BEGIN_SRC html
  <input id="my-file" type="file">
#+END_SRC

#+BEGIN_SRC clojure
  (def my-file
    (-> (.getElementById js/document "my-file")
        .-files first))
#+END_SRC

If you want to set the name of the file use a vector as =my-file=.

#+BEGIN_SRC clojure
  (def my-file ["myfile" [value filename]])
#+END_SRC

See [[https://developer.mozilla.org/en-US/docs/Web/API/FormData/append#Syntax][https://developer.mozilla.org/en-US/docs/Web/API/FormData/append#Syntax]] for more details.

*** HTTP Basic Authentication

#+BEGIN_SRC clojure
  (http/get "http://example.com" {:basic-auth {:username "hello" :password "world"}})
#+END_SRC

*** OAuth 2.0 Bearer Token

#+BEGIN_SRC clojure
  (http/get "http://example.com" {:with-credentials? false
                                  :oauth-token "SecretBearerToken"})
#+END_SRC

*** Custom Headers (Authorization)

#+BEGIN_SRC clojure
(http/post "https://example.com"
           {:with-credentials? false
            :headers {"Authorization" "SuperSecretToken"}})
#+END_SRC

*** Upload/Download progress monitoring

#+BEGIN_SRC clojure
(let [progress-channel (async/chan)]
  (http/post "http://example.com" {:multipart-params [["key1" "value1"] ["my-file" my-file]] :progress progress-chan}))
#+END_SRC

The progress-channel will receive progress events: {:directon dir :loaded uploaded_or_downloaded :total size}
- :direction is :upload or :download
- in some cases :total can be missing

*** JSONP

#+BEGIN_SRC clojure
  (http/jsonp "http://example.com" {:callback-name "callback" :timeout 3000})
#+END_SRC

Where =callback-name= is used to specify /JSONP/ callback param
name.  Defaults to "callback". =timeout= is the length of time, in
milliseconds. This channel is prepared to wait for for a request
to complete. If the call is not competed within the set time span,
it is assumed to have failed.

** License

Copyright (C) 2012-2016 r0man

Distributed under the Eclipse Public License, the same as Clojure.