Newbie question about defroutes

413 views
Skip to first unread message

Ronan Dunklau

unread,
Feb 14, 2010, 9:44:43 AM2/14/10
to comp...@googlegroups.com
Hi all.

I'm trying to learn compojure, and i must be missing a point: how can I
"compose" a route from multiple routes ? I have tried the following (among
other things), but I keep gettin NPE when GETting "/grou". Any advice ?


(defn hello-world [grou]
(html [:h1 (str "Hello world " grou)]))

(defroutes hello
(GET "/"
(hello-world 1)))

(defroutes hello2
(GET "/grou/"
(hello-world 2)))


(decorate hello
(with-headers {"myHeader" "myHeaderValue"})
(with-dojo-base-page "WebApp/dojo/"))


(defroutes allroutes
hello
hello2)

(defservice allroutes)

(def my-server
(jetty-server {:port 8080}
"/*" (servlet allroutes)))

I also tried to call defservice on each indivual route and defining mapping
them to separate servlets....

Thank you !

--
Ronan Dunklau

signature.asc

Nicolas Buduroi

unread,
Feb 14, 2010, 11:44:56 AM2/14/10
to Compojure
You're just having a small problem in the definition of allroutes:

(defroutes allroutes
hello
hello2)

should be

(defroutes allroutes
(GET "/" hello)
(GET "/grou/" hello2))

For this example, it doesn't add much, but nested routes are great for
separating routes definitions. e. g.:

(defroutes blog
(GET "/" ())
(GET "/new" (new-post))
(GET "/edit" (edit-post)))

(defroutes project
(GET "/" ())
(GET "/new" (new-project))
(GET "/edit" (edit-project)))

(defroutes site
(GET "/blog/*" blog)
(GET "/projects/*" project))

I think there was a function or macro to do what you asked for though,
I just don't remember what it is and don't know if it still exists.

>  signature.asc
> < 1KViewDownload

Ronan Dunklau

unread,
Feb 14, 2010, 12:17:32 PM2/14/10
to comp...@googlegroups.com, Nicolas Buduroi
Thanks, it now works as intended.

I guess I was a bit confused by a blog post which provided similar examples.
With that particular point solved, I can go back to learning compojure !

--
Ronan Dunklau

signature.asc

James Reeves

unread,
Feb 14, 2010, 1:15:34 PM2/14/10
to Compojure
On Feb 14, 4:44 pm, Nicolas Buduroi <nbudu...@gmail.com> wrote:
> You're just having a small problem in the definition of allroutes:
>
> (defroutes allroutes
>            hello
>            hello2)
>
> should be
>
> (defroutes allroutes
>            (GET "/" hello)
>            (GET "/grou/" hello2))

Actually, both forms should work. What may be tripping up Ronan is
that "/grou/" and "/grou" are not equivalent URIs.

It's important to realise that the GET macro is just a way of
generating a Ring handler function that returns nil if the request
doesn't match, or the user response if it does.

The defroutes macro defines a function that chains these individual
route functions together. The request map is passed to each function
in turn, until a non-nil response is returned.

You could even just write your own route functions directly:

(defroutes example
(fn [request]
(if (and (= (:request-method request) :get)
(= (:uri request) "/bar")
{:status 200
:headers {}
:body "Foobar!"})))

But because this is usually very verbose, the GET macro is probably
more suitable:

(defroutes example
(GET "/bar" "Foobar!"))

- James

jarik

unread,
Feb 15, 2010, 6:11:27 AM2/15/10
to Compojure
> > (defroutes allroutes
> >            (GET "/" hello)
> >            (GET "/grou/" hello2))
>
> Actually, both forms should work. What may be tripping up Ronan is
> that "/grou/" and "/grou" are not equivalent URIs.
Sometimes such URIs have to be equivalent. There's solution with
custom decorator:
(defn append-trailing-slash [handler]
(fn [request]
(let [response (handler request)]
(if response
response
(if (.endsWith (:uri request) "/")
{:status 404 :headers {}}
{:status 301 :body "Moved Permanently" :headers {"Location" (str
(:uri request) "/")}})))))

and than:
(decorate allroutes append-trailing-slash)

PS: There's ignore-trailing-slash in compojure, but when you write <a
href="100001/">Object's Id</a> typing /grou you'll get href="/100001/"
and typing /grou/ you'll get href="/grou/100001/". And append-trailing-
slash does not have this issue, so IMO it's much comfortable

Chas Emerick

unread,
Feb 15, 2010, 7:00:55 AM2/15/10
to comp...@googlegroups.com
FWIW, you can easily define a path that is insensitive to trailing
slashes using #"/grou/?". I'd certainly prefer that to a middleware
solution, as the effect is important (at least w.r.t. restful
guidelines) and the locality of using a regex on the affected paths
helps to remind one what's going on in each case.

- Chas

Ronan Dunklau

unread,
Feb 15, 2010, 7:03:44 AM2/15/10
to comp...@googlegroups.com
Thanks for these suggestions.

I'll try to apply these as soon as i get some time.

I will also test to map two different servlets to different URIs, since bad URI definition seems to be the root of my problems.

--
Ronan Dunklau



2010/2/15 jarik <jar...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "Compojure" group.
To post to this group, send email to comp...@googlegroups.com.
To unsubscribe from this group, send email to compojure+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/compojure?hl=en.


Reply all
Reply to author
Forward
0 new messages