Permalink
Browse files

Initial import from http://github.com/mmcgrana/clj-garden

  • Loading branch information...
mmcgrana committed Jan 12, 2009
0 parents commit 68e08fb6a8a09a5027459d383bdce70cfbe40367
@@ -0,0 +1 @@
+bundle
22 LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2009 Mark McGranaghan
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,60 @@
+h1. Ring
+
+Ring is a library inspired by Python's WSGI and Ruby's Rack that
+enables modular and concise Clojure web applications. Ring abstracts the details
+of HTTP and defines a simple API by which web application components can
+cleanly interact.
+
+h2. Quick Setup
+
+All jars needed to load any of the @ring.*@ libs in this distribution are
+included in the jars/ directory. To see a live Ring app, run:
+
+ java -Djava.ext.dirs=jars clojure.main src/ring/examples/hello_world.clj
+ curl localhost:8080/
+
+You can find additional example Ring apps in the @src/examples@ directory of this distribution, including a "basic stack" example that shows a typical Ring setup with wrapping middleware.
+
+h2. Spec
+
+Please consult the @SPEC@ file at the root of this distribution for a complete
+description of the Ring interface.
+
+h2. Available Libs
+
+ * @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 stack traces for debugging.
+ * @ring.reloading@: 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 @SPEC@.
+ * @ring.examples.*@: Various example Ring apps.
+
+h2. Development
+
+Ring is being actively developed; you can track its progress and contribute at: "github.com/mmcgrana/ring":http://github.com/mmcgrana/ring.
+
+To run all of the @ring.*@ unit tests:
+
+ java -Djava.ext.dirs=jars clojure.main test/ring/run.clj
+
+You can learn more about Ring's dependencies at the following sites:
+
+ * @clojure.jar@, @clojure-contrib.jar@: "clojure.org":http://clojure.org
+ * @jetty-6.1.14.jar@, @jetty-util-6.1.14.jar@, @servlet-api-2.5-6.1.14.jar@: "mortbay.org/jetty":http://www.mortbay.org/jetty
+ * @commons-io-1.4.jar@: "commons.apache.org/io":http://commons.apache.org/io/
+ * @clj-html.jar@, @clj-html-helpers.jar@, @clj-backtrace.jar@, @clj-unit@ (testing): "github.com/mmcgrana":http://github.com/mmcgrana
+
+---
+
+<pre><code>
+ +--->HTTP Request--->[Handler]--->Req1---->[Middleware]--->Req2----+
+ | |
+ [Client] [Endpoint]
+ | |
+ +----HTTP Response<--[Handler]<---Resp2<---[Middleware]<---Resp1<--+
+</code></pre>
+
+Copyright (c) 2009 Mark McGranaghan and released under an MIT license.
124 SPEC
@@ -0,0 +1,124 @@
+=== Ring Spec (Draft Version)
+Ring is defined in terms of Components, Handlers, Requests, and Responses,
+each of which are described below.
+
+
+== Components
+Ring components constitute the logic of the web application and are abstracted
+form the details of the HTTP protocol. They are implemented as Clojure
+functions that process a given request to generate and return a response.
+
+A component is either an 'endpoint' or 'middleware'. An endpoint component is
+used at the leaf of a component tree, i.e. it does not call any other components
+to generate it's response. A 'middleware' component in contrast may invoke
+other components to generate its response. We can combine 1 or more endpoints
+with 0 or more middleware components to build a complete Ring 'app'. Such an
+app can then be run by a Ring handler.
+
+== Handlers
+A Ring handler is a server implementation than can 'run' apps. Handlers are
+responsible for implementing the HTTP protocol and abstracting the apps that
+they run from the details of the protocol.
+
+Handlers are implemented as functions of two arguments, an options map and a
+Ring app. The options map provides any needed configuration to the handler, such
+as the port on which to run.
+
+Once initialized, handlers receive HTTP requests, parse them to construct an
+Ring request, and then invoke their Ring app with this request as an
+argument. Once the app returns a Ring response, the handler uses it to construct
+and send an HTTP response to the client.
+
+
+== Ring Requests
+A Ring request is a Clojure map containing at least the following keys and
+corresponding values:
+
+:server-port
+ (Required, Integer)
+ The port on which the request is being handled.
+
+:server-name
+ (Required, String)
+ The resolved server name, or the server IP address.
+
+:remote-addr
+ (Required, String)
+ The IP address of the client or the last proxy that sent the request.
+
+:uri
+ (Required, String)
+ The request URI. Must starts with "/".
+
+:query-string
+ (Optional, String)
+ The query string, if present.
+
+:scheme
+ (Required, Keyword)
+ The transport protocol, must be one of :http or :https.
+
+:request-method
+ (Required, Keyword)
+ The HTTP request method, must be one of :get, :head, :options, :put, :post, or
+ :delete.
+
+:content-type
+ (Optional, String)
+ The MIME type of the request body, if known.
+
+:content-length
+ (Optional, Integer)
+ The number of bytes in the request body, if known.
+
+:character-encoding
+ (Optional, String)
+ The name of the character encoding used in the request body, if known.
+
+:headers
+ (Required, IPersistentMap)
+ A Clojure map of downcased header name Strings to corresponding header value
+ Strings.
+
+:body
+ (Optional, InputStream)
+ An InputStream for the request body, if present.
+
+If a component invokes another component with an environment containing
+additional keys, these keys must be namespaced using the Clojure
+:name.space/key-name convention. The ring.* namespaces are reserved.
+
+
+== Ring Responses
+A Ring response is a Clojure map containing at least the following keys and corresponding values:
+
+:status
+ (Required, Integer)
+ The HTTP status code, must be greater than or equal to 100.
+
+:headers
+ (Required, IPersistentMap)
+ A Clojure map of HTTP header names to header values. These values may be
+ either Strings, in which case one name/value header will be sent in the
+ HTTP response, or a seq of Strings, in which case a name/value header will be
+ sent for each such String value.
+
+:body
+ (Optional, {String, File, InputStream})
+ A representation of the response body, if a response body is appropriate for
+ the response's status code. The respond body is handled according to its type:
+ String:
+ Contents are sent to the client as-is.
+ File:
+ Contents at the specified location are sent to the client. The server may
+ use an optimized method to send the file if such a method is available.
+ InputStream:
+ Contents are consumed from the stream and sent to the client. When the
+ stream is exhausted, it is .close'd.
+
+As with environments, keys other than those listed above should be appropriately
+namespaced.
+
+
+== Credit
+This project borrows heavily from Ruby's Rack and Python's WSGI, and I thank the communities developing and supporting those projects.
@@ -0,0 +1,17 @@
+<project name="ring" default="jar">
+ <description>Pack all sources into a JAR.</description>
+
+ <property name="jarfile" location="ring.jar"/>
+
+ <target name="clean" description="Remove generated files and directories.">
+ <delete file="${jarfile}"/>
+ </target>
+
+ <target name="jar" description="Create jar file.">
+ <jar jarfile="${jarfile}">
+ <path location="LICENSE"/>
+ <fileset dir="./src" includes="ring/**/*.clj"/>
+ <fileset dir="./test" includes="ring/**/*.clj"/>
+ </jar>
+ </target>
+</project>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,8 @@
+(ns ring.builder)
+
+(defn wrap-if
+ "If test is logically true, returns the result of invoking the wrapper on the
+ core app, i.e. a wrapped app; if test is logically false, returns the core
+ app."
+ [test wrapper-fn core-app]
+ (if test (wrapper-fn core-app) core-app))
@@ -0,0 +1,81 @@
+(ns ring.dump
+ (:use (clj-html core utils helpers)
+ clojure.contrib.def
+ clojure.set)
+ (:import (org.apache.commons.io IOUtils)))
+
+(def css "
+/*
+Copyright (c) 2008, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.6.0
+*/
+html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}del,ins{text-decoration:none;}
+
+
+h3.info {
+ font-size: 1.5em;
+ margin-left: 1em;
+ padding-top: .5em;
+ padding-bottom: .5em;
+}
+
+table.trace {
+ margin-left: 1em;
+ background: lightgrey;
+}
+
+table.trace tr {
+ line-height: 1.4em;
+}
+
+table.trace td.method {
+ padding-left: .5em;
+ text-aligh: left;
+}
+
+table.trace td.source {
+ text-align: left;
+}")
+
+(def ring-keys
+ '(:server-port :server-name :remote-addr :uri :query-string :scheme
+ :request-method :content-type :content-length :character-encoding
+ :headers :body))
+
+(defhtml req-pair
+ [key req]
+ [:tr [:td.source (h (str key))]
+ [:td.method (h (pr-str (key req)))]])
+
+(defhtml template
+ [req]
+ (doctype :xhtml-transitional)
+ [:html {:xmlns "http://www.w3.org/1999/xhtml"}
+ [:head
+ [:meta {:http-equiv "Content-Type" :content "text/html"}]
+ [:title "Ring: Environment Dump"]]
+ [:style {:type "text/css"} css]
+ [:body
+ [:div#content
+ [:h3.info "Ring Env. Values"]
+ [:table.trace
+ [:tbody
+ (domap-str [key ring-keys]
+ (req-pair key req))]]
+ (if-let [user-keys (difference (set (keys req)) (set ring-keys))]
+ (html
+ [:br]
+ [:table.trace
+ [:tbody [:tr
+ (domap-str [key (sort user-keys)]
+ (req-pair key req))]]]))]]])
+
+(defn app
+ "Returns a response tuple corresponding to an HTML dump of the request
+ req as it was recieved by this app."
+ [req]
+ {:status 200
+ :headers {"Content-Type" "text/html"}
+ :body (template req)})
@@ -0,0 +1,14 @@
+; A failry typical middleware configuration wrapping the dump endpoint.
+
+(ns ring.examples.basic-stack
+ (:require (ring show-exceptions file-info file reloading dump jetty))
+ (:import (java.io File)))
+
+(def app
+ (ring.show-exceptions/wrap
+ (ring.file-info/wrap
+ (ring.file/wrap (File. "src/ring/examples/public")
+ (ring.reloading/wrap '(ring.dump)
+ ring.dump/app)))))
+
+(ring.jetty/run {:port 8080} app)
@@ -0,0 +1,16 @@
+; A very simple Ring application.
+
+(ns ring.examples.hello_world
+ (:require ring.jetty)
+ (:import java.util.Date (java.text DateFormat 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)
@@ -0,0 +1,18 @@
+; Like basic_stack.clj, but with the linter inserted between each component.
+
+(ns ring.examples.linted
+ (:require (ring show-exceptions file file-info reloading lint dump jetty))
+ (:import (java.io File)))
+
+(def app
+ (ring.lint/wrap
+ (ring.show-exceptions/wrap
+ (ring.lint/wrap
+ (ring.file-info/wrap
+ (ring.lint/wrap
+ (ring.file/wrap (File. "src/ring/examples/public")
+ (ring.lint/wrap
+ (ring.reloading/wrap '(ring.dump)
+ ring.dump/app)))))))))
+
+(ring.jetty/run {:port 8080} app)
Binary file not shown.
Oops, something went wrong.

0 comments on commit 68e08fb

Please sign in to comment.