cson  Artifact Content

Artifact 87e6573e4f57cca6a1e0b890b8275ce0b1c438f0:

Wiki page [cson_cgi] by stephan 2011-05-09 17:58:44.
D 2011-05-09T17:58:44.226
L cson_cgi
P 8e052fad1ca755fdc462384e7563ffd9f144ec7b
U stephan
W 8365
<strong>ACHTUNG: THIS PAGE IS NOW MAINTAINED IN THE NEW WIKI:</strong> [http://whiki.wanderinghorse.net/wikis/cson/?page=cson_cgi]


See also: [cson_cgi_HowTo], [cson_session]

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

<h1>cson_cgi</h1>

<tt>cson_cgi</tt> is an experimental mini-framework, based off of <tt>cson</tt>, for creating JSON-only [http://en.wikipedia.org/wiki/Common_Gateway_Interface|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 <tt>cson</tt> 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 <em>require</em> 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 <em>only</em> 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).

<strong>What currently works:</strong>

   *  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 <em>must not</em> 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 [cson_session|session support], in the form of a persistent JSON object tree. Supports storing sessions in files or in a sqlite3/mysql5 database (using [http://fossil.wanderinghorse.net/repos/cpdo/|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 <em>implemented in C/C++</em> which supports persistent sessions.)

<strong>Notable TODOs...</strong>

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

<strong>Less significant TODOs...</strong>

   *  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 <tt>cson_cgi_init()</tt>.
   *  Possibly move the session initialization step out of <tt>cson_cgi_init()</tt>, 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 <tt>CONTENT_TYPE</tt> environment variable (which gets set by the web server) contains a type which we can possibly interpret as raw JSON (namely the types <tt>application/json</tt> and <tt>text/plain</tt>) 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 <tt>application/json</tt> as text, instead downloading it to a local file. Currently we try to guess the out-bound content type string based on the <tt>HTTP_ACCEPT</tt> values, falling back to <tt>text/plain</tt> if the user agent does not report supporting <tt>application/json</tt>.
   *  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).

<strong>Things it won't ever do...</strong>

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

<h1>Sample output</h1>

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

<verbatim>
{
    "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"
    }
}
</verbatim>

Z f66d3c632215ac19c6575d969a90101b