From 1531c30f8b3a2ad5001dfca1425578210c628782 Mon Sep 17 00:00:00 2001 From: Jonas Enlund Date: Sun, 18 Oct 2015 22:55:12 +0300 Subject: [PATCH] Fix defresource so it no longer implicitly binds 'request' --- CHANGES.markdown | 12 +++++----- src/liberator/core.clj | 47 +++++++++++++++++++-------------------- test/test_defresource.clj | 8 ++++++- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/CHANGES.markdown b/CHANGES.markdown index bf3a96f..7ddc540 100644 --- a/CHANGES.markdown +++ b/CHANGES.markdown @@ -2,6 +2,8 @@ # Unreleased +* The `defresource` macro no longer implicitly binds `request`. + * Values can be added to the context at the beginning of the execution flow using the :initialize-context action. @@ -30,7 +32,7 @@ ## Bugs fixed * #162 This release actually contains the changes announced for 0.12.1 - Due to whatever reason the revision in clojars did not match + Due to whatever reason the revision in clojars did not match what was tagged as 0.12.1 in the git repository. # New in 0.12.1 @@ -105,14 +107,14 @@ location from context key :location * Extractor for graphivz dot file that reads core.clj * Bump hiccup dependency to 1.0.2 -* Add can-put-to-missing? +* Add can-put-to-missing? * Fix representation render-map-csv * Make liberator build with lein 2.0.0RC1 (manage dependencies) * Drop unnecessary methods from Representation * Dispatch Representation on MapEquivalence and Sequential which increased robustness * Fixes to HTML Table representation (missing tr) -* Render Clojure Representation using \*print-dup\* +* Render Clojure Representation using \*print-dup\* * Support "application/edn" representation ## Bugs fixed @@ -129,12 +131,12 @@ * Include olympics example data with source -## Bugs fixes +## Bugs fixes * Handle line-break and whitespace in Accept headers * Ignore case in character set negotiation * #12 String representation sets character set * #9 Missing media-type for "hello george" example -* #11 +* #11 * #14 Use newer org.clojure:data.csv # New in 0.7.0 diff --git a/src/liberator/core.clj b/src/liberator/core.clj index 05237f5..0e3dcab 100644 --- a/src/liberator/core.clj +++ b/src/liberator/core.clj @@ -8,10 +8,10 @@ (:import (javax.xml.ws ProtocolException))) (defmulti coll-validator - "Return a function that evaluaties if the give argument - a) is contained in a collection + "Return a function that evaluaties if the give argument + a) is contained in a collection b) equals an argument - c) when applied to a function evaluates as true" + c) when applied to a function evaluates as true" (fn [x] (cond (coll? x) :col (fn? x) :fn))) @@ -23,10 +23,10 @@ (defmethod coll-validator :default [x] (partial = x)) -(defn console-logger [category values] +(defn console-logger [category values] #(apply println "LOG " category " " values)) -(def ^:dynamic *loggers* nil) +(def ^:dynamic *loggers* nil) (defmacro with-logger [logger & body] `(binding [*loggers* (conj (or *loggers* []) ~logger)] @@ -94,7 +94,7 @@ `(defn ~name [~'context] (decide ~(keyword name) ~test ~then ~else ~'context))) -(defmacro defdecision +(defmacro defdecision ([name then else] (defdecision* name nil then else)) ([name test then else] @@ -282,14 +282,14 @@ (defhandler handle-precondition-failed 412 "Precondition failed.") -(defdecision if-match-star-exists-for-missing? +(defdecision if-match-star-exists-for-missing? if-match-star handle-precondition-failed method-put?) (defhandler handle-not-modified 304 nil) -(defdecision if-none-match? +(defdecision if-none-match? #(#{ :head :get} (get-in % [:request :request-method])) handle-not-modified handle-precondition-failed) @@ -297,7 +297,7 @@ (defdecision put-to-existing? (partial =method :put) conflict? multiple-representations?) -(defdecision post-to-existing? (partial =method :post) +(defdecision post-to-existing? (partial =method :post) post! put-to-existing?) (defhandler handle-accepted 202 "Accepted") @@ -322,7 +322,7 @@ handle-not-modified) (defdecision if-modified-since-valid-date? - (fn [context] + (fn [context] (if-let [date (parse-http-date (get-in context [:request :headers "if-modified-since"]))] {::if-modified-since-date date})) modified-since? @@ -341,7 +341,7 @@ if-none-match? if-modified-since-exists?) -(defdecision if-none-match-star? +(defdecision if-none-match-star? #(= "*" (get-in % [:request :headers "if-none-match"])) if-none-match? etag-matches-for-if-none?) @@ -360,7 +360,7 @@ if-none-match-exists?) (defdecision if-unmodified-since-valid-date? - (fn [context] + (fn [context] (when-let [date (parse-http-date (get-in context [:request :headers "if-unmodified-since"]))] {::if-unmodified-since-date date})) unmodified-since? @@ -377,7 +377,7 @@ if-unmodified-since-exists? handle-precondition-failed) -(defdecision if-match-star? +(defdecision if-match-star? if-match-star if-unmodified-since-exists? etag-matches-for-if-match?) (defdecision if-match-exists? (partial header-exists? "if-match") @@ -390,7 +390,7 @@ (defhandler handle-not-acceptable 406 "No acceptable resource available.") -(defdecision encoding-available? +(defdecision encoding-available? (fn [ctx] (when-let [encoding (conneg/best-allowed-encoding (get-in ctx [:request :headers "accept-encoding"]) @@ -425,7 +425,7 @@ (defdecision language-available? #(try-header "Accept-Language" (when-let [lang (conneg/best-allowed-language - (get-in % [:request :headers "accept-language"]) + (get-in % [:request :headers "accept-language"]) ((get-in context [:resource :available-languages]) context))] (if (= lang "*") true @@ -437,8 +437,8 @@ (defn negotiate-media-type [context] (try-header "Accept" - (when-let [type (conneg/best-allowed-content-type - (get-in context [:request :headers "accept"]) + (when-let [type (conneg/best-allowed-content-type + (get-in context [:request :headers "accept"]) ((get-in context [:resource :available-media-types] (constantly "text/html")) context))] {:representation {:media-type (conneg/stringify type)}}))) @@ -452,7 +452,7 @@ ;; client accepts all media types" [p100] ;; in this case we do content-type negotiation using */* as the accept ;; specification - (if-let [type (liberator.conneg/best-allowed-content-type + (if-let [type (liberator.conneg/best-allowed-content-type "*/*" ((get-in context [:resource :available-media-types]) context))] [false {:representation {:media-type (liberator.conneg/stringify type)}}] @@ -583,7 +583,7 @@ (initialize-context {:request request :resource (map-values make-function (merge default-functions kvs)) :representation {}}) - + (catch ProtocolException e ; this indicates a client error {:status 400 :headers {"Content-Type" "text/plain"} @@ -607,11 +607,11 @@ kvs (rest kvs)] ;; Rather than call resource, create anonymous fn in callers namespace for better debugability. `(defn ~name [~@args] - (fn [~'request] - (run-resource ~'request (get-options (list ~@kvs)))))) + (fn [request#] + (run-resource request# (get-options (list ~@kvs)))))) `(def ~name - (fn [~'request] - (run-resource ~'request (get-options (list ~@kvs))))))) + (fn [request#] + (run-resource request# (get-options (list ~@kvs))))))) (defn by-method "returns a handler function that uses the request method to @@ -623,4 +623,3 @@ :delete \"Entity was deleted successfully.\"})" [map] (fn [ctx] ((make-function (get map (get-in ctx [:request :request-method]) ctx)) ctx))) - diff --git a/test/test_defresource.clj b/test/test_defresource.clj index 605c432..0bdfa9b 100644 --- a/test/test_defresource.clj +++ b/test/test_defresource.clj @@ -52,6 +52,9 @@ (parametrized-config media-type) :handle-ok (fn [_] (format "The text is %s" txt))) +(defresource non-anamorphic-request [request] + :handle-ok (str request)) + (facts "about defresource" (fact "its simple form should behave as it always has" (without-param {:request-method :get}) @@ -77,7 +80,10 @@ => {:headers {"Content-Type" "text/plain;charset=UTF-8"}, :body "with-service-available?-multimethod", :status 200}) (fact "should allow multi methods as decisions alternate path" (with-decisions-multimethod {:request-method :get :service-available? :not-available}) - => {:headers {"Content-Type" "text/plain;charset=UTF-8"}, :body "Service not available.", :status 503})) + => {:headers {"Content-Type" "text/plain;charset=UTF-8"}, :body "Service not available.", :status 503}) + (fact "should allow 'request' to be used as a resource parameter name, this was a bug at a time." + (:body ((non-anamorphic-request "test") {:request-method :get})) + => "test")) (def fn-with-options