clj-http
clj-http copied to clipboard
An idiomatic clojure http client wrapping the apache client. Officially supported version.
#+TITLE: clj-http documentation #+AUTHOR: Lee Hinman #+STARTUP: align fold nodlcheck lognotestate showall #+OPTIONS: H:4 num:nil toc:t \n:nil @:t ::t |:t ^:{} -:t f:t *:t #+OPTIONS: skip:nil d:(HIDE) tags:not-in-toc auto-id:t #+PROPERTY: header-args :results code :exports both :noweb yes #+HTML_HEAD: #+LANGUAGE: en
[[https://clojars.org/clj-http][file:https://img.shields.io/clojars/v/clj-http.svg]] [[https://github.com/dakrone/clj-http/actions?query=workflow%3A%22Clojure+CI%22][file:https://github.com/dakrone/clj-http/workflows/Clojure%20CI/badge.svg]] [[https://gitter.im/clj-http/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge][file:https://badges.gitter.im/clj-http/Lobby.svg]]
- Table of Contents :TOC_3: :PROPERTIES: :CUSTOM_ID: h-aaf075ea-2f0e-4a45-871a-0f89c838fb4b :END:
- [[#branches][Branches]]
- [[#introduction][Introduction]]
- [[#overview][Overview]]
- [[#philosophy][Philosophy]]
- [[#installation][Installation]]
- [[#quickstart][Quickstart]]
- [[#head][HEAD]]
- [[#get][GET]]
- [[#put][PUT]]
- [[#post][POST]]
- [[#delete][DELETE]]
- [[#async-http-request][Async HTTP Request]]
- [[#cancelling-requests][Cancelling Requests]]
- [[#coercions][Coercions]]
- [[#input-coercion][Input coercion]]
- [[#output-coercion][Output coercion]]
- [[#headers][Headers]]
- [[#query-string-parameters][Query-string parameters]]
- [[#meta-tag-headers][Meta Tag Headers]]
- [[#link-headers][Link Headers]]
- [[#redirects][Redirects]]
- [[#how-to-create-a-custom-redirectstrategy][How to create a custom RedirectStrategy]]
- [[#cookies][Cookies]]
- [[#cookiestores][Cookiestores]]
- [[#keystores-trust-stores][Keystores, Trust-stores]]
- [[#exceptions][Exceptions]]
- [[#decompression][Decompression]]
- [[#debugging][Debugging]]
- [[#logging][Logging]]
- [[#caching][Caching]]
- [[#authentication][Authentication]]
- [[#basic-auth][Basic Auth]]
- [[#digest-auth][Digest Auth]]
- [[#ntlm-auth][NTLM Auth]]
- [[#oauth2][oAuth2]]
- [[#advanced-usage][Advanced Usage]]
- [[#raw-request][Raw Request]]
- [[#boolean-options][Boolean options]]
- [[#persistent-connections][Persistent Connections]]
- [[#re-using-httpclient-between-requests][Re-using =HttpClient= between requests]]
- [[#proxies][Proxies]]
- [[#custom-middleware][Custom Middleware]]
- [[#modifying-apache-specific-features-of-the-httpclientbuilder-and-httpasyncclientbuilder][Modifying Apache-specific features of the =HttpClientBuilder= and =HttpAsyncClientBuilder=]]
- [[#incrementally-json-parsing][Incrementally JSON Parsing]]
- [[#dns-resolution][DNS Resolution]]
- [[#raw-request][Raw Request]]
- [[#development][Development]]
- [[#faking-responses][Faking Responses]]
- [[#optional-dependencies][Optional Dependencies]]
- [[#clj-http-lite][clj-http-lite]]
- [[#troubleshooting][Troubleshooting]]
- [[#verifyerror-class-orgcodehausjacksonsmilesmileparser-overrides-final-method-getbinaryvalue][VerifyError class org.codehaus.jackson.smile.SmileParser overrides final method getBinaryValue...]]
- [[#nohttpresponseexception--due-to-stale-connections][NoHttpResponseException ... due to stale connections**]]
- [[#tests][Tests]]
- [[#testimonials][Testimonials]]
- [[#other-libraries-providing-middleware][Other Libraries Providing Middleware]]
- [[#license][License]]
- Branches :PROPERTIES: :CUSTOM_ID: h-e390585c-cbd8-4e94-b36b-4e9c27c16720 :END:
There are branches for the major version numbers:
- 2.x (no longer maintained except for security issues)
- 3.x (current stable releases and the main Github branch)
- master (which is 4.x, unreleased, based on version 5 of the apache http client)
- Introduction :PROPERTIES: :CUSTOM_ID: h-d893078a-b20b-4086-9272-3d9c28c86846 :END:
** Overview :PROPERTIES: :CUSTOM_ID: h-d8b17d06-124e-44fd-9c86-0399f39b0254 :END:
clj-http is an HTTP library wrapping the [[http://hc.apache.org/][Apache HttpComponents]] client. This library has taken over from mmcgrana's clj-http.
** Philosophy :PROPERTIES: :CUSTOM_ID: h-aa21d07d-333b-4ff2-93a9-ffdca31d8949 :END:
The design of =clj-http= is inspired by the [[https://github.com/ring-clojure/ring][Ring]] protocol for Clojure HTTP server applications.
The client in =clj-http.core= makes HTTP requests according to a given Ring request map and returns [[https://github.com/ring-clojure/ring/blob/master/SPEC][Ring response maps]] corresponding to the resulting HTTP response. The function =clj-http.client/request= uses Ring-style middleware to layer functionality over the core HTTP request/response implementation. Methods like =clj-http.client/get= are sugar over this =clj-http.client/request= function.
- Installation :PROPERTIES: :CUSTOM_ID: h-ddfce0e2-6797-4774-add5-d5cf5bfaaa17 :END:
=clj-http= is available as a Maven artifact from [[http://clojars.org/clj-http][Clojars]].
With Leiningen/Boot:
#+BEGIN_SRC clojure [clj-http "3.12.3"] #+END_SRC
If you need an older version, a 2.x release is also available.
#+BEGIN_SRC clojure [clj-http "2.3.0"] #+END_SRC
clj-http 3.x supports clojure 1.6.0 and higher. clj-http 4.x will support clojure 1.7.0 and higher.
- Quickstart :PROPERTIES: :CUSTOM_ID: h-65f0132e-1f96-4711-a84e-973817f37dd3 :END:
The main HTTP client functionality is provided by the =clj-http.client= namespace.
First, require it in the REPL:
#+BEGIN_SRC clojure (require '[clj-http.client :as client]) #+END_SRC
Or in your application:
#+BEGIN_SRC clojure (ns my-app.core (:require [clj-http.client :as client])) #+END_SRC
The client supports simple =get=, =head=, =put=, =post=, =delete=, =copy=, =move=, =patch=, and =options= requests. Response are returned as [[https://github.com/ring-clojure/ring/blob/master/SPEC][Ring-style response maps]]:
** HEAD :PROPERTIES: :CUSTOM_ID: h-79d1bb5f-c695-46a6-af4e-a64ca599c978 :END:
#+BEGIN_SRC clojure
(client/head "http://example.com/resource")
(client/head "http://example.com/resource" {:accept :json})
#+END_SRC
** GET :PROPERTIES: :CUSTOM_ID: h-89c164fb-85c2-4953-a8c4-a50867adf42a :END:
Example requests:
#+BEGIN_SRC clojure
(client/get "http://example.com/resources/id")
;; Setting options (client/get "http://example.com/resources/3" {:accept :json}) (client/get "http://example.com/resources/3" {:accept :json :query-params {"q" "foo, bar"}})
;; Specifying headers as either a string or collection: (client/get "http://example.com" {:headers {"foo" ["bar" "baz"], "eggplant" "quux"}})
;; Using either string or keyword header names: (client/get "http://example.com" {:headers {:foo ["bar" "baz"], :eggplant "quux"}})
;; Completely ignore cookies: (client/post "http://example.com" {:cookie-policy :none}) ;; There are also multiple ways to handle cookies (client/post "http://example.com" {:cookie-policy :default}) (client/post "http://example.com" {:cookie-policy :netscape}) (client/post "http://example.com" {:cookie-policy :standard}) (client/post "http://example.com" {:cookie-policy :standard-strict})
;; Cookies can be completely configurable with a custom spec by adding a ;; function to return a cookie spec for parsing the cookie. For example, if you ;; wanted to configure a spec provider to have a certain compatibility level: (client/post "http://example.com" {:cookie-spec (fn [http-context] (println "generating a new cookie spec") (.create (org.apache.http.impl.cookie.RFC6265CookieSpecProvider. org.apache.http.impl.cookie.RFC6265CookieSpecProvider$CompatibilityLevel/IE_MEDIUM_SECURITY (PublicSuffixMatcherLoader/getDefault)) http-context))}) ;; Or a version with relaxed compatibility (client/post "http://example.com" {:cookie-spec (fn [http-context] (println "generating a new cookie spec") (.create (org.apache.http.impl.cookie.RFC6265CookieSpecProvider. org.apache.http.impl.cookie.RFC6265CookieSpecProvider$CompatibilityLevel/RELAXED (PublicSuffixMatcherLoader/getDefault)) http-context))})
;; Sometimes you want to do your own validation or something, which you can do ;; by proxying the CookieSpecBase. Note that this doesn't actually return the ;; cookies, because clj-http does its own cookie parsing. If you want to store ;; the cookies from these methods you'll need to use a cookie store or put it in ;; some datastructure yourself. (client/post "http://example.com" {:cookie-spec (fn [http-context] (proxy [org.apache.http.impl.cookie.CookieSpecBase] [] ;; Version and version header (getVersion [] 0) (getVersionHeader [] nil) ;; parse headers into cookie objects (parse [header cookie-origin] (java.util.ArrayList.)) ;; Validate a cookie, throwing MalformedCookieException if the ;; cookies isn't valid (validate [cookie cookie-origin] (println "validating:" cookie)) ;; Determine if a cookie matches the target location (match [cookie cookie-origin] true) ;; Format a list of cookies into a list of headers (formatCookies [cookies] (java.util.ArrayList.))))})
;; If you have created your own registry for cookie policies, you can provide ;; :cookie-policy-registry to use it. See ;; clj-http.core/create-custom-cookie-policy-registry for an example of a custom ;; registry (client/post "http://example.com" {:cookie-policy-registry my-custom-policy-registry :cookie-policy "my-policy"})
;; Need to contact a server with an untrusted SSL cert? (client/get "https://alioth.debian.org" {:insecure? true})
;; If you don't want to follow-redirects automatically: (client/get "http://example.com/redirects-somewhere" {:redirect-strategy :none})
;; Only follow a certain number of redirects: (client/get "http://example.com/redirects-somewhere" {:max-redirects 5})
;; Avoid throwing exceptions if redirected too many times: (client/get "http://example.com/redirects-somewhere" {:max-redirects 5 :redirect-strategy :graceful})
;; Throw an exception if the get takes too long. Timeouts in milliseconds. (client/get "http://example.com/redirects-somewhere" {:socket-timeout 1000 :connection-timeout 1000})
;; Query parameters (client/get "http://example.com/search" {:query-params {"q" "foo, bar"}})
;; "Nested" query parameters
;; (this yields a query string of a[e][f]=6&a[b][c]=5
)
(client/get "http://example.com/search" {:query-params {:a {:b {:c 5} :e {:f 6}}}})
;; Provide cookies 窶