>> What's does the req object that is passed into the function have in it?
The contents of the incoming Ring request (and outgoing Ring response) are described in the SPEC document. I should make this a little clearer in the docs. Good for you for checking the source though! > Which by the way is awesome, because you function takes a map, which doesn't > have to be created from an HttpServletRequest object. For the purposes of > testing, you can just construct a map with the parts you want and pass that > to your function. Exactly. By distilling the request/response process into a single function call with a Clojure map as an argument, we get all the power and flexibility of Clojure and its data structures as well as the ability to concisely construct test cases for Ring components. Note also that we are not limited to the values supplied by the original Ring handler - middleware components may want to assoc in values both on the way up to the endpoint app and on the way down back to the client. For example, post body parsing middleware could process the response body and assoc the parsed value into the request before proxying back to the main app. On the response side, middleware might assoc in additional headers to augment the response, as ring.file-info does to File responses. Thanks for your comments, - Mark On Tue, Jan 13, 2009 at 1:19 AM, Paul Barry <pauljbar...@gmail.com> wrote: > To answer my own question: > [#^HttpServletRequest request] > {:server-port (.getServerPort request) > :server-name (.getServerName request) > :remote-addr (.getRemoteAddr request) > :uri (.getRequestURI request) > :query-string (.getQueryString request) > :scheme (keyword (.getScheme request)) > :request-method (keyword (.toLowerCase (.getMethod request))) > :headers (reduce > (fn [header-map #^String header-name] > (assoc header-map > (.toLowerCase header-name) > (.getHeader request header-name))) > {} > (enumeration-seq (.getHeaderNames request))) > :content-type (.getContentType request) > :content-length (let [len (.getContentLength request)] > (if (>= len 0) len)) > :character-encoding (.getCharacterEncoding request) > :body (.getInputStream request)}) > Which by the way is awesome, because you function takes a map, which doesn't > have to be created from an HttpServletRequest object. For the purposes of > testing, you can just construct a map with the parts you want and pass that > to your function. Great Work! > On Tue, Jan 13, 2009 at 1:13 AM, Paul Barry <pauljbar...@gmail.com> wrote: >> >> What's does the req object that is passed into the function have in it? >> >> On Mon, Jan 12, 2009 at 11:45 PM, Mark McGranaghan <mmcgr...@gmail.com> >> wrote: >>> >>> Hi All, >>> >>> I'm happy to announce the alpha release of 'Ring', a library inspired >>> by Python's WSGI and Ruby's Rack for developing web applications in >>> Clojure. >>> >>> I've made it as easy as humanly possible for you to try it out: >>> >>> git clone git://github.com/mmcgrana/ring.git >>> cd ring >>> java -Djava.ext.dirs=jars clojure.main src/ring/examples/ >>> hello_world.clj >>> >>> And your up and running with your first Ring web app, which you can >>> see at http://localhost:8080/ in your browser. >>> >>> The basic idea of Ring is that web apps are just Clojure functions >>> that take a standardized request as a single argument and return and >>> standardized response. For example, the hello_world.clj script from >>> above is: >>> >>> (ns ring.examples.hello-world >>> (:require ring.jetty) >>> (:import java.util.Date java.text.SimpleDateFormat)) >>> >>> (def formatter (SimpleDateFormat. "HH:mm:ss")); >>> >>> (defn app >>> [req] >>> {:status 200 >>> :headers {"Content-Type" "text/html"} >>> :body (str "<h3>Hello World from Ring</h3>" >>> "<p>The current time is " >>> (.format formatter (Date.)) ".</p>")}) >>> >>> (ring.jetty/run {:port 8080} app) >>> >>> Its nice to be able to get to "Hello World" so quickly, but the real >>> power of Ring is that apps are just functions - hence we can combine, >>> wrap, curry, and generally manipulate them as first class values. >>> >>> For example, someone asked in #clojure today how they could make their >>> web app provide a cleaned backtrace as an HTML response when it raised >>> exceptions. To add such exception handling to our Hello World Ring app >>> we would just use the ring.backtrace middleware: >>> >>> (ring.jetty/run {:port 8080} app) >>> >>> becomes >>> >>> (ring.jetty/run {:port 8080} >>> (ring.backtrace/wrap >>> app)) >>> >>> Similarly, one might want to have changes to a web app's code be >>> reflected in real time in the development environment, so as to avoid >>> constantly having to reboot the webserver. The ring.reload middleware >>> accomplishes exactly that: >>> >>> (ring.jetty/run {:port 8080} >>> (ring.backtrace/wrap >>> (ring.reload/wrap '(ring.examples.hello-world) >>> app) >>> >>> These are some of the features that originally motivated me to develop >>> Ring, but the complete list of functionality available to Ring apps is >>> larger and continues to grow: >>> >>> * ring.jetty: Handler for the Jetty webserver. >>> * ring.file: Middleware that serves static files out of a public >>> directory. >>> * ring.file-info: Middleware that augments response headers with info >>> about File responses. >>> * ring.dump: Endpoint that dumps the Ring requests as HTML responses >>> for debugging. >>> * ring.show-exceptions: Middleware that catches exceptions and >>> displays readable backtraces for debugging. >>> * ring.reload: Middleware to automatically reload selected libs before >>> each requests, minimizing server restarts. >>> * ring.builder: Helpers for combining Ring endpoints and middleware >>> into Ring apps. >>> * ring.lint: Linter for the Ring interface, ensures compliance with >>> the Ring spec. >>> * ring.examples.*: Various example Ring apps. >>> >>> You can find more details about Ring at its project page on GitHub, >>> including a README file for new users and a draft SPEC file that >>> documents the Ring interface: >>> >>> http://github.com/mmcgrana/ring >>> >>> I've built an open source web app on Ring: http://cljre.com. The >>> source for this simple app, available at >>> http://github.com/mmcgrana/cljre.com, >>> could serve as a good introduction to how apps can consume Ring >>> requests and to the use of modular Ring middleware; see in particular >>> the src/cljre/app.clj file, where most of that application is defined. >>> >>> Also, I think I should mention how I see Ring relating to the Java >>> Servlet abstraction and to existing and new Clojure web frameworks. >>> Ring heavily leverages the Servlet API internally, as I strongly >>> believe in not reinventing wheels such as basic HTTP parsing. >>> Furthermore, I think that the interface that Ring presents to Clojure >>> web application developers by pre-processing the servlet requests is >>> dramatically more useful than that of the raw servlet. Ring uses >>> Servlets for what they are really good at - implementing HTTP - and >>> presents a simple API against which additional logic can be defined in >>> the application layer. >>> >>> In terms of Clojure web frameworks, I think that there is a lot to be >>> gained by leveraging the Ring interface, especially from the modular >>> functionality provided by Ring middleware. I'd like in particular to >>> be able to run Compojure apps in Ring - if the users and authors of >>> Compojure are interested I'd be happy to work with them to see what we >>> can do. >>> >>> If you've made it this far, thanks a lot for reading! I welcome any >>> comments or suggestions that you have about Ring, the draft SPEC >>> document, or the Clojure web app space in general. >>> >>> Thanks again, >>> - Mark >>> >>> >> > > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---