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()
}}}

Reply via email to