Both sets of code implement the basic AtomAPI in Python. Both implementations are just CGI glue that maps the CGI interface to a lower level API in the Python module myLowLevelBloggingAPI.py. That module has four functions: create(content), get(id), update(id, content), delete(id).
Notes on the first two examples:
-
If either of these cgi scripts were installed as atom.cgi on example.org then doing a GET on http://example.org/atom.cgi/1 would get the Entry with an 'id' of 1.
-
Note that in the second example all the dispatching is done via the HTTP verbs, no parsing of the content is necessary.
-
For both examples, there is a single CGI script that processes the requests.
-
Both versions support doing a GET on the unique URI for each Entry.
HTTP using GET/POST to a single URI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #!/usr/bin/python import cgitb; cgitb.enable() import os, cgi, urlparse, sys import myLowLevelBloggingAPI import xmltramp method = os.environ['REQUEST_METHOD'] id = None if method == 'POST': content = sys.stdin.read() d = xmltramp.parse(content) if d._name == 'delete': myLowLevelBloggingAPI.delete(d('id')) try: id = d.entry.id except: pass if id == None: id = myLowLevelBloggingAPI.create(sys.stdin.read()) print "Status: 201 Created" print "Location: " + urlparse.urlunparse(('http', os.environ['SERVER_NAME'], os.environ['REQUEST_URI'] + '/%d', '', '', '')) + "\n" % (id, ) else: myLowLevelBloggingAPI.update(id, content) print "Status: 205 Reset Content\n" elif method == 'GET': id = os.environ.get('PATH_INFO', '') print "Status: 200 Ok\n" print myLowLevelBloggingAPI.get(id) |
-
AnswerMe: How would this example handle creating or updating content types other than XML? Would it get the 'id' from a different source (HTTP header, PATH_INFO, or QUERY_STRING, maybe) or would it encode the content within XML as in content?
-
AnswerMe: How are comments and trackbacks directed to their respective entries?
HTTP in the REST Architectural Style
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/usr/bin/python import cgitb; cgitb.enable() import os, urlparse, sys import myLowLevelBloggingAPI method = os.environ['REQUEST_METHOD'] id = os.environ.get('PATH_INFO', '') if method == 'POST': id = myLowLevelBloggingAPI.create(sys.stdin.read()) print "Status: 201 Created" print "Location: " + urlparse.urlunparse(('http', os.environ['SERVER_NAME'], os.environ['REQUEST_URI'] + '/%d', '', '', '')) + "\n" % (id, ) elif method == 'GET': print "Status: 200 Ok\n" print myLowLevelBloggingAPI.get(id) elif method == 'PUT': myLowLevelBloggingAPI.update(id, sys.stdin.read()) print "Status: 205 Reset Content\n" elif method == 'DELETE': myLowLevelBloggingAPI.delete(id) print "Status: 200 Ok\n" |
Complete RESTful Server
atom.cgi is a shell script that implements a RESTful server. CommonGatewayInterface, like most web server interfaces, does all the real work in providing the method (REQUEST_METHOD), the parsed and relatively safe portion of the URI (PATH_INFO), and any query parameters (QUERY_STRING).
atom.cgi supports entries, comments and static files using PUT/GET/DELETE, and queries for comments and other references to an entry, via a '?references' query parameter to entries. New comments are created using POST to the resource (typically an entry) being commented-on.
If your browser supports XSLT rendering of XML content (Moz/5 does), you can view the home page, an entry, and what currently passes for a comment. Also manageable thru atom.cgi are the stylesheets, a FOAF file, and its icon, .