Initial routing.

This commit is contained in:
Raoul Snyman 2011-02-24 18:35:18 +02:00
parent bc2f7547cc
commit 3d2ac84739
1 changed files with 62 additions and 10 deletions

View File

@ -27,6 +27,7 @@
import logging import logging
import os import os
import urlparse import urlparse
import re
try: try:
import json import json
@ -40,6 +41,18 @@ from openlp.core.utils import AppLocation
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class HttpResponse(object):
"""
A simple object to encapsulate a pseudo-http response.
"""
content = u''
mimetype = None
def __init__(self, content=u'', mimetype=None):
self.content = content
self.mimetype = mimetype
class HttpServer(object): class HttpServer(object):
""" """
Ability to control OpenLP via a webbrowser Ability to control OpenLP via a webbrowser
@ -144,6 +157,12 @@ class HttpConnection(object):
socket.peerAddress().toString()) socket.peerAddress().toString())
self.socket = socket self.socket = socket
self.parent = parent self.parent = parent
self.routes = [
(u'^/$', self.serve_file, [u'filename'], {u'filename': u''}),
(r'^/files/(?P<filename>.*)$', self.serve_file, [u'filename'], None),
(r'^/send/(?P<name>.*)$', self.process_event, [u'name', u'parameters'], None),
(r'^/request/(?P<name>.*)$', self.process_request, [u'name', u'parameters'], None)
]
QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'readyRead()'), QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'readyRead()'),
self.ready_read) self.ready_read)
QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'disconnected()'), QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'disconnected()'),
@ -158,11 +177,35 @@ class HttpConnection(object):
data = unicode(self.socket.readLine()) data = unicode(self.socket.readLine())
log.debug(u'received: ' + data) log.debug(u'received: ' + data)
words = data.split(u' ') words = data.split(u' ')
html = None response = None
mimetype = None
if words[0] == u'GET': if words[0] == u'GET':
url = urlparse.urlparse(words[1]) url = urlparse.urlparse(words[1])
params = self.load_params(url.query) params = self.load_params(url.query)
# Loop through the routes we set up earlier and execute them
for route, func, kws, defaults in self.routes:
match = re.match(route, url.path)
if match:
log.debug(u'Matched on "%s" from "%s"', route, url.path)
log.debug(u'Groups: %s', match.groups())
kwargs = {}
# Loop through all the keywords supplied
for keyword in kws:
groups = match.groupdict()
if keyword in groups:
# If we find a valid keyword in our URL, use it
kwargs[keyword] = groups[keyword]
elif defaults and keyword in defaults:
# Otherwise, if we have defaults, use them
kwargs[keyword] = defaults[keyword]
else:
# Lastly, set our parameter to None.
kwargs[keyword] = None
if u'parameters' in kwargs:
kwargs[u'parameters'] = params
log.debug(u'Keyword arguments: %s', kwargs)
response = func(**kwargs)
break
"""
folders = url.path.split(u'/') folders = url.path.split(u'/')
if folders[1] == u'': if folders[1] == u'':
mimetype, html = self.serve_file(u'') mimetype, html = self.serve_file(u'')
@ -173,17 +216,21 @@ class HttpConnection(object):
elif folders[1] == u'request': elif folders[1] == u'request':
if self.process_request(folders[2], params): if self.process_request(folders[2], params):
return return
if html: """
if mimetype: if response:
self.send_200_ok(mimetype) if hasattr(response, u'mimetype'):
self.send_200_ok(response.mimetype)
else: else:
self.send_200_ok() self.send_200_ok()
self.socket.write(html) if hasattr(response, u'content'):
self.socket.write(response.content)
else:
self.socket.write(response)
else: else:
self.send_404_not_found() self.send_404_not_found()
self.close() self.close()
def serve_file(self, filename): def serve_file(self, **kwargs):
""" """
Send a file to the socket. For now, just a subset of file types Send a file to the socket. For now, just a subset of file types
and must be top level inside the html folder. and must be top level inside the html folder.
@ -192,6 +239,7 @@ class HttpConnection(object):
Ultimately for i18n, this could first look for xx/file.html before Ultimately for i18n, this could first look for xx/file.html before
falling back to file.html... where xx is the language, e.g. 'en' falling back to file.html... where xx is the language, e.g. 'en'
""" """
filename = kwargs.get(u'filename', u'')
log.debug(u'serve file request %s' % filename) log.debug(u'serve file request %s' % filename)
if not filename: if not filename:
filename = u'index.html' filename = u'index.html'
@ -224,7 +272,7 @@ class HttpConnection(object):
finally: finally:
if file_handle: if file_handle:
file_handle.close() file_handle.close()
return (mimetype, html) return HttpResponse(content=html, mimetype=mimetype)
def load_params(self, query): def load_params(self, query):
""" """
@ -237,12 +285,14 @@ class HttpConnection(object):
else: else:
return params['q'] return params['q']
def process_event(self, event, params): def process_event(self, **kwargs):
""" """
Send a signal to openlp to perform an action. Send a signal to openlp to perform an action.
Currently lets anything through. Later we should restrict and perform Currently lets anything through. Later we should restrict and perform
basic parameter checking, otherwise rogue clients could crash openlp basic parameter checking, otherwise rogue clients could crash openlp
""" """
event = kwargs.get(u'name')
params = kwargs.get(u'parameters')
log.debug(u'Processing event %s' % event) log.debug(u'Processing event %s' % event)
if params: if params:
Receiver.send_message(event, params) Receiver.send_message(event, params)
@ -250,7 +300,7 @@ class HttpConnection(object):
Receiver.send_message(event) Receiver.send_message(event)
return json.dumps([u'OK']) return json.dumps([u'OK'])
def process_request(self, event, params): def process_request(self, **kwargs):
""" """
Client has requested data. Send the signal and parameters for openlp Client has requested data. Send the signal and parameters for openlp
to handle, then listen out for a corresponding ``_request`` signal to handle, then listen out for a corresponding ``_request`` signal
@ -267,6 +317,8 @@ class HttpConnection(object):
``params`` ``params``
Parameters sent with the event. Parameters sent with the event.
""" """
event = kwargs.get(u'name')
params = kwargs.get(u'parameters')
log.debug(u'Processing request %s' % event) log.debug(u'Processing request %s' % event)
if not event.endswith(u'_request'): if not event.endswith(u'_request'):
return False return False