couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Apache Wiki <wikidi...@apache.org>
Subject [Couchdb Wiki] Update of "ExternalProcesses" by PaulDavis
Date Wed, 17 Dec 2008 05:33:33 GMT
Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Couchdb Wiki" for change notification.

The following page has been changed by PaulDavis:
http://wiki.apache.org/couchdb/ExternalProcesses

New page:
= External Processes =

CouchDB now allows for the ability to develop custom behaviors via processes that communicate
over ''stdin'' and ''stdout''. Requests to CouchDB that are captured by the external process
handler are passed via JSON object to the external process over ''stdin'' and reads a JSON
object from ''stdout''. Without further ado...

== JSON Requests ==

Requests capture information about the incoming HTTP request and transform it into a JSON
object. I've formatted the object here, though in real life this obejct would contain no new
lines and all embedded white space would be normalized to a single ' ' (space) character.

An example object:

{{{
{
    'body': 'undefined',
    'cookie': {
        '__utma': '96992031.3087658685658095000.1224404084.1226129950.1226169567.5',
        '__utmz': '96992031.1224404084.1.1.utmcsr'
    },
    'form': {},
    'info': {
        'compact_running': False,
        'db_name': 'couchbox',
        'disk_size': 50559251,
        'doc_count': 9706,
        'doc_del_count': 0,
        'purge_seq': 0,
        'update_seq': 9706},
    'path': [],
    'query': {},
    'verb': 'GET'
}
}}}

In order:

 * ''body'' - Raw post body
 * ''cookie'' - Cookie information passed on from mochiweb
 * ''form'' - If the request's Content-Type is "application/x-www-form-urlencoded", a decoded
version of the body
 * ''info'' - Same structure as returned by http://127.0.0.1:5984/db_name/
 * ''path'' - Any extra path information after routing to the external process
 * ''query'' - Decoded version of the query string parameters.
 * ''verb'' - HTTP request verb

== JSON Response ==

The response object has four possible elements

 * ''code'' - HTTP response code [Default is 200]
 * ''headers'' - An object with key-value pairs that specify HTTP headers to send to the client
 * ''json'' - An arbitrary JSON object to send the client. Automatically sets the Content-Type
header to "application/json"
 * ''body'' - An arbitrary BLOB to be sent to the client. Content-Type header default's to
"text/html"

While nothing breaks if you specify both a ''json'' and ''body'' member, it is undefined which
response will be used. If you specify a Content-Type header in the ''headers'' member, it
will override the default.

== Common Pitfalls ==

 * When responding to queries always remember to turn off buffering for ''stdout'' or issue
a ''flush()'' call on the file handle.
 * All interaction is in the form of single lines. Each response should include *exactly*
one new line that terminates the JSON object.

== Configuration ==

Adding external processes is as easy as pie. Simply place key=command pairs in the ''[external]''
section of your ''local.ini'' like:

{{{
;Including [log] and [update_notification] for context

[log]
level = info

[external]
test = /usr/local/src/couchdb/test.py

[update_notification]
;unique notifier name=/full/path/to/exe -with "cmd line arg"
}}}

This configuration will make the ''/usr/local/src/couchdb/test.py'' responsible for handling
requests from the url:

{{{
http://127.0.0.1:5984/${dbname}/_external/test
}}}

== Example External Process ==

Here is a complete Python external process that does a whole lot of nothing except show the
mechanics.

{{{
#! /usr/bin/env python

import sys
import simplejson

def requests():
    # `for line in sys.stdin` won't work here
    line = sys.stdin.readline()
    while line:
        yield simplejson.loads(line)
        line = sys.stdin.readline()

def respond(code=200, data={}, headers={}):
    sys.stdout.write("%s\n" % simplejson.dumps({"code": code, "json": data, "headers": headers}))
    sys.stdout.flush()

def main():
    for req in requests():
        respond(data={"qs": req["query"]})

if __name__ == "__main__":
    main()
}}}

Mime
View raw message