From 40f499401313ebcd9f1d679ed61954b306f738f3 Mon Sep 17 00:00:00 2001 From: schneefux Date: Sat, 21 Feb 2015 16:27:24 +0100 Subject: first commit --- snapext.py | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100755 snapext.py (limited to 'snapext.py') diff --git a/snapext.py b/snapext.py new file mode 100755 index 0000000..04a1977 --- /dev/null +++ b/snapext.py @@ -0,0 +1,173 @@ +# Copyright (C) 2013 Connor Hudson, Tim Radvan + +"""Module for writing Snap! extensions. + +See example.py for usage. + +Handler functions should return unicode. Non-unicode strings are assumed to +be UTF-8 encoded. + +""" + +__version__ = '0.1.4' + +import inspect +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO +from urlparse import urlsplit, parse_qs +from SimpleHTTPServer import SimpleHTTPRequestHandler +from SocketServer import TCPServer + + + +class SnapHandler(SimpleHTTPRequestHandler): + """An HTTP handler with Flask-style routing.""" + + routes = {} + + special = { + 'true': True, + 'True': True, + 'false': False, + 'False': False, + } + + @classmethod + def prettify_arg(cls, value): + value = value.decode('utf-8') + value = cls.special.get(value, value) + if isinstance(value, bool): + return value + try: + return int(value) + except ValueError: + try: + return float(value) + except ValueError: + return value # str + + def send_head(self): + split_url = urlsplit(self.path) + path = split_url.path + params = parse_qs(split_url.query) + params = dict((k, self.prettify_arg(v[0])) for (k, v) in params.items()) + print 'params', params + is_browser = "text/html" in self.headers['Accept'] + + (status, mime_type, response) = self.get_response(path, params, + is_browser) + if isinstance(response, str): + response = response.decode('utf-8') + else: + response = unicode(response) + + if is_browser and mime_type == "text/plain": + mime_type = "text/html" + response = u"""{response}""".format(title=path, response=response) + + if isinstance(response, unicode): + response = response.encode('utf-8') + + self.send_response(status) + self.send_header("Content-Type", mime_type) + self.send_header("Content-Length", str(len(response))) + self.send_header("Access-Control-Allow-Origin", "*") + self.end_headers() + + return StringIO(response) + + def get_response(self, path, params, is_browser): + mime_type = "text/plain" + if path in self.routes: + f = self.routes[path] + try: + response = f(**params) + if response is None: + response = "" + elif response is True: + response = "true" + elif response is False: + response = "false" + return (200, mime_type, response) + except KeyboardInterrupt: + raise + except TypeError, e: + for param in inspect.getargspec(f).args: + if param not in params: + response = "ERROR: Missing argument %r" % param + return (400, mime_type, response) + else: + raise + elif path == '/': + return self.index(is_browser) + elif path == '/crossdomain.xml': + return """ + + + + + """ + else: + return (404, mime_type, "ERROR: Route not found") + + def index(self, is_browser): + """Return the list of routes in plain text format.""" + if is_browser: + html = u""" + + / +