zaach / jack forked from 280north/jack

Rack for JavaScript

This URL has Read+Write access

tlrobinson (author)
Thu Mar 26 16:17:03 -0700 2009
commit  9f13eb7504e247622ce1d0918d5011b059571336
tree    342fa61faa5768f4ed4d2c5be51514206142757e
parent  dd219306d8708a338c99eca525687bcf66209f55
jack /
name age message
file README Loading commit data...
directory bin/
file core.js
directory example/
directory lib/
directory tests/
README
Jack: Rack for JavaScript

    "Rack provides an minimal interface between webservers supporting Ruby and Ruby 
    frameworks".replace("Rack","Jack").replace("Ruby","JavaScript")

    Indeed, Jack is heavily inspired by Rack (http://rack.rubyforge.org/), as well as Python's WSGI 
    (http://www.wsgi.org/), with adjustments to suit JavaScript where necessary.
    
    It provides a common interface between web servers and web applications or frameworks written in JavaScript. At it's 
    core, Jack is simply a protocol that defines an interface, but it is also an implementation of a set of handlers (to 
    connect to web servers), adapters (to connect to JavaScript frameworks and applications), middleware (to intercept 
    and manipulate requests or responses), and utilities (to make using Jack easier) implemented in JavaScript.

    Homepage: http://jackjs.org/

    Source & Download: http://github.com/tlrobinson/jack/

    Mailing list: http://groups.google.com/group/jack-js
    
    IRC: #jack-js on irc.freenode.net
    

== Getting Started:

    Jack currently supports the Jetty (and other servlet containers) and Simple webservers using Rhino, and it should be 
    easy to integrate with other JavaScript interpreters and web servers. It also has preliminary support for v8cgi.

    To start working with Jack, ensure you have the Rhino ("js.jar") and Jetty ("jetty", "jetty-util", "servlet-api") or 
    Simple ("simple") jars in your CLASSPATH environment variable. From the Jack project directory execute "bin/jackup" 
    with the path to a Jackup configuration file:

        ./bin/jackup example/hello.js
        
    or (this one specifies a path to an extra library that needs to be included, "lib/jack/lobster.js"):
    
        ./bin/jackup -r lib/jack/lobster.js example/example.js
    
    Jackup configuration files simply contain JavaScript with the last statement being a reference to a Jack application 
    (or middleware)

    To see other options of Jackup, use the "-h" option:

        ./bin/jackup -h

    If you want to install and run Jackup from a different directory you can edit the following line at the top of the 
    jackup (and roundup) scripts to be an absolute path to the "lib" directory:

        require.paths.push("lib");


== Writing Jack Applications:
        
    A Jack application is simply a JavaScript function. It should return an array containing three elements: the status 
    code (an integer), the headers values (a hash), and a body object (anything that responds to the "forEach" method).

        
    We have extended JavaScript Array and String objects to respond to "forEach" (so they are valid "body" responses), 
    thus the following is a valid Jack application:
    
        function(env) {
            return [200, {"Content-Type":"text/plain"}, "Hello world!"];
        }
    
    If you need something more complex with extra state, you can provide use a "constructor" in the form of a function
        
        MyApp = function(something) {
            return function(env) {
                return [200, {"Content-Type":"text/plain"}, "Hello " + this.something + "!"];
            }
        }
        
        app = MyApp("Fred");
    
    Be careful to ensure you application is threadsafe if you plan to use a multithreaded server.
        
    The first (and only) argument to the application method is the "environment", which contains a number of properties. 
    Many of the common CGI environment variables are included, as well as some Jack specific properties which are 
    prefixed with "jack.".

    The Request and Response objects aren't required, but may be helpful in parsing request parameters, and building a 
    valid response. They are used as follows:
    
        var req = new Jack.Request(env);
        var name = req.GET("name");
        
        var resp = new Jack.Response();
        resp.setHeader("Content-Type", "text/plain");
        resp.write("hello ");
        resp.write(name);
        resp.write("!");
        return resp.finish(); // equivalent to returning [200, {"Content-Type" : "text/plain"}, "hello "+name+"!"]
        
    These objects are currently partially implemented.


== Roundabout

    Roundabout is a Rack compatible application / middleware that works similarly to the Ruby Sinatra framework.
    
    One major difference is that Roundabout can be used as middleware to map other Rack components to specific URL 
    patterns, like a more powerful version of the URLMap middleware.
    
    More documentation forthcoming. Run the roundup script with a Roundabout app:

        ./bin/roundup example/roundup/example.js

    
== Writing Jack Middleware:

    Jack middleware performs some sort of pre or post processing on requests, such as logging, authentication, etc. Most 
    Jack middleware, by convention (and required for use with the Builder DSL, etc), is a function that takes in one 
    argument, "app" (which will be a Jack application) and creates a Jack application (i.e. another function that takes 
    in an "env" argument and returns a three element array). In the returned Jack application it will typically 
    optionally do some preprocessing on the request, followed by calling the "app" that was provided, optionally 
    followed by some post processing.
    
    For example, the "Head" middleware calls the "app", then checks to see if the request HTTP method was "HEAD". If so, 
    it clears the body of response before returning it, since HEAD requests shouldn't have a response body.
    
    A more complicated middleware might need to peform postprocessing on the body contents. A common pattern is to call 
    the app, then store the body as a property of a "context" and return the context *as* the body instead. It also 
    defines an "forEach" method on the context, which proxies to the stored body property. It is important to proxy the 
    response body rather than buffer the entire response when dealing with streaming type applications. A good example 
    of this pattern is the CommonLogger middleware, which does this in order to calculate the body length for logging.


== Caveats

    Thread safety:

        Jack is simply a protocol, which is inherently thread safe. Additionally, all these components should be 
        threadsafe. If you find one that is not, please report it.

    Completeness:

        The basic functionality of the handlers and middleware is complete. Some things are missing though.

    API stability:

        The Jack protocol will likely not change significantly, but some of the details may. Keep up to date on the 
        mailing list mentioned above.

    Misc:

        Jack depends on a small library currently named "core.js" which contains a basic Ruby-style "require" method as 
        well as some additions to the built in JavaScript objects, etc. Eventually this will be replaced by a 
        standardized general purpose API: http://groups.google.com/group/serverjs/
        

== Differences between Jack and Rack:

  Jack applications are simply functions, rather than objects that respond to the "call" method.


== Component Status:

    Component       Status
    ---------       ------
Core:
    Request:        incomplete
    Response:       incomplete
    
Utilities:
    Jackup:         complete (?)

Handlers:
    Servlet:        complete (?), for use with Jetty on Rhino, or other servlet container.
    Jetty:          complete (?), simple wrapper for Jetty using Servlet handler (http://www.mortbay.org/jetty/)
    Simple:         complete (?), for use with the Simple webserver (http://www.simpleframework.org/)
    V8CGI:          complete (?), for use with the v8cgi project (http://code.google.com/p/v8cgi/)

Middleware:
    Cascade:        complete
    CommonLogger:   complete
    ContentLength:  complete
    Deflater:       missing
    Directory:      missing
    File:           complete
    Head:           complete
    JSONP:          complete
    Lint:           mostly complete (needs stream wrappers)
    MethodOverride: complete
    Mock:           missing
    Recursive:      missing
    ShowExceptions: simple version complete, needs better HTML output
    ShowStatus:     missing
    Static:         complete
    URLMap:         complete

    

== Acknowledgments

This software was influenced by Rack, written by Christian Neukirchen.

http://rack.rubyforge.org/


== License:

Copyright (c) 2009 Thomas Robinson <tlrobinson.net>

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 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.