From f45fc56e557e73cbdabf1e8fd620ca498fed319d Mon Sep 17 00:00:00 2001 From: func Date: Sun, 27 Nov 2016 15:12:58 +0900 Subject: [PATCH 1/3] Following the latest stable dependencies. --- project.clj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/project.clj b/project.clj index ed99f50..fab4c9e 100644 --- a/project.clj +++ b/project.clj @@ -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"]]) From 930ffc6055f692bc042809367a23186c3d326650 Mon Sep 17 00:00:00 2001 From: func Date: Sun, 27 Nov 2016 19:02:49 +0900 Subject: [PATCH 2/3] Fix: We should consider of ExceptionInfo which is thrown from clj-http. --- src/oauth/client.clj | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/oauth/client.clj b/src/oauth/client.clj index 2832f33..f7949ff 100644 --- a/src/oauth/client.clj +++ b/src/oauth/client.clj @@ -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] @@ -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]] @@ -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. @@ -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)) From bf24041e5e5f25685284d87f5d0b7193c991eeef Mon Sep 17 00:00:00 2001 From: func Date: Mon, 28 Nov 2016 02:04:27 +0900 Subject: [PATCH 3/3] Fix, Add: Corresponding to fix oauth.client/post-request-body-decoded. --- test/oauth/client_twitter_test.clj | 81 ++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/test/oauth/client_twitter_test.clj b/test/oauth/client_twitter_test.clj index 620b78d..fe1b6ee 100644 --- a/test/oauth/client_twitter_test.clj +++ b/test/oauth/client_twitter_test.clj @@ -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 @@ -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."}