2011-12-05 39 views
7

Tal vez solo soy un idiota, pero no puedo configurar una coincidencia para una barra inclinada optativa en Clojure.Compojure regex para hacer coincidir una barra inclinada

lein repl 
REPL started; server listening on localhost port 47383 
user=> (use 'ring.mock.request 'clout.core) 
nil 
user=> (route-matches "/article/" (request :get "/article/")) 
{} 
user=> (route-matches "/article/?" (request :get "/article")) 
nil 
user=> (route-matches "/article/?" (request :get "/article/")) 
nil 
user=> (route-matches #"/article/?" (request :get "/article/")) 
java.lang.IllegalArgumentException: No implementation of method: :route-matches of protocol: #'clout.core/Route found for class: java.util.regex.Pattern (NO_SOURCE_FILE:0) 

¿Qué expresiones regulares puedo usar para que coincida con una barra diagonal opcional en Compojure?

Respuesta

5

La cadena de ruta esperada por clout como primer argumento para route-matches no es una expresión regular, sino una cadena que puede contener palabras clave y el comodín *.

Creo que clout no admite de forma nativa la definición de rutas que ignoran una barra inclinada. Podría resolver el problema con una función de middleware que elimine las barras diagonales. Las siguientes funciones fueron tomadas de una versión anterior del código fuente compojure (antes de la gran refactorización), no pude averiguar si se mudaron a un lugar nuevo. Aquí está el original commit que introdujo estas funciones.

(defn with-uri-rewrite 
    "Rewrites a request uri with the result of calling f with the 
    request's original uri. If f returns nil the handler is not called." 
    [handler f] 
    (fn [request] 
    (let [uri (:uri request) 
      rewrite (f uri)] 
     (if rewrite 
     (handler (assoc request :uri rewrite)) 
     nil)))) 

(defn- uri-snip-slash 
    "Removes a trailing slash from all uris except \"/\"." 
    [uri] 
    (if (and (not (= "/" uri)) 
      (.endsWith uri "/")) 
    (chop uri) 
    uri)) 

(defn ignore-trailing-slash 
    "Makes routes match regardless of whether or not a uri ends in a slash." 
    [handler] 
    (with-uri-rewrite handler uri-snip-slash)) 
+0

Ah, yo estaba esperando para evitar el middleware. Si es la única manera, entonces OK. –

1

Aquí hay una versión condensada del middleware sin dependencias: ediciones fix

(defn with-ignore-trailing-slash [handler] (fn [request] 
    (let [uri  (request :uri) 
     clean-uri (if (and (not= "/" uri) (.endsWith uri "/")) 
        (subs uri 0 (- (count uri) 1)) 
        uri)] 
    (handler (assoc request :uri clean-uri))))) 

Bug bienvenida.

0

Para aquellos que buscan una solución aún más comprimido :)

(defn- with-ignore-trailing-slash [handler] 
    (fn [request] 
    (let [uri (request :uri) 
      clean-uri (str/replace uri #"^(.+?)/+$" "$1")] 
     (handler (assoc request :uri clean-uri))))) 
Cuestiones relacionadas