smallseo.info

compojure

A concise routing library for Ring/Clojure

Compojure routes with different middleware

I'm currently writing an API in Clojure using Compojure (and Ring and associated middleware).

I'm trying to apply different authentication code depending on the route. Consider the following code:

(defroutes public-routes
  (GET "/public-endpoint" [] ("PUBLIC ENDPOINT")))

(defroutes user-routes
  (GET "/user-endpoint1" [] ("USER ENDPOINT 1"))
  (GET "/user-endpoint2" [] ("USER ENDPOINT 1")))

(defroutes admin-routes
  (GET "/admin-endpoint" [] ("ADMIN ENDPOINT")))

(def app
  (handler/api
    (routes
      public-routes
      (-> user-routes
          (wrap-basic-authentication user-auth?)))))
      (-> admin-routes
          (wrap-basic-authentication admin-auth?)))))

This doesn't work as expected because wrap-basic-authentication indeed wraps routes so it gets tried regardless of the wrapped routes. Specifically, if the requests needs to be routed to admin-routes, user-auth? will still be tried (and fail).

I resorted to use context to root some routes under a common base path but it's quite a constraint (the code below may not work it's simply to illustrate the idea):

(defroutes user-routes
  (GET "-endpoint1" [] ("USER ENDPOINT 1"))
  (GET "-endpoint2" [] ("USER ENDPOINT 1")))

(defroutes admin-routes
  (GET "-endpoint" [] ("ADMIN ENDPOINT")))

(def app
  (handler/api
    (routes
      public-routes
      (context "/user" []
        (-> user-routes
            (wrap-basic-authentication user-auth?)))
      (context "/admin" []
        (-> admin-routes
            (wrap-basic-authentication admin-auth?))))))

I'm wondering if I'm missing something or if there's any way at all to achieve what I want without constraint on my defroutes and without using a common base path (as ideally, there would be none).


Source: (StackOverflow)

How To Integrate Clojure Web Applications in Apache

Note

Given this OP was written about two years ago, rather than ask the same question again, I am wondering if step-by-step instructions exist, so that I can integrate a Noir or other Clojure web application into Apache, whether it's Jetty, Tomcat, or something else. Similar instructions exist for Django, and I think I understand that Python is being run in Django's case as an engine rather than a ring framework, so things are more complicated with Clojure web applications.

End Note

I'm deeply in love with Clojure, and Compojure seems like a neat web framework.

But it all fell apart when I wanted to deploy my application on a regular application server like Tomcat as a WAR. I actually had to write custom Ring handlers for static files and resources that would work on both local Jetty and Tomcat because the stock handlers didn't, and I had to prepend the context root everywhere manually.

I am negatively amazed that I had to write all this code to create the simplest web application conceivable that would run on both Jetty and Tomcat. I have only three possible explanations for this:

  1. Nobody uses Clojure/Compojure for anything other than local development with Jetty, i.e. in production
  2. Everybody deploys Clojure/Compojure apps on a dedicated Jetty without context root (LIke people do it with Node.js apps)
  3. There is a really simple way to circumvent the problems I ran into I wasn't aware of

Which of these is in your opinion the case? Or is it something else?

Edit:

Please note that creating a war file is a no-brainer with Maven/Leiningen and not what I mean. I'm wondering that I have to write so much code to make Compojure work with Tomcat, basic stuff like static file serving and context root awareness that should work out of the box.


Source: (StackOverflow)

Compojure/Ring: Why doesn't a session with cookie-store survive a server restart?

I have a compojure app that uses the ring session wrapper to store the OAuth token associated with the current user. I would like for this token to remain available when the server restarts, so that I don't have to go through the auth process each time.

I assumed that using the cookie-store instead of the default memory-store would help, but it does not. What am I missing?

This is the relevant part of the code:

(defn auth-callback-handler
  [session {code :code}]
  (let [token (retrieve-token code)]
    (-> (redirect "/") (assoc :session (assoc session :token token)))))

(defroutes app-routes
  (GET "/" {session :session} (root-handler session))
  (GET "/auth-callback" {session :session params :params} (auth-callback-handler session params))
  (route/not-found "Not Found"))

(def app
  (-> (handler/site app-routes)
      (wrap-session {:store (cookie-store {:key "a 16-byte secret"})})))

The function root-handler uses the token to decide if someone is logged in or not, but does not return anything in the way of session info.


Source: (StackOverflow)

Could not locate compojure in classpath

I am trying the various Getting started examples and I can get a basic hello world example working with basic HTML in the route as such

(ns hello-world
  (:use compojure.core ring.adapter.jetty)
  (:require [compojure.route :as route]))

(defroutes example
  (GET "/" [] "<h1>Hello World Wide Web!</h1>"))

(run-jetty example {:port 8080})

But when I attempt to use the html helpers like so

(ns hello-world
  (:use compojure ring.adapter.jetty)
  (:require [compojure.route :as route]))

(defroutes example
  (GET "/" []
    (html [:h1 "Hello World"])))

(run-jetty example {:port 8080})

Then I get the following error

[null] Exception in thread "main" java.io.FileNotFoundException: Could not locate compojure__init.class or compojure.clj on classpath: (core.clj:1)


Source: (StackOverflow)

How do I use snippets in enlive?

I'm a Rails dev getting my feet wet in Clojure. I'm trying to do something which was very simple with ERB but I can't for the life of me figure it out in enlive.

Say I have a simple layout file for a website in layout.html:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>

And I have these snippets, for instance, header.html and footer.html and this simple route.

(deftemplate layout "layout.html" [])

(defroutes home-routes
  (GET "/" [] layout))

How can I make it so whenever a request goes to "/" it transforms the layout and inserts the header and footer snippets into it?


Source: (StackOverflow)

Getting started with CSS in Compojure?

I found a very basic web page on the Internet and now I would like to do the obvious thing and add some CSS so I can build nicer pages.

  1. How can I include jQuery, as well as other style sheets?
  2. How can I include inline CSS so I can throw in a text-align: center, for example, to try out quick changes?

Regular jQuery include:


<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"/>

Basic Hello World server without formatting: (Updated to include static routing fix so others will be up and running quicker)


(ns hello-world
  (:use compojure))

(defn index
  [request]
    (html
    [:h1 "Hello World"]
    [:p "This is ugly with CSS!"])
    )

(defn hello
  [request]
  (html ""
   [:title "A very long title"]
   [:div.comment
    [:h1 "Hello's Page"]
    [:p "This would look better with some CSS formatting!"]]
))

(defroutes greeter
  (GET "/" index)
  (GET "/h" hello)
  (GET "/*"
       (or (serve-file "/opt/compojure/www/public" (params :*)) ;; This is needed to find CSS and js files
       :next))
  (ANY "*"
       (page-not-found) ;;  404.html is in /opt/compojure/www/public/404.html
  ))


(run-server {:port 9090}
  "/*" (servlet greeter))


Source: (StackOverflow)

What's the relationship between Leiningen, Compojure, Luminus and Ring?

I'm starting my new learning phase of Clojure. I want to build a web application, but I don't know which one to use. I've searched for several hours online, and all the things I found kind of overlap each other and I'm a little bit confused by that.

I have experience in ASP.NET MVC and JavaEE, so if there's something to relate Clojure web programming with those experiences, I'm glad to hear about it.

What's the relationship between Leiningen, Compojure, Luminus and Ring?


Source: (StackOverflow)

Passing state as parameter to a ring handler?

How does one inject state into ring handlers most conveniently (without using global vars)?

Here is an example:

(defroutes main-routes
  (GET "/api/fu" [] (rest-of-the-app the-state)))

(def app
  (-> (handler/api main-routes)))

I would like to get the-state into the compojure handler for main-routes. The state might be something like a map created with:

(defn create-app-state []
  {:db (connect-to-db)
   :log (create-log)})

In a non ring application I would create the state in a main function and start injecting it, or parts of it, as function parameters to the different components of the application.

Can something similar be done with ring's :init function without using a global var?


Source: (StackOverflow)

Compojure: how to map query parameters

I'm trying to make any of the following mappings work to map http://mysite.org/add?http://sitetoadd.com or http://mysite.org/add?u=http://sitetoadd.com

  (GET "/add?:url" [url] url)
  (GET "/add?u=:url" [url] url)
  (GET "/add" {params :params} (params :u))
  (GET "/add" {params :params} (params "u"))
  (GET "/add" [u] u)

But it just fails and I don't know why. On the other hand, this works:

  (GET "/add/:url" [url] url)

but I can't use it because I have to pass a url and http://mysite.org/add/http://sitetoadd.com is invalid while http://mysite.org/add?http://sitetoadd.com is ok.

EDIT: dumping request i've seen that params is empty. I thought that it would contain POST and GET parameters, but the only place where I can find the params I pass is in :query-string ("u=asd"). It seems that a middleware is needed to parse query strings. My question stands still, by the way.


Source: (StackOverflow)

Missing form parameters in Compojure POST request

I'm having problems getting the form parameters in the following Compojure example:

(ns hello-world
  (:use compojure.core, ring.adapter.jetty)
  (:require [compojure.route :as route]))

(defn view-form []
(str "<html><head></head><body>"
   "<form method=\"post\">"
   "Title <input type=\"text\" name=\"title\"/>"
   "<input type=\"submit\"/>"
   "</form></body></html>"))

(defroutes main-routes
  (GET "/" [] "Hello World")
  (GET "/new" [] (view-form))
  (POST "/new" {params :params} (prn "params:" params))
  (route/not-found "Not Found"))

(run-jetty main-routes {:port 8088})

When submitting the form the output is always

params: {}

and I can't figure out why the title parameter is not in the params map.

I'm using Compojure 0.6.2.


Source: (StackOverflow)

How to run an arbitrary startup function in a ring project?

I've got a compojure/ring application I currently run with lein ring server that I'd like to compile to a .war so I can deploy it. I've got a definition, however, just like

 (def foo (start-scheduler))

That blocks the compilation and the generation of the .war. To circumvent this, I thought about moving the call to a startup function, but how would I call it when the server launches?

If I put the call inside the handler, I'd end up with the same problem as before.

Thanks!


Source: (StackOverflow)

All-in-one solution for using OAuth2 with Compojure

I am trying to integrate a compojure application with those OAuth2 providers: LinkedIn, Facebook, Google, and Twitter, using an all in one solution. I am aware of some existing java libraries such as scribe-java or spring-social that can help. But they suck when used from clojure. Is there a more clojure friendly solution to my goal? Or can anyone point me to a working sample / tutorial on how to reach my goal?


Source: (StackOverflow)

Clojure Webapp in Intellij + Maven + Tomcat

I am working with a Compojure based Clojure web application in IntelliJ using Maven as my dependency manager. It is based on an application I found at this git repository referenced by this example. When I try to run the application using IntelliJ's Tomcat6 configuration, it fails each time citing a Servlet Exception:

javax.servlet.ServletException: Wrapper cannot find servlet class tracker.core or a class it depends on

Additionally looking at the web.xml, IntelliJ does not recognize the servlet class (tracker.core is highlighted).

A little background:

This application was originally was built as a proof of concept for a client and written by my coworker who recently left the company. I personally have no experience with clojure beyond working on this project over the last two days. Using Leiningen ring server, I can successfully get the application to run in jetty. Using leiningen ring uberwar, the resulting war successfully deploys and runs in tomcat.

The original file structure looks like so:

/tracker-webapp  
    /classes
    /lib
    /resources
    /src
        /tracker
            /core.clj (and other *.clj files)
    /test
    project.clj

The new mavenized file structure now mirrors the example in the previously mentioned git repo:

/tracker-webapp
    /src
        /main
            /clojure
                /tracker
                    /core.clj (and other *.clj files)
            /webapp
                /WEB-INF
                    /web.xml
    /pom.xml

My web.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
     PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

  <display-name>Simple Clojure WebApp</display-name>
  <servlet>
    <servlet-name>myservlet</servlet-name>
    <servlet-class>tracker.core</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>myservlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

</web-app>

Other Resources

Okay so I was going to post the other resources that I've looked at in this section but since I'm a Stack Overflow Newb I only get two links :/

P.S. This is my first question on Stack Overflow so if I missed something or you have any suggestions of anything I left out or do differently let me know. Thanks!


Source: (StackOverflow)

How do you use sessions with Compojure/Ring?

I'm developing a web application using Compojure and I would hugely appreciate a small and complete example of storing and retrieving session data.

Many thanks in advance, James.


Source: (StackOverflow)

Compojure or Noir for a UI-less webservice?

If one is planning to create a UI-less web service (receives JSON and/or XML, returns JSON and/or XML), does Noir provide anything useful over and above Compojure?


Source: (StackOverflow)