Fix the Http router return values

bzr-revno: 2313
This commit is contained in:
Felipe Polo-Wood 2013-12-01 20:58:09 +00:00 committed by Tim Bentley
commit e9848a2653
3 changed files with 95 additions and 26 deletions

View File

@ -128,6 +128,15 @@ from openlp.core.common import AppLocation, Settings, translate
from openlp.core.lib import Registry, PluginStatus, StringContent, image_to_byte from openlp.core.lib import Registry, PluginStatus, StringContent, image_to_byte
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
FILE_TYPES = {
'.html': 'text/html',
'.css': 'text/css',
'.js': 'application/javascript',
'.jpg': 'image/jpeg',
'.gif': 'image/gif',
'.ico': 'image/x-icon',
'.png': 'image/png'
}
class HttpRouter(object): class HttpRouter(object):
@ -346,30 +355,13 @@ class HttpRouter(object):
path = os.path.normpath(os.path.join(self.html_dir, file_name)) path = os.path.normpath(os.path.join(self.html_dir, file_name))
if not path.startswith(self.html_dir): if not path.startswith(self.html_dir):
return self.do_not_found() return self.do_not_found()
ext = os.path.splitext(file_name)[1] content = None
html = None ext, content_type = self.get_content_type(path)
if ext == '.html':
self.send_header('Content-type', 'text/html')
variables = self.template_vars
html = Template(filename=path, input_encoding='utf-8', output_encoding='utf-8').render(**variables)
elif ext == '.css':
self.send_header('Content-type', 'text/css')
elif ext == '.js':
self.send_header('Content-type', 'application/javascript')
elif ext == '.jpg':
self.send_header('Content-type', 'image/jpeg')
elif ext == '.gif':
self.send_header('Content-type', 'image/gif')
elif ext == '.ico':
self.send_header('Content-type', 'image/x-icon')
elif ext == '.png':
self.send_header('Content-type', 'image/png')
else:
self.send_header('Content-type', 'text/plain')
file_handle = None file_handle = None
try: try:
if html: if ext == '.html':
content = html variables = self.template_vars
content = Template(filename=path, input_encoding='utf-8', output_encoding='utf-8').render(**variables)
else: else:
file_handle = open(path, 'rb') file_handle = open(path, 'rb')
log.debug('Opened %s' % path) log.debug('Opened %s' % path)
@ -380,8 +372,22 @@ class HttpRouter(object):
finally: finally:
if file_handle: if file_handle:
file_handle.close() file_handle.close()
self.send_response(200)
self.send_header('Content-type', content_type)
self.end_headers()
return content return content
def get_content_type(self, file_name):
"""
Examines the extension of the file and determines
what the content_type should be, defaults to text/plain
Returns the extension and the content_type
"""
content_type = 'text/plain'
ext = os.path.splitext(file_name)[1]
content_type = FILE_TYPES.get(ext, 'text/plain')
return ext, content_type
def poll(self): def poll(self):
""" """
Poll OpenLP to determine the current slide number and item name. Poll OpenLP to determine the current slide number and item name.

View File

@ -62,7 +62,7 @@ class TestRemoteTab(TestCase):
""" """
Create the UI Create the UI
""" """
fd, self.ini_file = mkstemp('.ini') self.fd, self.ini_file = mkstemp('.ini')
Settings().set_filename(self.ini_file) Settings().set_filename(self.ini_file)
self.application = QtGui.QApplication.instance() self.application = QtGui.QApplication.instance()
Settings().extend_default_settings(__default_settings__) Settings().extend_default_settings(__default_settings__)
@ -76,6 +76,7 @@ class TestRemoteTab(TestCase):
del self.application del self.application
del self.parent del self.parent
del self.form del self.form
os.close(self.fd)
os.unlink(self.ini_file) os.unlink(self.ini_file)
def get_ip_address_default_test(self): def get_ip_address_default_test(self):

View File

@ -37,7 +37,8 @@ from PyQt4 import QtGui
from openlp.core.common import Settings from openlp.core.common import Settings
from openlp.plugins.remotes.lib.httpserver import HttpRouter from openlp.plugins.remotes.lib.httpserver import HttpRouter
from tests.functional import MagicMock from tests.functional import MagicMock, patch
from mock import mock_open
__default_settings__ = { __default_settings__ = {
'remotes/twelve hour': True, 'remotes/twelve hour': True,
@ -50,6 +51,7 @@ __default_settings__ = {
'remotes/ip address': '0.0.0.0' 'remotes/ip address': '0.0.0.0'
} }
TEST_PATH = os.path.abspath(os.path.dirname(__file__))
class TestRouter(TestCase): class TestRouter(TestCase):
""" """
@ -59,7 +61,7 @@ class TestRouter(TestCase):
""" """
Create the UI Create the UI
""" """
fd, self.ini_file = mkstemp('.ini') self.fd, self.ini_file = mkstemp('.ini')
Settings().set_filename(self.ini_file) Settings().set_filename(self.ini_file)
self.application = QtGui.QApplication.instance() self.application = QtGui.QApplication.instance()
Settings().extend_default_settings(__default_settings__) Settings().extend_default_settings(__default_settings__)
@ -70,6 +72,7 @@ class TestRouter(TestCase):
Delete all the C++ objects at the end so that we don't have a segfault Delete all the C++ objects at the end so that we don't have a segfault
""" """
del self.application del self.application
os.close(self.fd)
os.unlink(self.ini_file) os.unlink(self.ini_file)
def password_encrypter_test(self): def password_encrypter_test(self):
@ -109,4 +112,63 @@ class TestRouter(TestCase):
assert function['function'] == mocked_function, \ assert function['function'] == mocked_function, \
'The mocked function should match defined value.' 'The mocked function should match defined value.'
assert function['secure'] == False, \ assert function['secure'] == False, \
'The mocked function should not require any security.' 'The mocked function should not require any security.'
def get_content_type_test(self):
"""
Test the get_content_type logic
"""
# GIVEN: a set of files and their corresponding types
headers = [ ['test.html', 'text/html'], ['test.css', 'text/css'],
['test.js', 'application/javascript'], ['test.jpg', 'image/jpeg'],
['test.gif', 'image/gif'], ['test.ico', 'image/x-icon'],
['test.png', 'image/png'], ['test.whatever', 'text/plain'],
['test', 'text/plain'], ['', 'text/plain'],
[os.path.join(TEST_PATH,'test.html'), 'text/html']]
# WHEN: calling each file type
for header in headers:
ext, content_type = self.router.get_content_type(header[0])
# THEN: all types should match
self.assertEqual(content_type, header[1], 'Mismatch of content type')
def serve_file_without_params_test(self):
"""
Test the serve_file method without params
"""
# GIVEN: mocked environment
self.router.send_response = MagicMock()
self.router.send_header = MagicMock()
self.router.end_headers = MagicMock()
self.router.wfile = MagicMock()
self.router.html_dir = os.path.normpath('test/dir')
self.router.template_vars = MagicMock()
# WHEN: call serve_file with no file_name
self.router.serve_file()
# THEN: it should return a 404
self.router.send_response.assert_called_once_with(404)
self.router.send_header.assert_called_once_with('Content-type','text/html')
self.assertEqual(self.router.end_headers.call_count, 1,
'end_headers called once')
def serve_file_with_valid_params_test(self):
"""
Test the serve_file method with an existing file
"""
# GIVEN: mocked environment
self.router.send_response = MagicMock()
self.router.send_header = MagicMock()
self.router.end_headers = MagicMock()
self.router.wfile = MagicMock()
self.router.html_dir = os.path.normpath('test/dir')
self.router.template_vars = MagicMock()
with patch('openlp.core.lib.os.path.exists') as mocked_exists, \
patch('builtins.open', mock_open(read_data='123')):
mocked_exists.return_value = True
# WHEN: call serve_file with an existing html file
self.router.serve_file(os.path.normpath('test/dir/test.html'))
# THEN: it should return a 200 and the file
self.router.send_response.assert_called_once_with(200)
self.router.send_header.assert_called_once_with(
'Content-type','text/html')
self.assertEqual(self.router.end_headers.call_count, 1,
'end_headers called once')