diff --git a/src/clj/puppetlabs/http/client/async.clj b/src/clj/puppetlabs/http/client/async.clj index a001ea4..dfa8261 100644 --- a/src/clj/puppetlabs/http/client/async.clj +++ b/src/clj/puppetlabs/http/client/async.clj @@ -26,7 +26,7 @@ (:require [puppetlabs.certificate-authority.core :as ssl] [clojure.string :as str] [puppetlabs.kitchensink.core :as ks] - [puppetlabs.http.client.schemas :as schemas] + [puppetlabs.http.client.common :as common] [schema.core :as schema] [clojure.tools.logging :as log]) (:refer-clojure :exclude (get))) @@ -60,12 +60,12 @@ [req] (initialize-ssl-context-from-ca-pem req)) -(schema/defn configure-ssl :- (schema/either {} schemas/SslContextOptions) +(schema/defn configure-ssl :- (schema/either {} common/SslContextOptions) "Configures a request map to have an SSLContext. It will use an existing one (stored in :ssl-context) if already present, and will fall back to a set of PEM files (stored in :ssl-cert, :ssl-key, and :ssl-ca-cert) if those are present. If none of these are present this does not modify the request map." - [opts :- schemas/SslOptions] + [opts :- common/SslOptions] (cond (:ssl-context opts) opts (every? opts [:ssl-cert :ssl-key :ssl-ca-cert]) (configure-ssl-from-pems opts) @@ -169,16 +169,16 @@ :body (when-let [entity (.getEntity http-response)] (.getContent entity))})) -(schema/defn error-response :- schemas/ErrorResponse - [opts :- schemas/UserRequestOptions +(schema/defn error-response :- common/ErrorResponse + [opts :- common/UserRequestOptions e :- Exception] {:opts opts :error e}) -(schema/defn callback-response :- schemas/Response - [opts :- schemas/UserRequestOptions - callback :- schemas/ResponseCallbackFn - response :- schemas/Response] +(schema/defn callback-response :- common/Response + [opts :- common/UserRequestOptions + callback :- common/ResponseCallbackFn + response :- common/Response] (if callback (try (callback response) @@ -187,11 +187,11 @@ response)) (schema/defn deliver-result - [client :- schemas/Client - result :- schemas/ResponsePromise - opts :- schemas/UserRequestOptions - callback :- schemas/ResponseCallbackFn - response :- schemas/Response] + [client :- common/Client + result :- common/ResponsePromise + opts :- common/UserRequestOptions + callback :- common/ResponseCallbackFn + response :- common/Response] (try (deliver result (callback-response opts callback response)) (finally @@ -199,10 +199,10 @@ (.close client))))) (schema/defn future-callback - [client :- schemas/Client - result :- schemas/ResponsePromise - opts :- schemas/UserRequestOptions - callback :- schemas/ResponseCallbackFn] + [client :- common/Client + result :- common/ResponsePromise + opts :- common/UserRequestOptions + callback :- common/ResponseCallbackFn] (reify FutureCallback (completed [this http-response] (try @@ -223,12 +223,12 @@ opts (HttpClientException. "Request cancelled")))))) -(schema/defn extract-client-opts :- schemas/ClientOptions - [opts :- schemas/UserRequestOptions] +(schema/defn extract-client-opts :- common/ClientOptions + [opts :- common/UserRequestOptions] (select-keys opts [:ssl-context :ssl-ca-cert :ssl-cert :ssl-key])) -(schema/defn create-default-client :- schemas/Client - [opts :- schemas/RawUserRequestOptions] +(schema/defn create-default-client :- common/Client + [opts :- common/RawUserRequestOptions] (let [defaults {:headers {} :body nil :decompress-body true @@ -245,7 +245,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Public -(schema/defn ^:always-validate request :- schemas/ResponsePromise +(schema/defn ^:always-validate request :- common/ResponsePromise "Issues an async HTTP request and returns a promise object to which the value of `(callback {:opts _ :status _ :headers _ :body _})` or `(callback {:opts _ :error _})` will be delivered. @@ -275,16 +275,16 @@ * :ssl-cert - path to a PEM file containing the client cert * :ssl-key - path to a PEM file containing the client private key * :ssl-ca-cert - path to a PEM file containing the CA cert" - ([opts :- schemas/RawUserRequestOptions] + ([opts :- common/RawUserRequestOptions] (request opts nil)) - ([opts :- schemas/RawUserRequestOptions - callback :- schemas/ResponseCallbackFn] + ([opts :- common/RawUserRequestOptions + callback :- common/ResponseCallbackFn] (let [client (create-default-client opts) opts (assoc opts :persistent false)] (request opts callback client))) - ([opts :- schemas/RawUserRequestOptions - callback :- schemas/ResponseCallbackFn - client :- schemas/Client] + ([opts :- common/RawUserRequestOptions + callback :- common/ResponseCallbackFn + client :- common/Client] (let [defaults {:headers {} :body nil :decompress-body true diff --git a/src/clj/puppetlabs/http/client/common.clj b/src/clj/puppetlabs/http/client/common.clj index 132d918..37310e5 100644 --- a/src/clj/puppetlabs/http/client/common.clj +++ b/src/clj/puppetlabs/http/client/common.clj @@ -1,6 +1,16 @@ (ns puppetlabs.http.client.common + (:import (java.net URL) + (javax.net.ssl SSLContext) + (org.apache.http.impl.nio.client CloseableHttpAsyncClient) + (clojure.lang IBlockingDeref) + (java.io InputStream) + (java.nio.charset Charset)) + (:require [schema.core :as schema]) (:refer-clojure :exclude (get))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Client Protocol + (defprotocol HTTPClient (get [this url] [this url opts]) (head [this url] [this url opts]) @@ -11,3 +21,98 @@ (options [this url] [this url opts]) (patch [this url] [this url opts]) (close [this])) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Schemas + +(def ok schema/optional-key) + +(def UrlOrString (schema/either schema/Str URL)) + +;; TODO: replace this with a protocol +(def Client CloseableHttpAsyncClient) + +(def Headers + {schema/Str schema/Str}) + +(def Body + (schema/maybe (schema/either String InputStream))) + +(def BodyType + (schema/enum :text :stream)) + +(def RawUserRequestOptions + {:url UrlOrString + :method schema/Keyword + (ok :headers) Headers + (ok :body) Body + (ok :decompress-body) schema/Bool + (ok :as) BodyType + (schema/optional-key + :persistent) schema/Bool + + (ok :ssl-context) SSLContext + (ok :ssl-cert) UrlOrString + (ok :ssl-key) UrlOrString + (ok :ssl-ca-cert) UrlOrString}) + +(def RequestOptions + {:url UrlOrString + :method schema/Keyword + :headers Headers + :body Body + :decompress-body schema/Bool + :as BodyType + (schema/optional-key + :persistent) schema/Bool}) + +(def SslContextOptions + {:ssl-context SSLContext}) + +(def SslCaCertOptions + {:ssl-ca-cert UrlOrString}) + +(def SslCertOptions + {:ssl-cert UrlOrString + :ssl-key UrlOrString + :ssl-ca-cert UrlOrString}) + +(def SslOptions + (schema/either {} SslContextOptions SslCertOptions SslCaCertOptions)) + +(def UserRequestOptions + (schema/either + RequestOptions + (merge RequestOptions SslContextOptions) + (merge RequestOptions SslCaCertOptions) + (merge RequestOptions SslCertOptions))) + +(def ClientOptions + SslOptions) + +(def ResponseCallbackFn + (schema/maybe (schema/pred ifn?))) + +(def ResponsePromise + IBlockingDeref) + +(def ContentType + (schema/maybe {:mime-type schema/Str + :charset (schema/maybe Charset)})) + +(def NormalResponse + {:opts UserRequestOptions + :orig-content-encoding (schema/maybe schema/Str) + :body Body + :headers Headers + :status schema/Int + :content-type ContentType}) + +(def ErrorResponse + {:opts UserRequestOptions + :error Exception}) + +(def Response + (schema/either NormalResponse ErrorResponse)) + + diff --git a/src/clj/puppetlabs/http/client/persistent_async.clj b/src/clj/puppetlabs/http/client/persistent_async.clj index 5408f44..7506b9d 100644 --- a/src/clj/puppetlabs/http/client/persistent_async.clj +++ b/src/clj/puppetlabs/http/client/persistent_async.clj @@ -2,7 +2,7 @@ (:import (org.apache.http.impl.nio.client HttpAsyncClients)) (:require [schema.core :as schema] [puppetlabs.http.client.common :as common] - [puppetlabs.http.client.schemas :as schemas] + [puppetlabs.http.client.common :as common] [puppetlabs.http.client.async :refer [request configure-ssl]]) (:refer-clojure :exclude (get))) @@ -10,7 +10,7 @@ ;;; Public (schema/defn create-client :- common/HTTPClient - [opts :- schemas/ClientOptions] + [opts :- common/ClientOptions] (let [opts (configure-ssl opts) client (if (:ssl-context opts) (.. (HttpAsyncClients/custom) (setSSLContext (:ssl-context opts)) build) diff --git a/src/clj/puppetlabs/http/client/persistent_sync.clj b/src/clj/puppetlabs/http/client/persistent_sync.clj index f6e94f0..7f8f06c 100644 --- a/src/clj/puppetlabs/http/client/persistent_sync.clj +++ b/src/clj/puppetlabs/http/client/persistent_sync.clj @@ -2,7 +2,7 @@ (:import (org.apache.http.impl.nio.client HttpAsyncClients)) (:require [schema.core :as schema] [puppetlabs.http.client.common :as common] - [puppetlabs.http.client.schemas :as schemas] + [puppetlabs.http.client.common :as common] [puppetlabs.http.client.sync :refer [request]] [puppetlabs.http.client.async :refer [configure-ssl]]) (:refer-clojure :exclude (get))) @@ -11,7 +11,7 @@ ;;; Public (schema/defn create-client :- common/HTTPClient - [opts :- schemas/ClientOptions] + [opts :- common/ClientOptions] (let [opts (configure-ssl opts) client (if (:ssl-context opts) (.. (HttpAsyncClients/custom) (setSSLContext (:ssl-context opts)) build) diff --git a/src/clj/puppetlabs/http/client/schemas.clj b/src/clj/puppetlabs/http/client/schemas.clj deleted file mode 100644 index 776a779..0000000 --- a/src/clj/puppetlabs/http/client/schemas.clj +++ /dev/null @@ -1,102 +0,0 @@ -(ns puppetlabs.http.client.schemas - (:import (java.net URL) - (javax.net.ssl SSLContext) - (org.apache.http.impl.nio.client CloseableHttpAsyncClient) - (clojure.lang IBlockingDeref) - (java.io InputStream) - (java.nio.charset Charset)) - (:require [schema.core :as schema])) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Schemas - -(def ok schema/optional-key) - -(def UrlOrString (schema/either schema/Str URL)) - -;; TODO: replace this with a protocol -(def Client CloseableHttpAsyncClient) - -(def Headers - {schema/Str schema/Str}) - -(def Body - (schema/maybe (schema/either String InputStream))) - -(def BodyType - (schema/enum :text :stream)) - -(def RawUserRequestOptions - {:url UrlOrString - :method schema/Keyword - (ok :headers) Headers - (ok :body) Body - (ok :decompress-body) schema/Bool - (ok :as) BodyType - (schema/optional-key - :persistent) schema/Bool - - (ok :ssl-context) SSLContext - (ok :ssl-cert) UrlOrString - (ok :ssl-key) UrlOrString - (ok :ssl-ca-cert) UrlOrString}) - -(def RequestOptions - {:url UrlOrString - :method schema/Keyword - :headers Headers - :body Body - :decompress-body schema/Bool - :as BodyType - (schema/optional-key - :persistent) schema/Bool}) - -(def SslContextOptions - {:ssl-context SSLContext}) - -(def SslCaCertOptions - {:ssl-ca-cert UrlOrString}) - -(def SslCertOptions - {:ssl-cert UrlOrString - :ssl-key UrlOrString - :ssl-ca-cert UrlOrString}) - -(def SslOptions - (schema/either {} SslContextOptions SslCertOptions SslCaCertOptions)) - -(def UserRequestOptions - (schema/either - RequestOptions - (merge RequestOptions SslContextOptions) - (merge RequestOptions SslCaCertOptions) - (merge RequestOptions SslCertOptions))) - -(def ClientOptions - SslOptions) - -(def ResponseCallbackFn - (schema/maybe (schema/pred ifn?))) - -(def ResponsePromise - IBlockingDeref) - -(def ContentType - (schema/maybe {:mime-type schema/Str - :charset (schema/maybe Charset)})) - -(def NormalResponse - {:opts UserRequestOptions - :orig-content-encoding (schema/maybe schema/Str) - :body Body - :headers Headers - :status schema/Int - :content-type ContentType}) - -(def ErrorResponse - {:opts UserRequestOptions - :error Exception}) - -(def Response - (schema/either NormalResponse ErrorResponse)) -