Last active
December 15, 2015 05:19
-
-
Save jameskeane/5208276 to your computer and use it in GitHub Desktop.
Simple DFA based HTTP dispatch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import nails | |
class IndexController(nails.Controller): | |
def index(self, request): | |
return "Hello World from controller!" | |
def proof(self, request): | |
return "Proof that routing is working" | |
def test_regex(self, request, id): | |
return "id is %s" % id | |
class HelloWorld(nails.Application): | |
urls = [ | |
(r'^/?$', IndexController().index), | |
(r'^/test/:id/?$', IndexController().test_regex), | |
(r'^/proof$', IndexController().proof), | |
] | |
if __name__ == '__main__': | |
app = HelloWorld() | |
app.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from werkzeug.serving import run_simple | |
from werkzeug.wrappers import Request, Response | |
import plex | |
from plex.traditional import re as plexre | |
from plex import Lexicon, Scanner | |
from cStringIO import StringIO | |
import re | |
class Application(object): | |
def __init__(self): | |
self.build_lexicon() | |
def dispatch_request(self, request): | |
# Build a plex scanner to parse the request path | |
# and unpack it | |
try: | |
scanner = Scanner(self.lexicon, StringIO(request.path)) | |
(action, regex), matched_path = scanner.read() | |
except plex.errors.UnrecognizedInput: | |
return self.error(404, request) | |
# Parse the path to get the route parameters | |
params = re.match(regex, matched_path).groupdict() | |
# Call the action and handle the response | |
response = action(request, **params) | |
return self.handle_response(response) | |
def wsgi_app(self, environ, start_response): | |
request = Request(environ) | |
response = self.dispatch_request(request) | |
return response(environ, start_response) | |
def error(self, code, request): | |
return Response('Error %d' % code, status=code) | |
def __call__(self, environ, start_response): | |
return self.wsgi_app(environ, start_response) | |
def run(self, host='127.0.0.1', port=8000): | |
run_simple(host, port, self, use_debugger=True, use_reloader=True) | |
def build_lexicon(self): | |
# route is (regular expression, controller function) | |
# Notice, that we pass along the original regular expression | |
# because we will need to run it again, to grab the matches | |
lexicons = [] | |
for route, action in self.urls: | |
lexicons.append(( | |
plexre(re.sub(r':([^/]+)', r'[^/]+', route)), # convert :parameters into regex | |
( | |
action, | |
re.sub(r':([^/]+)', r'(?P<\1>[^/]+)', route) # :param into named regex | |
) | |
)) | |
self.lexicon = Lexicon(lexicons) | |
def handle_response(self, response): | |
# TODO: strings -> Response objects | |
# dicts -> json Response objects | |
# pass through Response objects | |
# figure out how to wrap yields | |
return Response(response) | |
class Controller(object): | |
def as_resource(self): | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment