Skip to content

Instantly share code, notes, and snippets.

@KirinDave
Created October 26, 2010 21:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KirinDave/47de41199aabd74df3c0 to your computer and use it in GitHub Desktop.
Save KirinDave/47de41199aabd74df3c0 to your computer and use it in GitHub Desktop.
(ns clothesline.protocol.graph
(:use [clothesline.protocol
syntax
response-helpers
graph-helpers
test-helpers])
(:require [clothesline [service :as s]]))
(protocol-machine
(def start #'b13)
(defstate b13
"Check if service has been made unavailable. Return status 503 if not."
:test (call-on-handler s/service-available?)
:yes b12
:no (stop-response 503))
(defstate b12
:test (constantly true)
:yes b11
:no (stop-response 501))
(defstate b11
:test (call-on-handler s/uri-too-long?)
:no b10
:yes (stop-response 414))
(defstate b10
:test (fn [{:keys [handler request graphdata]}]
((getres (s/allowed-methods handler request graphdata))
(:request-method request)))
:yes b9
:no (stop-response 501))
(defstate b9
:test (call-on-handler s/malformed-request?)
:no b8
:yes (stop-response 400))
(defstate b8
:test (call-on-handler s/authorized?)
:yes b7
:no (stop-response 401))
(defstate b7
:test (call-on-handler s/forbidden?)
:yes (stop-response 403)
:no b6)
(defstate b6
:test (call-on-handler s/valid-content-headers?)
:yes b5
:no (stop-response 501))
(defstate b5
:test (call-on-handler s/known-content-type?)
:yes b4
:no (stop-response 415))
(defstate b4
:test (call-on-handler s/valid-entity-length?)
:yes b3
:no (stop-response 413))
(defstate b3
:body (fn [{:keys [handler request graphdata] :as args}]
(if (= :options (:request-method request))
(let [options-headers (or (getres (s/options handler request graphdata)) {})]
{:status 200
:body ""
:headers options-headers})
(c3 args))))
(defstate c3
:test (request-header-exists? "accept")
:yes c4
:no d4)
(defstate c4
"Map the accept handler through and set it."
:test (fn [{:keys [handler request graphdata]}]
(let [available-handlers (getres (s/content-types-provided handler
request
graphdata))
chosen (map-accept-header request "accept" available-handlers)]
(if chosen
(annotated-return true {:annotate {:content-handler chosen}})
false)))
:yes d4
:no (stop-response 406))
(defstate d4
:test (request-header-exists? "accept-language")
:yes d5
:no e5)
(defstate d5
"Currently ignored. TODO: Fix me!"
:test (constantly true)
:yes e5
:no (stop-response 406))
(defstate e5
:test (request-header-exists? "accept-charset")
:yes f6 ; TODO: Re-enable accept-charset!
:no f6)
(defstate e6
"Check and select a supported character set"
:test (fn [{:keys [handler request graphdata]}]
(let [available-handlers (getres (s/charsets-provided handler
request
graphdata))
chosen (map-accept-header request "accept-charset" available-handlers)]
(if chosen
(annotated-return true {:annotate {:content-charset chosen}})
false)))
:yes f6
:no (stop-response 406))
(defstate f6
"Check if accept-encoding header is present"
:test (request-header-exists? "accept-encoding")
:yes g7 ; TODO: Re-enable accept-encoding
:no g7)
(defstate f7
:test (fn [{:keys [handler request graphdata]}]
(let [available-handlers (getres (s/charsets-provided handler
request
graphdata))
chosen (map-accept-header request "accept-encoding" available-handlers)]
(if chosen
(annotated-return true {:annotate {:content-encoding chosen}})
false)))
:yes g7
:no (stop-response 406))
(defstate g7
:test (call-on-handler s/resource-exists?)
:yes g8
:no h7)
; The graph bifurcates significantly here. Taking the path down
; g8 leads us towards serving a resource. Taking the path down
; h7 leads towards various failure responses.
; Resource exists, move towards serving it
(defstate g8
:test (request-header-exists? "if-match")
:yes g9
:no h10)
(defstate g9
:test (fn [_ request _]
(let [if-match-value (get (:headers request) "if-match")]
(= "*" if-match-value)))
:yes h10
:no g11)
(defstate g11
:test (fn [{:keys [request handler graphdata]}]
(let [if-match-value (hv request "if-match")
[etag ann] (getres (s/generate-etag handler request graphdata))]
(annotated-return (= if-match-value etag) ann)))
:yes h10
:no (stop-response 412))
(defstate h10
:test (request-header-exists? "if-unmodified-since")
; :yes h11 ; TODO: Re-enable this
:yes i12 ; TODO: Un-ignore the date headers.
:no i12)
(defstate i12
:test (request-header-exists? "if-none-match")
:yes i13
:no l13)
(defstate i13
:test (request-header-is? "if-none-match" "*")
:yes j18
:no k13)
(defstate k13
:test (fn [{:keys [request handler graphdata]}]
(let [[v ann] (getresann (s/generate-etag handler request graphdata))]
(annotated-return (= v (hv request "if-none-match"))
ann)))
:yes j18
:no l13)
(defstate j18
:test (request-method-is? :get)
:yes (stop-response 304)
:no (stop-response 412))
(defstate l13
:test (request-header-exists? "if-modified-since")
:yes m16 ; TODO: un-ignore date headers, this should go to L14
:no m16)
(defstate m16
:test (request-method-is? :delete)
:no n16
:yes m20)
(defstate m20
:test (call-on-handler s/delete-resource)
:yes o20
:no (stop-response 202))
(defstate o20
:test (fn [{:keys [request handler graphdata]}]
(or (:content-provider graphdata)
(:body graphdata)))
:yes o18
:no (stop-response 204))
(defstate o18
:test (call-on-handler s/multiple-choices?)
:yes (stop-response 300)
:no (normal-response 200)
)
(defstate n16
:test (request-method-is? :post)
:yes n11
:no o16)
(defstate o16
:test (request-method-is? :put)
:yes o14
:no o18)
(defstate o14
:test (call-on-handler s/conflict?)
:yes (stop-response 409)
:no p11)
;; Back up to failure states
(defstate h7
:test (request-header-is? "if-match" "*")
:yes (stop-response 412)
:no i7)
(defstate i7
:test (request-method-is? :put)
:yes i4
:no k7)
(defstate k7
:test (call-on-handler s/previously-existed?)
:yes k5
:no l7)
(defstate k5
:test (fn [{:keys [handler request graphdata]}]
(let [[redirect-to ann] (getresann (s/moved-permanently? handler
request
graphdata))]
(if redirect-to
(annotated-return true (merge ann {:headers {"Location", redirect-to}}))
(annotated-return false ann))))
:yes (normal-response 301)
:no l5)
(defstate i4
:test (fn [{:keys [handler request graphdata]}]
(let [[redirect-to ann] (getresann (s/moved-permanently? handler
request
graphdata))]
(if redirect-to
(annotated-return true (merge ann {:headers {"Location", redirect-to}}))
(annotated-return false ann))))
:yes (normal-response 301)
:no p3)
(defstate l5
:test (fn [{:keys [handler request graphdata]}]
(let [[redirect-to ann] (getresann (s/moved-temporarily? handler
request
graphdata))]
(if redirect-to
(annotated-return true (merge ann {:headers {"Location", redirect-to}}))
(annotated-return false ann))))
:yes (normal-response 307)
:no m5)
(defstate l7
:test (request-method-is? :post)
:no (stop-response 404)
:yes m7)
(defstate m7
:test (call-on-handler s/allow-missing-post?)
:yes n11
:no (stop-response 404))
(defstate m5
:test (request-method-is? :post)
:no (stop-response 410)
:yes n5) ; Identical to m7
(defstate n5
:test (call-on-handler s/allow-missing-post?)
:no (stop-response 410)
:yes n11)
(defstate n11
; TODO, fix this so it does what it's supposed to.
:test (fn [{:keys [handler request graphdata]}]
(let [is-redirect false]
(if (s/post-is-create? handler request graphdata)
(let [cpath (s/create-path handler request graphdata)]
false)
(do (s/process-post handler request graphdata)
false))))
:yes (normal-response 303)
:no p11)
(defstate p11
:test (response-header-set? "Location")
:yes (normal-response 201)
:no o20)
(defstate p3
:test (call-on-handler s/conflict?)
:yes (stop-response 409)
:no p11)
(defstate temp-end
:test (constantly (annotated-return false {:annotate {:fart true}
:headers {"fart" "true"}}))
:yes :respond
:no {:status 500, :body "Epic fail."})
) ; Protocol machine v3.
at clojure.core$apply.invoke(core.clj:544)
at clojure.core$use.doInvoke(core.clj:4880)
at clojure.lang.RestFn.invoke(RestFn.java:422)
at clothesline.core$loading__4410__auto__.invoke(core.clj:1)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:2906)
... 26 more
Caused by: java.lang.IllegalStateException: Var clothesline.protocol.graph/b13 is unbound.
at clojure.lang.Var.deref(Var.java:142)
at clojure.lang.Var.get(Var.java:133)
at clothesline.protocol.graph__init.load(Unknown Source)
at clothesline.protocol.graph__init.<clinit>(Unknown Source)
... 67 more
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment