2011-12-05 9 views
7

Forse sono solo un idiota, ma non riesco a impostare una corrispondenza per una barra finale opzionale in Clojure.Espressione regolare di Compojure per la corrispondenza di una barra finale

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) 

Quale regex posso utilizzare per abbinare una barra finale opzionale in Compojure?

risposta

5

La stringa di percorso prevista da clout come primo argomento su route-matches non è un'espressione regolare, ma una stringa che può contenere parole chiave e il carattere jolly *.

Credo che clout non supporti nativamente la definizione di route che ignorano una barra finale. È possibile risolvere il problema con una funzione middleware che rimuove le barre finali. Le seguenti funzioni sono state prese da una vecchia versione del codice sorgente compojure (prima del grande refactoring), non ho potuto scoprire se si sono spostati in un nuovo luogo. Ecco lo original commit che ha introdotto queste funzioni.

(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, speravo di evitare il middleware. Se è l'unico modo però, allora OK. –

1

Ecco una versione condensata della middleware senza dipendenze: modifiche

(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 fix benvenuto.

0

Per chi cerca una soluzione ancora più compressi :)

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