cson  Update of "cson_cgi"

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview

Artifact ID: 87e6573e4f57cca6a1e0b890b8275ce0b1c438f0
Page Name:cson_cgi
Date: 2011-05-09 17:58:44
Original User: stephan
Parent: 8e052fad1ca755fdc462384e7563ffd9f144ec7b
Content

ACHTUNG: THIS PAGE IS NOW MAINTAINED IN THE NEW WIKI: http://whiki.wanderinghorse.net/wikis/cson/?page=cson_cgi

See also: cson_cgi_HowTo, cson_session

Online demo: http://fossil.wanderinghorse.net/demos/cson/

cson_cgi

cson_cgi is an experimental mini-framework, based off of cson, for creating JSON-only CGI web applications. The library imports various CGI-related data (e.g. environment variables, GET/POST data) into JSON form, makes it available to the client application, and handles the output of generated JSON. Client applications are intended to generate only JSON as output, and need only work with high-level cson objects. This library handles all i/o and parsing.

It is primarily intended for implementing JSON-centric AJAX-based back-ends. It can also be used for writing JSON-centric apps which are not necessarily CGI-specific. The library itself does not require a CGI-like environment to run, but without CGI-based input some of its functionality will be missing (e.g., it obviously cannot manage inbound HTTP POST data if there is no associated POST request).

cson_cgi provides an easy-to-use basis for writing CGI applications which themselves produce only JSON data. It is not intended for writing HTML-generating CGIs, and its output model will not work with such applications. That said, it can be used in conjunction with such applications as long as the client takes over the generation of all output (but the library can still be helpful in processing incoming GET/POST data and provide persistent session state).

What currently works:

  • JSON-izes the HTTP GET parameters, cookies, the system environment variables, and command-line arguments.
  • Reads JSON-format (unencoded) or form-urlencoded HTTP POST data.
  • Makes the above data available to the application in the form of JSON object trees (using the cson API).
  • Allows clients to add custom HTTP headers and cookies.
  • Handles all i/o for the client, both input and output. (Client CGI applications must not generate any output to stdout, or they risk invalidating the generated output.)
  • Client-configurable indentation of generated JSON, with various tradeoffs available for human-readability vs. small output size.
  • Optional session support, in the form of a persistent JSON object tree. Supports storing sessions in files or in a sqlite3/mysql5 database (using libcpdo, which is included in this source tree and does not need to be installed extra by the client). The session ID comes from an HTTP cookie by default, but client code can also specify their own if they like. (i'm not aware of any other CGI framework implemented in C/C++ which supports persistent sessions.)

Notable TODOs...

  • Support JSON objects/arrays as cookie values, by JSONing them and then urlencoding them. Currently only "plain" types (numbers, strings, boolean, null) are allowed as cookie values.
  • JSONP support.
  • More documentation. Especially document how to enable each separate DB driver implementation, and the linking arguments required for each.
  • Currently requires that certain JSON data be Objects, as opposed to Arrays. This is on the to-fix list, but in my experience arrays are seldom used as JSON root nodes.
  • One internally-used function requires C99 compilation mode. This should be rewritten to work in C89, as it is the only code in the tree which needs C99.
  • The cookie output routine has some glaring buffer overrun possibilities.

Less significant TODOs...

  • Allow configuration info to come from a JSON object tree, instead of just from an input file. This would allow, e.g., the client to store his cson_cgi config embedded in another client-defined JSON-format configuration file/object, and then feed the appropriate subtree to cson_cgi_init().
  • Possibly move the session initialization step out of cson_cgi_init(), so that the client can start the session manually based on config information in the request/environment state. Currently the session is started if it can be (if it's turned on and properly configured in the configuration file), but provides no way to set it up after-the-fact if the default behaviour cannot start the session.
  • Add an initialization option to disable automatic handling of POST data, so that the client can read it themselves. We currently automatically consume the stdin input only if the CONTENT_TYPE environment variable (which gets set by the web server) contains a type which we can possibly interpret as raw JSON (namely the types application/json and text/plain) or decode (form-urlencoded).
  • Add an option to allow the client app (not the remote client) to force a specific content type string for the output. i've seen cases of Firefox not accepting application/json as text, instead downloading it to a local file. Currently we try to guess the out-bound content type string based on the HTTP_ACCEPT values, falling back to text/plain if the user agent does not report supporting application/json.
  • Add a session manager impl which loads/stores its state from/to a cookie. This can only work if the session stays really small, but might have some interesting uses. This support depends on the ability to cookie-serialize/deserialize objects/arrays, which is on the TODO list (we have all the code, we just need to glue it together).

Things it won't ever do...

  • Handle file uploads. If the data can't fit in JSON then it won't be handled here.

Sample output

Here's some sample client application output. This app simply returns some of the various cson_cgi environment data to the user...

{
    "argv": [
        "./cgi-test",
        "-a=b",
        "c",
        "123"
    ],
    "$ENV": {
        "GATEWAY_INTERFACE": "CGI/1.1",
        "CONTENT_TYPE": "application/json",
        "HTTP_ACCEPT_CHARSET": "ISO-8859-1,utf-8;q=0.7,*;q=0.3",
        "HTTP_X_REQUESTED_WITH": "XMLHttpRequest",
        "REMOTE_ADDR": "127.1.1.1",
        "QUERY_STRING": "a[]=3&a[]=7",
        "REMOTE_PORT": "43422",
        "DOCUMENT_ROOT": "/home/stephan/cvs/fossil/cson",
        "HTTP_USER_AGENT": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.28 (KHTML, like Gecko) Chrome/12.0.725.0 Safari/534.28",
        "SERVER_SIGNATURE": "<address>Apache/2.2.16 (Ubuntu) Server at cson-cgi Port 80</address>\n",
        "HTTP_ACCEPT": "application/json, text/javascript, */*",
        "CONTENT_LENGTH": "39",
        "SCRIPT_FILENAME": "/home/stephan/cvs/fossil/cson/index.cgi",
        "HTTP_HOST": "cson-cgi",
        "REQUEST_URI": "/index.cgi?a[]=3&a[]=7",
        "SERVER_SOFTWARE": "Apache/2.2.16 (Ubuntu)",
        "HTTP_CONNECTION": "keep-alive",
        "HTTP_COOKIE": "cson_session_id=39063eee%2D7e34%2D649f%2Ddfed%2D1cfd2c6a452f",
        "PATH": "/usr/local/bin:/usr/bin:/bin",
        "HTTP_ACCEPT_LANGUAGE": "en-US,en;q=0.8",
        "HTTP_REFERER": "http://cson-cgi/demo.html",
        "SERVER_PROTOCOL": "HTTP/1.1",
        "HTTP_ACCEPT_ENCODING": "gzip,deflate,sdch",
        "REQUEST_METHOD": "POST",
        "SERVER_ADMIN": "[no address given]",
        "SERVER_ADDR": "127.1.1.1",
        "PWD": "/home/stephan/cvs/fossil/cson",
        "HTTP_ORIGIN": "http://cson-cgi",
        "SERVER_PORT": "80",
        "SCRIPT_NAME": "/index.cgi",
        "SERVER_NAME": "cson-cgi"
    },
    "$GET": {
        "a": [
            "3",
            "7"
        ]
    },
    "$COOKIE": {
        "cson_session_id": {
            "expires": 1303235938,
            "value": "39063eee-7e34-649f-dfed-1cfd2c6a452f"
        }
    },
    "$POST": {
        "hi": "world",
        "demotime": "now"
    },
    "$APP": {
        "guessedOutputContentType": "application/json",
        "timestamp": 1302631138
    },
    "$SESSION": {
        "timestamp": 1302631138,
        "hits": 14,
        "sessionManager": "sqlite3"
    }
}