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

Interceptor refactor #301

Merged
merged 8 commits into from Dec 14, 2014

Conversation

Projects
None yet
1 participant
@ohpauleez
Member

ohpauleez commented Dec 14, 2014

Updated Interceptor API

THIS IS A BREAKING CHANGE - Version is now 0.4.0-SNAPSHOT

I usually don't do Pull-Requests for my own branches, but this is such a significant breaking change, I wanted to document it somewhere besides just the release notes (for those who work from Pedestal-master).

The problem

Pedestal's core is just a collection of Interceptors (Records), and a mechanism hook them together (into an Interceptor Chain/Path). Given that, there have always been a number of ways to create interceptors, but at the bottom of it all, was a single Record. Most developers who were comfortable working in Pedestal opted for the most direct approach (calling (interceptor ...) and (definterceptor ...)), but there were various utilities for common cases (handlers, before, after, around, middleware, etc). These utilities obfuscated the core simplicity of interceptors. This issue has been well documented on the mailing list and on issue #129

The solution

There are four parts to the solution: Put interceptor creation behind a protocol, ensure all interceptors that are created are valid at compile/creation time, improve error messaging for malformed/created interceptors, and migrate all auxiliary interceptor-creating functions into a dedicated namespace.

The new interceptor protocol is called IntoInterceptor. You should never have to interface with this directly - care has been given to capture all of the common cases for interceptor creation. The way to directly create interceptors is with the (io.pedestal.interceptor/interceptor ...) function. This function ensures correct interceptor creation and has helpful error messages when things go wrong.

The new namespace for the auxiliary functions is io.pedestal.interceptor.helpers. You will need to update the namespace for all hand-written interceptors created with these functions - before, defbefore, after, defafter, around, defaround, etc.

There is no more definterceptorfn. Creation and generation of interceptors are all driven by functions. This has two implications, and two breaking changes. Everywhere in code that previously used definterceptorfn is now just defn - you'll need to update your code. You can no longer pass bare interceptor-fns into the routes - they MUST be wrapped in parenthesis/called.
For example, consider the old, Pedestal 0.3.X code below (taken from the CSRF tests):

(defhandler terminator
  "An interceptor that creates a valid ring response and places it in
  the context, terminating the interceptor chain."
  [request]
  {:status 200 :body success-msg :headers {}})

(defafter token-sniffer
  "Relay the token to the requester behind the scenes to mimic the
   use of a conventional form with a hidden field."
  [context]
  (let [token   (get-in context [:response :session "__anti-forgery-token"])
        headers (merge {} (when token {"csrf-token" token}))]
    (assoc-in context [:response :headers] headers)))

(defroutes request-handling-routes
  [[:request-handling "csrf-test.pedestal"
    ["/anti-forgery" ^:interceptors [rm/session token-sniffer anti-forgery]
     ["/leaf" {:any [:leaf terminator]}]]]])

Look back at the defroutes - you'll see that /anti-forgery passes in two interceptorfn's, rm/session and anti-forgery. Since those are now just defns in Pedestal 0.4.X, the new routes would look like:

(defroutes request-handling-routes
  [[:request-handling "csrf-test.pedestal"
    ["/anti-forgery" ^:interceptors [(rm/session) token-sniffer (anti-forgery)]
     ["/leaf" {:any [:leaf terminator]}]]]])

Symbols that resolve to functions are always treated like handlers now. You'll also notice we didn't need to wrap token-sniffer. You only need to wrap interceptors that are defns - if you use a helper, you're all set.

ohpauleez added a commit that referenced this pull request Dec 14, 2014

@ohpauleez ohpauleez merged commit a2b36c4 into master Dec 14, 2014

1 check passed

continuous-integration/travis-ci The Travis CI build passed
Details

@ohpauleez ohpauleez deleted the interceptor-refactor branch Dec 14, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment