2010-05-10 24 views
6

J'essaye de construire un site web simple en utilisant Clojure/Compojure et je veux appliquer un filtre de servlet à la requête/réponse (ie une instance javax.servlet.Filter standard) .Utilisation d'un javax.servlet.Filter avec Compojure

par exemple. si le code source est en cours:

(defroutes my-app 
    (GET "/*" 
    (html [:h1 "Hello Foo!!"])) 
) 

Je voudrais ajouter un filtre comme ceci:

(defroutes my-app 
    (GET "/*" 
    (FILTER my-filter-name 
     (html [:h1 "Hello Foo!!"]))) 
) 

Où mon-nom-filtre est une instance arbitraire de javax.servlet.Filter.

Une idée de comment le faire efficacement et élégamment?

+3

Voulez-vous appliquer votre filtre à tous les itinéraires ou seulement certains? Dans le premier cas, il peut être plus facile de placer le filtre au-dessus de Ring/Compojure, au niveau du servlet. Dans le second cas, vous devez écrire (avec reify ou proxy) un adaptateur qui transforme un filtre en middleware. – cgrand

+0

Merci beaucoup. Je voudrais faire la seconde mais cela ne semble pas possible car les paramètres de requête/réponse dont le filtre a besoin ne sont pas transmis en tant que paramètres au système de middleware. J'essaye la première - posterai une réponse si je la fais fonctionner! – mikera

+3

Pour effectuer la seconde, vous devez également créer des objets qui implémentent HttpServletRequest/Response au-dessus des mappes de requête/réponse. Ou pour utiliser l'implémentation existante (par exemple http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/mock/web/MockHttpServletRequest.html) mais je pense qu'il est plus simple de les implémenter avec reify qu'avec traiter avec un objet fantaisie étatful - comme Rich Hickey dit "Ces faux objets, ils se moquent de vous"! – cgrand

Répondre

8

Ok, j'ai maintenant ce travail! Merci cgrand pour les pointeurs dans la bonne direction!

Ma solution impliquait la création de proxys pour une servlet filtrée et une chaîne de filtres. Code ci-dessous pour toute personne intéressée .....

(def pass-through-filter 
    (proxy [javax.servlet.Filter] [] 
    (doFilter 
     [request response #^javax.servlet.FilterChain filterchain] 
     (do 
     (.doFilter filterchain request response))))) 


(defn filter-chain 
    [#^javax.servlet.Servlet servlet] 
    (proxy [javax.servlet.FilterChain] [] 
    (doFilter 
     [request response] 
     (.service servlet request response)))) 

(defn filtered-servlet 
    [#^javax.servlet.Filter servlet-filter handler] 
    (let [#^javax.servlet.Servlet base-servlet (servlet handler) 
     the-filter-chain (filter-chain base-servlet)] 
    (proxy [javax.servlet.http.HttpServlet] [] 
     (service 
      [request response] 
      (.doFilter servlet-filter request response the-filter-chain)) 
     (init 
       [config] 
       (.init base-servlet config))))) 

(defroutes my-app 
    (GET "/*" 
    (html 
      [:h1 "Hello Foo!!"])) 
    (ANY "*" 
    [404 "Page not found"]) 
) 


(run-server {:port 80} 
    "/*" (filtered-servlet pass-through-filter my-app)) 
+2

Vous n'avez pas besoin d'ajouter votre définition de filtre au fichier web.xml? – Chiron