Mercurial > hg > WSGraph
view wsgraph/web.py @ 40:00aee7b82657
notes
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Thu, 11 Apr 2013 13:50:51 -0700 |
parents | 24d57daaca21 |
children |
line wrap: on
line source
#!/usr/bin/env python """ web handler for WSGraph """ import json import sys from webob import Request, Response, exc # rank constants GRAPH = 0 NODE = 1 EDGE = 2 # XXX stubbing hack class JSONformatter(object): def __init__(self, content_type='application/json', sort_keys=True): self.content_type = content_type self.sort_keys = sort_keys def format(self, instance): """front-end to json.dumps""" return json.dumps(instance, sort_keys=self.sort_keys) def node(self, request, graph, node): return Response(content_type=self.content_type, body=self.format(graph.node(node))) def edge(self, request, graph, node1, node2): return Response(content_type=self.content_type, body=self.format(graph.edge(node1, node2))) def graph(self, request, graph): return Response(content_type=self.content_type, body = self.format(graph())) class Dispatcher(object): def __init__(self, graph, graph_formatters, node_formatters, edge_formatters, require_auth=False): self.graph = graph self.require_auth = require_auth # view formatters self.formatters = {GRAPH: graph_formatters, NODE: node_formatters, EDGE: edge_formatters} for key, value in self.formatters.items(): # ensure default formatter assert None in value # ensure all formatters are callable self.methods = dict([(i, getattr(self, i)) for i in dir(self) if i.isupper()]) def __call__(self, environ, start_response): request = Request(environ) method = self.methods.get(request.method) if method is None: return exc.HTTPMethodNotAllowed()(environ, start_response) response = method(request) return response(environ, start_response) @staticmethod def path_segments(path): """split a path into segments""" segments = path.strip('/').split('/') if segments == ['']: segments = [] return segments def formatter(self, rank, request): """returns the formatter for a request""" formatters = self.formatters[rank] format = request.GET.get('format') return formatters.get(format, formatters[None]) # HTTP methods def GET(self, request): """ respond to a GET request Formatters are keyed off of formatters = {0: { } A graph formatter takes the following arguments: def sample_graph_formatter(graph, request): A node formatter takes the following arguments: def sample_node_formatter(node, graph, request): An edge formatter takes the following arguments: def sample_edge_formatter(edge, graph, request): API: ?format=<format> """ # get resource requestor segments = self.path_segments(request.path_info) rank = len(segments) if rank not in (0,1,2): return exc.HTTPNotFound() # is resource in the graph? if (rank == EDGE) or (rank == NODE): if tuple(segments) not in self.graph: return exc.HTTPNotFound() # formatter formatter = self.formatter(rank, request) return formatter(request, self.graph, *segments) def POST(self, request): """ respond to a POST request API: ?update : """ # check authorization if self.require_auth: raise NotImplementedError return exc.HTTPSeeOther(location='/') # TODO: /path/to/self def HEAD(self, request): """respond to a HEAD request""" raise NotImplementedError def OPTIONS(self, request): return Response() # TODO: Allow=', '.join(self.methods); Content-Length=0 def main(args=sys.argv[1:]): """example web server""" # imports from wsgiref import simple_server from model import MemoryCache from optparse import OptionParser # parse command line options parser = OptionParser() parser.add_option('-p', '--port', type='int', default=8080, help="port to serve on") options, args = parser.parse_args() # example model graph = MemoryCache() # example formatter(s) formatter = JSONformatter(content_type='text/plain') _formatters = {} _formatters = dict([('%s_formatters' % i, {None: getattr(formatter, i)}) for i in 'graph', 'node', 'edge']) # WSGI app app = Dispatcher(graph=graph, **_formatters) server = simple_server.make_server(host='0.0.0.0', port=options.port, app=app) print 'http://localhost:%s/' % options.port server.serve_forever() if __name__ == '__main__': main()