Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corresponding exceptions from clj-http. #54

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
:url "https://opensource.org/licenses/BSD-2-Clause"
:distribution :repo}
:description "OAuth support for Clojure"
:dependencies [[org.clojure/clojure "1.7.0"]
[commons-codec/commons-codec "1.8"]
[org.bouncycastle/bcprov-jdk15on "1.54"]
[org.bouncycastle/bcpkix-jdk15on "1.54"]
[clj-http "2.0.1"]])
:dependencies [[org.clojure/clojure "1.8.0"]
[commons-codec/commons-codec "1.10"]
[org.bouncycastle/bcprov-jdk15on "1.55"]
[org.bouncycastle/bcpkix-jdk15on "1.55"]
[clj-http "3.4.1"]])
33 changes: 21 additions & 12 deletions src/oauth/client.clj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
(defrecord #^{:doc "OAuth consumer"}
Consumer [key secret request-uri
access-uri authorize-uri signature-method])

(defn make-consumer
"Make a consumer struct map."
[key secret request-uri access-uri authorize-uri signature-method]
Expand Down Expand Up @@ -54,14 +55,6 @@ to approve the Consumer's access to their account. A map of extra parameters may
[(keyword (sig/url-decode k)) (sig/url-decode v)]))
(split s #"&")))))

(defn- check-success-response [m]
(let [code (:status m)]
(if (or (< code 200)
(>= code 300))
(throw (new Exception (str "Got non-success code: " code ". "
"Content: " (:body m))))
m)))

(defn build-request
"Construct request from prepared paramters."
[oauth-params & [form-params]]
Expand All @@ -71,10 +64,25 @@ to approve the Consumer's access to their account. A map of extra parameters may
(when form-params {:form-params form-params}))]
req))

(defn post-request-body-decoded [url & [req]]
(form-decode
(:body (check-success-response
(httpclient/post url req)))))
(defn post-request-body-decoded
"Get a response from token providers, then return a response map which decoded its body.
Throws:
clojure.lang.ExceptionInfo (Extended RuntimeException)
When a response from its token provider is returned with status code 4xx or 3xx, clj-http will throw this exception to wrap its actual response body.
If you will use this function with ExceptionInfo:

(try
;; Consider do-something is including the post-request-body-decoded function.
(do-something ...)
(catch ExceptionInfo e
(some-error-handler (ex-data e))))

But this code should be used in the application side because ExceptionInfo is RuntimeException. Otherwise means that ExceptionInfo thrown from clj-http has been replaced to other exceptions by other libraries side. We should consider it is not so good thing."
[url & [req]]
(let [res (httpclient/post url req)]
(update res
:body
(form-decode (:body res)))))

(defn credentials
"Return authorization credentials needed for access to protected resources.
Expand Down Expand Up @@ -147,6 +155,7 @@ Authorization HTTP header or added as query parameters to the request."
unsigned-oauth-params
nil
token-secret)))))

(defn build-xauth-access-token-request
([consumer username password nonce timestamp]
(build-xauth-access-token-request consumer nil username password nonce timestamp))
Expand Down
81 changes: 78 additions & 3 deletions test/oauth/client_twitter_test.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
(ns oauth.client-twitter-test
(:refer-clojure :exclude [key])
(:require [oauth.client :as oc])
(:require [oauth.client :as oc]
[oauth.signature :refer [oauth-params signature-methods]])
(:use clojure.test)
(:import [clojure.lang ExceptionInfo])
(:load "twitter_keys"))

(def consumer (oc/make-consumer key
Expand All @@ -13,8 +15,81 @@
(deftest
#^{:doc "Test requesting a token from Twitter.
Considered to pass if no exception is thrown."}
request-token
(oc/request-token consumer))
request-token-success-test
(is (= 200
(:status (oc/request-token consumer)))
"Twitter has regarded your application as web application.")
(is (= 200
(:status (oc/request-token consumer "http://localhost/")))
"Twitter has regarded your application as desktop application."))

(deftest
^{:doc "Test requesting a token from Twitter.
Considered to pass if some exception is thrown."}
request-token-error-test
(testing "When consumer has not been passed."
(is (thrown-with-msg? ExceptionInfo
#"clj-http: status 400"
(oc/request-token nil))
"Calling request_token has been passed but header has not set.")
(is (thrown-with-msg? ExceptionInfo
#"clj-http: status 400"
(oc/request-token nil "http://localhost/"))
"Calling request_token has been passed but header has not set."))
(testing "When consumer is passed but oauth_timestamp is invalid. (timestamp = -1)"
(with-redefs [oauth-params (fn
([consumer nonce _]
{:oauth_consumer_key (:key consumer)
:oauth_signature_method (sig/signature-methods (:signatue-method consumer))
:oauth_timestamp -1
:oauth_nonce nonce
:oauth_version "1.0"})
([consumer nonce _ token]
(assoc (oauth-params consumer nonce nil)
:oauth_token token))
([consumer nonce _ token verifier]
(assoc (oauth-params consumer nonce nil token)
:oauth_verifier verifier)))]
(is (thrown-with-msg? ExceptionInfo
#"clj-http: status 401"
(oc/request-token consumer))
"oauth_timestamp has been passed but is invalid.")
(is (thrown-with-msg? ExceptionInfo
#"clj-http: status 401"
(oc/request-token consumer "http://localhost/"))
"oauth_timestamp has been passed but is invalid.")))
(testing "When consumer key, Consumer secret or both is incorrect:"
(let [request-uri "https://api.twitter.com/oauth/request_token"
access-uri "https://api.twitter.com/oauth/access_token"
authorize-uri "https://api.twitter.com/oauth/authorize"
signature-method :hmac-sha1]
(is (thrown-with-msg? ExceptionInfo
#"clj-http: status 401"
(oc/request-token (oc/make-consumer nil
nil
request-uri
access-uri
authorize-uri
signature-method)))
"Request Token has been responded but Consumer Key and Consumer Secret are nil.")
(is (thrown-with-msg? ExceptionInfo
#"clj-http: status 401"
(oc/request-token (oc/make-consumer key
nil
request-uri
access-uri
authorize-uri
signature-method)))
"Request Token has been responded but Consumer Secret is nil.")
(is (thrown-with-msg? ExceptionInfo
#"clj-http: status 401"
(oc/request-token (oc/make-consumer nil
secret
request-uri
access-uri
authorize-uri
signature-method)))
"Request Token has been responded but Consumer Key is nil."))))

(deftest
#^{:doc "Considered to pass if no exception is thrown."}
Expand Down