2014-07-03 15:58:46 +00:00
|
|
|
(ns puppetlabs.http.client.async-plaintext-test
|
2016-01-07 17:05:54 +00:00
|
|
|
(:import (com.puppetlabs.http.client Async RequestOptions ClientOptions)
|
2014-08-08 23:32:48 +00:00
|
|
|
(org.apache.http.impl.nio.client HttpAsyncClients)
|
2016-01-07 17:05:54 +00:00
|
|
|
(java.net URI SocketTimeoutException ServerSocket))
|
2014-07-03 15:58:46 +00:00
|
|
|
(:require [clojure.test :refer :all]
|
2014-08-06 17:49:48 +00:00
|
|
|
[puppetlabs.http.client.test-common :refer :all]
|
2014-07-03 15:58:46 +00:00
|
|
|
[puppetlabs.trapperkeeper.core :as tk]
|
|
|
|
[puppetlabs.trapperkeeper.testutils.bootstrap :as testutils]
|
|
|
|
[puppetlabs.trapperkeeper.testutils.logging :as testlogging]
|
2015-03-16 17:50:09 +00:00
|
|
|
[puppetlabs.trapperkeeper.testutils.webserver :as testwebserver]
|
2014-07-03 15:58:46 +00:00
|
|
|
[puppetlabs.trapperkeeper.services.webserver.jetty9-service :as jetty9]
|
2014-07-15 23:46:20 +00:00
|
|
|
[puppetlabs.http.client.common :as common]
|
2014-07-03 15:58:46 +00:00
|
|
|
[puppetlabs.http.client.async :as async]
|
2015-12-18 20:21:27 +00:00
|
|
|
[schema.test :as schema-test]))
|
2014-07-03 15:58:46 +00:00
|
|
|
|
|
|
|
(use-fixtures :once schema-test/validate-schemas)
|
|
|
|
|
|
|
|
(defn app
|
2015-03-16 17:50:09 +00:00
|
|
|
[_]
|
2014-07-03 15:58:46 +00:00
|
|
|
{:status 200
|
|
|
|
:body "Hello, World!"})
|
|
|
|
|
2016-02-04 13:11:27 +00:00
|
|
|
(defn app-with-empty-content-type
|
|
|
|
[_]
|
|
|
|
{:headers {"content-type" ""}
|
|
|
|
:status 200
|
|
|
|
:body "Hello, World!"})
|
|
|
|
|
2014-07-03 15:58:46 +00:00
|
|
|
(tk/defservice test-web-service
|
|
|
|
[[:WebserverService add-ring-handler]]
|
|
|
|
(init [this context]
|
|
|
|
(add-ring-handler app "/hello")
|
|
|
|
context))
|
|
|
|
|
2014-07-15 22:07:43 +00:00
|
|
|
(deftest persistent-async-client-test
|
|
|
|
(testlogging/with-test-logging
|
|
|
|
(testutils/with-app-with-config app
|
|
|
|
[jetty9/jetty9-service test-web-service]
|
|
|
|
{:webserver {:port 10000}}
|
2014-11-07 21:29:17 +00:00
|
|
|
(testing "java async client"
|
|
|
|
(let [request-options (RequestOptions. (URI. "http://localhost:10000/hello/"))
|
|
|
|
client-options (ClientOptions.)
|
2014-11-10 19:24:36 +00:00
|
|
|
client (Async/createClient client-options)]
|
2014-11-07 21:29:17 +00:00
|
|
|
(testing "HEAD request with persistent async client"
|
|
|
|
(let [response (.head client request-options)]
|
|
|
|
(is (= 200 (.getStatus (.deref response))))
|
|
|
|
(is (= nil (.getBody (.deref response))))))
|
|
|
|
(testing "GET request with persistent async client"
|
|
|
|
(let [response (.get client request-options)]
|
|
|
|
(is (= 200 (.getStatus (.deref response))))
|
|
|
|
(is (= "Hello, World!" (slurp (.getBody (.deref response)))))))
|
|
|
|
(testing "POST request with persistent async client"
|
|
|
|
(let [response (.post client request-options)]
|
|
|
|
(is (= 200 (.getStatus (.deref response))))
|
|
|
|
(is (= "Hello, World!" (slurp (.getBody (.deref response)))))))
|
|
|
|
(testing "PUT request with persistent async client"
|
|
|
|
(let [response (.put client request-options)]
|
|
|
|
(is (= 200 (.getStatus (.deref response))))
|
|
|
|
(is (= "Hello, World!" (slurp (.getBody (.deref response)))))))
|
|
|
|
(testing "DELETE request with persistent async client"
|
|
|
|
(let [response (.delete client request-options)]
|
|
|
|
(is (= 200 (.getStatus (.deref response))))
|
|
|
|
(is (= "Hello, World!" (slurp (.getBody (.deref response)))))))
|
|
|
|
(testing "TRACE request with persistent async client"
|
|
|
|
(let [response (.trace client request-options)]
|
|
|
|
(is (= 200 (.getStatus (.deref response))))
|
|
|
|
(is (= "Hello, World!" (slurp (.getBody (.deref response)))))))
|
|
|
|
(testing "OPTIONS request with persistent async client"
|
|
|
|
(let [response (.options client request-options)]
|
|
|
|
(is (= 200 (.getStatus (.deref response))))
|
|
|
|
(is (= "Hello, World!" (slurp (.getBody (.deref response)))))))
|
|
|
|
(testing "PATCH request with persistent async client"
|
|
|
|
(let [response (.patch client request-options)]
|
|
|
|
(is (= 200 (.getStatus (.deref response))))
|
|
|
|
(is (= "Hello, World!" (slurp (.getBody (.deref response)))))))
|
2014-11-12 22:20:50 +00:00
|
|
|
(testing "client closes properly"
|
|
|
|
(.close client)
|
|
|
|
(is (thrown? IllegalStateException
|
|
|
|
(.get client request-options))))))
|
2014-11-07 21:29:17 +00:00
|
|
|
(testing "clojure async client"
|
|
|
|
(let [client (async/create-client {})]
|
|
|
|
(testing "HEAD request with persistent async client"
|
|
|
|
(let [response (common/head client "http://localhost:10000/hello/")]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= nil (:body @response)))))
|
|
|
|
(testing "GET request with persistent async client"
|
|
|
|
(let [response (common/get client "http://localhost:10000/hello/")]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (slurp (:body @response))))))
|
|
|
|
(testing "POST request with persistent async client"
|
|
|
|
(let [response (common/post client "http://localhost:10000/hello/")]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (slurp (:body @response))))))
|
|
|
|
(testing "PUT request with persistent async client"
|
|
|
|
(let [response (common/put client "http://localhost:10000/hello/")]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (slurp (:body @response))))))
|
|
|
|
(testing "DELETE request with persistent async client"
|
|
|
|
(let [response (common/delete client "http://localhost:10000/hello/")]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (slurp (:body @response))))))
|
|
|
|
(testing "TRACE request with persistent async client"
|
|
|
|
(let [response (common/trace client "http://localhost:10000/hello/")]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (slurp (:body @response))))))
|
|
|
|
(testing "OPTIONS request with persistent async client"
|
|
|
|
(let [response (common/options client "http://localhost:10000/hello/")]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (slurp (:body @response))))))
|
|
|
|
(testing "PATCH request with persistent async client"
|
|
|
|
(let [response (common/patch client "http://localhost:10000/hello/")]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (slurp (:body @response))))))
|
2016-02-04 11:07:07 +00:00
|
|
|
(testing "GET request via request function with persistent async client"
|
2016-01-15 19:14:54 +00:00
|
|
|
(let [response (common/make-request client "http://localhost:10000/hello/" :get)]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (slurp (:body @response))))))
|
2016-02-04 11:07:07 +00:00
|
|
|
(testing "Bad verb request via request function with persistent async client"
|
|
|
|
(is (thrown? IllegalArgumentException
|
|
|
|
(common/make-request client
|
|
|
|
"http://localhost:10000/hello/"
|
|
|
|
:bad))))
|
2014-11-07 21:29:17 +00:00
|
|
|
(testing "client closes properly"
|
|
|
|
(common/close client)
|
2014-11-12 22:20:50 +00:00
|
|
|
(is (thrown? IllegalStateException
|
|
|
|
(common/get client
|
|
|
|
"http://localhost:10000/hello/")))))))))
|
2014-07-17 21:03:39 +00:00
|
|
|
|
|
|
|
(deftest request-with-client-test
|
|
|
|
(testlogging/with-test-logging
|
|
|
|
(testutils/with-app-with-config app
|
|
|
|
[jetty9/jetty9-service test-web-service]
|
|
|
|
{:webserver {:port 10000}}
|
|
|
|
(let [client (HttpAsyncClients/createDefault)
|
|
|
|
opts {:method :get :url "http://localhost:10000/hello/"}]
|
|
|
|
(.start client)
|
|
|
|
(testing "GET request works with request-with-client"
|
|
|
|
(let [response (async/request-with-client opts nil client)]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (slurp (:body @response))))))
|
|
|
|
(testing "Client persists when passed to request-with-client"
|
|
|
|
(let [response (async/request-with-client opts nil client)]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (slurp (:body @response))))))
|
2014-08-06 17:49:48 +00:00
|
|
|
(.close client)))))
|
|
|
|
|
2014-11-14 23:36:40 +00:00
|
|
|
(deftest query-params-test-async
|
|
|
|
(testlogging/with-test-logging
|
|
|
|
(testutils/with-app-with-config app
|
|
|
|
[jetty9/jetty9-service test-params-web-service]
|
|
|
|
{:webserver {:port 8080}}
|
|
|
|
(testing "URL Query Parameters work with the Java client"
|
|
|
|
(let [client (Async/createClient (ClientOptions.))]
|
|
|
|
(try
|
|
|
|
(let [request-options (RequestOptions.
|
|
|
|
(URI. "http://localhost:8080/params?foo=bar&baz=lux"))
|
|
|
|
response (.get client request-options)]
|
|
|
|
(is (= 200 (.getStatus (.deref response))))
|
|
|
|
(is (= queryparams (read-string (slurp (.getBody
|
|
|
|
(.deref response)))))))
|
|
|
|
(finally
|
|
|
|
(.close client)))))
|
|
|
|
(testing "URL Query Parameters work with the clojure client"
|
|
|
|
(with-open [client (async/create-client {})]
|
|
|
|
(let [opts {:method :get
|
|
|
|
:url "http://localhost:8080/params/"
|
|
|
|
:query-params queryparams
|
|
|
|
:as :text}
|
|
|
|
response (common/get client "http://localhost:8080/params" opts)]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= queryparams (read-string (:body @response)))))))
|
|
|
|
(testing "URL Query Parameters can be set directly in the URL"
|
|
|
|
(with-open [client (async/create-client {})]
|
|
|
|
(let [response (common/get client
|
|
|
|
"http://localhost:8080/params?paramone=one"
|
|
|
|
{:as :text})]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= (str {"paramone" "one"}) (:body @response))))))
|
|
|
|
(testing (str "URL Query Parameters set in URL are overwritten if params "
|
|
|
|
"are also specified in options map")
|
|
|
|
(with-open [client (async/create-client {})]
|
|
|
|
(let [response (common/get client
|
|
|
|
"http://localhost:8080/params?paramone=one&foo=lux"
|
|
|
|
query-options)]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= queryparams (read-string (:body @response))))))))))
|
|
|
|
|
2014-08-25 18:15:22 +00:00
|
|
|
(deftest redirect-test-async
|
|
|
|
(testlogging/with-test-logging
|
|
|
|
(testutils/with-app-with-config app
|
|
|
|
[jetty9/jetty9-service redirect-web-service]
|
|
|
|
{:webserver {:port 8080}}
|
2014-11-15 22:37:00 +00:00
|
|
|
(testing (str "redirects on POST not followed by persistent Java client "
|
|
|
|
"when forceRedirects option not set to true")
|
|
|
|
(let [client (Async/createClient (ClientOptions.))]
|
|
|
|
(try
|
|
|
|
(let [request-options (RequestOptions.
|
|
|
|
(URI. "http://localhost:8080/hello"))
|
|
|
|
response (.post client request-options)]
|
|
|
|
(is (= 302 (.getStatus (.deref response)))))
|
|
|
|
(finally
|
|
|
|
(.close client)))))
|
|
|
|
(testing "redirects on POST followed by Java client when option is set"
|
|
|
|
(let [client (Async/createClient (.. (ClientOptions.)
|
|
|
|
(setForceRedirects true)))]
|
|
|
|
(try
|
|
|
|
(let [request-options (RequestOptions.
|
|
|
|
(URI. "http://localhost:8080/hello"))
|
|
|
|
response (.post client request-options)]
|
|
|
|
(is (= 200 (.getStatus (.deref response))))
|
|
|
|
(is (= "Hello, World!" (slurp (.getBody (.deref response))))))
|
|
|
|
(finally
|
|
|
|
(.close client)))))
|
|
|
|
(testing "redirects not followed by Java client when :follow-redirects is false"
|
|
|
|
(let [client (Async/createClient (.. (ClientOptions.)
|
|
|
|
(setFollowRedirects false)))]
|
|
|
|
(try
|
|
|
|
(let [request-options (RequestOptions.
|
|
|
|
(URI. "http://localhost:8080/hello"))
|
|
|
|
response (.get client request-options)]
|
|
|
|
(is (= 302 (.getStatus (.deref response)))))
|
|
|
|
(finally
|
|
|
|
(.close client)))))
|
|
|
|
(testing ":follow-redirects overrides :force-redirects for Java client"
|
|
|
|
(let [client (Async/createClient (.. (ClientOptions.)
|
|
|
|
(setFollowRedirects false)
|
|
|
|
(setForceRedirects true)))]
|
|
|
|
(try
|
|
|
|
(let [request-options (RequestOptions.
|
|
|
|
(URI. "http://localhost:8080/hello"))
|
|
|
|
response (.get client request-options)]
|
|
|
|
(is (= 302 (.getStatus (.deref response)))))
|
|
|
|
(finally
|
|
|
|
(.close client)))))
|
|
|
|
(testing (str "redirects on POST not followed by clojure client "
|
|
|
|
"when :force-redirects is not set to true")
|
|
|
|
(with-open [client (async/create-client {:force-redirects false})]
|
|
|
|
(let [opts {:method :post
|
|
|
|
:url "http://localhost:8080/hello"
|
|
|
|
:as :text}
|
|
|
|
response (common/post client "http://localhost:8080/hello" opts)]
|
|
|
|
(is (= 302 (:status @response))))))
|
2014-08-25 18:15:22 +00:00
|
|
|
(testing (str "redirects on POST followed by persistent clojure client "
|
|
|
|
"when option is set")
|
2014-11-15 22:37:00 +00:00
|
|
|
(with-open [client (async/create-client {:force-redirects true})]
|
|
|
|
(let [response (common/post client
|
|
|
|
"http://localhost:8080/hello"
|
|
|
|
{:as :text})]
|
|
|
|
(is (= 200 (:status @response)))
|
|
|
|
(is (= "Hello, World!" (:body @response))))))
|
2014-08-26 23:36:47 +00:00
|
|
|
(testing (str "persistent clojure client does not follow redirects when "
|
|
|
|
":follow-redirects is set to false")
|
2014-11-15 22:37:00 +00:00
|
|
|
(with-open [client (async/create-client {:follow-redirects false})]
|
|
|
|
(let [response (common/get client
|
|
|
|
"http://localhost:8080/hello"
|
|
|
|
{:as :text})]
|
|
|
|
(is (= 302 (:status @response))))))
|
2014-08-26 23:36:47 +00:00
|
|
|
(testing ":follow-redirects overrides :force-redirects with persistent clj client"
|
2014-11-15 22:37:00 +00:00
|
|
|
(with-open [client (async/create-client {:follow-redirects false
|
|
|
|
:force-redirects true})]
|
|
|
|
(let [response (common/get client
|
|
|
|
"http://localhost:8080/hello"
|
|
|
|
{:as :text})]
|
|
|
|
(is (= 302 (:status @response)))))))))
|
2015-03-16 17:50:09 +00:00
|
|
|
|
|
|
|
(deftest short-connect-timeout-persistent-java-test-async
|
|
|
|
(testing (str "connection times out properly for java persistent client "
|
|
|
|
"async request with short timeout")
|
|
|
|
(with-open [client (-> (ClientOptions.)
|
|
|
|
(.setConnectTimeoutMilliseconds 250)
|
|
|
|
(Async/createClient))]
|
|
|
|
(let [request-options (RequestOptions. "http://127.0.0.255:65535")
|
|
|
|
time-before-connect (System/currentTimeMillis)]
|
2015-03-17 05:46:07 +00:00
|
|
|
(is (connect-exception-thrown? (-> client
|
|
|
|
(.get request-options)
|
|
|
|
(.deref)
|
|
|
|
(.getError)))
|
2015-03-16 17:50:09 +00:00
|
|
|
"Unexpected result for connection attempt")
|
|
|
|
(is (elapsed-within-range? time-before-connect 2000)
|
|
|
|
"Connection attempt took significantly longer than timeout")))))
|
|
|
|
|
|
|
|
(deftest short-connect-timeout-persistent-clojure-test-async
|
|
|
|
(testing (str "connection times out properly for clojure persistent client "
|
|
|
|
"async request with short timeout")
|
|
|
|
(with-open [client (async/create-client
|
|
|
|
{:connect-timeout-milliseconds 250})]
|
|
|
|
(let [time-before-connect (System/currentTimeMillis)]
|
2015-03-17 05:46:07 +00:00
|
|
|
(is (connect-exception-thrown? (-> @(common/get
|
|
|
|
client
|
|
|
|
"http://127.0.0.255:65535")
|
|
|
|
:error))
|
2015-03-16 17:50:09 +00:00
|
|
|
"Unexpected result for connection attempt")
|
|
|
|
(is (elapsed-within-range? time-before-connect 2000)
|
|
|
|
"Connection attempt took significantly longer than timeout")))))
|
|
|
|
|
|
|
|
(deftest longer-connect-timeout-test-async
|
|
|
|
(testing "connection succeeds for async request with longer connect timeout"
|
|
|
|
(testlogging/with-test-logging
|
|
|
|
(testwebserver/with-test-webserver app port
|
|
|
|
(let [url (str "http://localhost:" port "/hello")]
|
|
|
|
(testing "java persistent async client"
|
|
|
|
(with-open [client (-> (ClientOptions.)
|
|
|
|
(.setConnectTimeoutMilliseconds 2000)
|
|
|
|
(Async/createClient))]
|
|
|
|
(let [response (-> client
|
|
|
|
(.get (RequestOptions. url))
|
|
|
|
(.deref))]
|
|
|
|
(is (= 200 (.getStatus response)))
|
|
|
|
(is (= "Hello, World!" (slurp (.getBody response)))))))
|
|
|
|
(testing "clojure persistent async client"
|
|
|
|
(with-open [client (async/create-client
|
|
|
|
{:connect-timeout-milliseconds 2000})]
|
|
|
|
(let [response @(common/get client url {:as :text})]
|
|
|
|
(is (= 200 (:status response)))
|
|
|
|
(is (= "Hello, World!" (:body response)))))))))))
|
|
|
|
|
|
|
|
(deftest short-socket-timeout-persistent-java-test-async
|
|
|
|
(testing (str "socket read times out properly for persistent java async "
|
|
|
|
"request with short timeout")
|
|
|
|
(with-open [client (-> (ClientOptions.)
|
|
|
|
(.setSocketTimeoutMilliseconds 1)
|
|
|
|
(Async/createClient))
|
|
|
|
server (ServerSocket. 0)]
|
|
|
|
(let [request-options (-> "http://127.0.0.1:"
|
|
|
|
(str (.getLocalPort server))
|
|
|
|
(RequestOptions.))
|
|
|
|
time-before-connect (System/currentTimeMillis)]
|
|
|
|
(is (instance? SocketTimeoutException (-> client
|
|
|
|
(.get request-options)
|
|
|
|
(.deref)
|
|
|
|
(.getError)))
|
|
|
|
"Unexpected result for get attempt")
|
|
|
|
(is (elapsed-within-range? time-before-connect 2000)
|
|
|
|
"Get attempt took significantly longer than timeout")))))
|
|
|
|
|
2015-03-20 04:25:55 +00:00
|
|
|
(deftest short-socket-timeout-persistent-clojure-test-async
|
2015-03-16 17:50:09 +00:00
|
|
|
(testing (str "socket read times out properly for clojure persistent client "
|
|
|
|
"async request with short timeout")
|
|
|
|
(with-open [client (async/create-client
|
|
|
|
{:socket-timeout-milliseconds 250})
|
|
|
|
server (ServerSocket. 0)]
|
|
|
|
(let [url (str "http://127.0.0.1:" (.getLocalPort server))
|
|
|
|
time-before-connect (System/currentTimeMillis)]
|
|
|
|
(is (instance? SocketTimeoutException
|
|
|
|
(-> @(common/get client url)
|
|
|
|
:error))
|
|
|
|
"Unexpected result for get attempt")
|
|
|
|
(is (elapsed-within-range? time-before-connect 2000)
|
|
|
|
"Get attempt took significantly longer than timeout")))))
|
|
|
|
|
|
|
|
(deftest longer-socket-timeout-test-async
|
2015-03-20 04:25:55 +00:00
|
|
|
(testing "get succeeds for async request with longer socket timeout"
|
2015-03-16 17:50:09 +00:00
|
|
|
(testlogging/with-test-logging
|
|
|
|
(testwebserver/with-test-webserver app port
|
|
|
|
(let [url (str "http://localhost:" port "/hello")]
|
|
|
|
(testing "java persistent async client"
|
|
|
|
(with-open [client (-> (ClientOptions.)
|
|
|
|
(.setSocketTimeoutMilliseconds 2000)
|
|
|
|
(Async/createClient))]
|
|
|
|
(let [response (-> client
|
|
|
|
(.get (RequestOptions. url))
|
|
|
|
(.deref))]
|
|
|
|
(is (= 200 (.getStatus response)))
|
|
|
|
(is (= "Hello, World!" (slurp (.getBody response)))))))
|
|
|
|
(testing "clojure persistent async client"
|
|
|
|
(with-open [client (async/create-client
|
|
|
|
{:socket-timeout-milliseconds 2000})]
|
|
|
|
(let [response @(common/get client url {:as :text})]
|
|
|
|
(is (= 200 (:status response)))
|
2015-09-07 10:07:26 +00:00
|
|
|
(is (= "Hello, World!" (:body response)))))))))))
|
2016-02-04 13:11:27 +00:00
|
|
|
|
|
|
|
(deftest empty-content-type-async
|
|
|
|
(testing "content-type parsing handles empty content-type"
|
|
|
|
(testlogging/with-test-logging
|
|
|
|
(testwebserver/with-test-webserver app-with-empty-content-type port
|
|
|
|
(let [url (str "http://localhost:" port "/hello")]
|
|
|
|
(testing "java persistent async client"
|
|
|
|
(with-open [client (-> (ClientOptions.)
|
|
|
|
(Async/createClient))]
|
|
|
|
(let [response (-> client
|
|
|
|
(.get (RequestOptions. url))
|
|
|
|
(.deref))]
|
|
|
|
(is (= 200 (.getStatus response))))))
|
|
|
|
(testing "clojure persistent async client"
|
|
|
|
(with-open [client (async/create-client {})]
|
|
|
|
(let [response @(common/get client url {:as :text})]
|
|
|
|
(is (= 200 (:status response)))))))))))
|