From b81bf41015df0c1a8fd9f15467f25b0e28c8cab7 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 24 Apr 2019 13:35:56 -0400 Subject: [PATCH] facilitate testing on localhost for CloudStorage --- CherryPy.conf | 11 ++++++++--- CherryPyApp.py | 25 ++++++++++++------------- CloudStorage.py | 11 ++++++++--- templates/index.html | 19 ------------------- test/index.html | 19 +++++++++++++++++++ test/test.pdf | Bin 0 -> 13295 bytes 6 files changed, 47 insertions(+), 38 deletions(-) delete mode 100644 templates/index.html create mode 100644 test/index.html create mode 100644 test/test.pdf diff --git a/CherryPy.conf b/CherryPy.conf index 31fb9ff..05614d7 100644 --- a/CherryPy.conf +++ b/CherryPy.conf @@ -12,7 +12,7 @@ server.socket_queue_size: 10 server.thread_pool: 20 server.thread_pool_max: 20 -# change host params in .autocat3 or /etc/autocat3.conf files +# change host and postgres params in .autocat3 or /etc/autocat3.conf files pghost: 'localhost' pgport: 5432 pgdatabase: 'gutenberg' @@ -20,6 +20,7 @@ pguser: 'postgres' host: 'www.gutenberg.org' host_mobile: 'm.gutenberg.org' +host_https: 1 file_host: 'www.gutenberg.org' sqlalchemy.pool_size: 20 @@ -72,8 +73,8 @@ tools.sessions.on: True tools.sessions.table_name = "cherrypy.sessions" tools.sessions.timeout: 30 tools.sessions.path: '/' -# change host in .autocat3 or /etc/autocat3.conf files tools.sessions.domain: 'gutenberg.org' +#tools.sessions.domain: 'localhost' tools.expires.on: True tools.expires.secs: 0 @@ -81,4 +82,8 @@ tools.expires.force: True [/index.html] tools.staticfile.on: True -tools.staticfile.filename: CherryPyApp.install_dir + '/templates/index.html' +tools.staticfile.filename: CherryPyApp.install_dir + '/test/index.html' + +[/test.pdf] +tools.staticfile.on: True +tools.staticfile.filename: CherryPyApp.install_dir + '/test/test.pdf' diff --git a/CherryPyApp.py b/CherryPyApp.py index 793f206..099da2a 100644 --- a/CherryPyApp.py +++ b/CherryPyApp.py @@ -54,10 +54,7 @@ plugins.Timer = Timer.TimerPlugin install_dir = os.path.dirname (os.path.abspath (__file__)) CHERRYPY_CONFIG = os.path.join(install_dir, 'CherryPy.conf') -LOCAL_CONFIG = ( - os.path.join(install_dir, 'CherryPy.conf'), - os.path.expanduser('~/.autocat3'), '/etc/autocat3.conf' -) +LOCAL_CONFIG = [os.path.expanduser('~/.autocat3'), '/etc/autocat3.conf'] class MyRoutesDispatcher (cherrypy.dispatch.RoutesDispatcher): """ Dispatcher that tells us the matched route. @@ -92,13 +89,6 @@ def main (): config_filename = None cherrypy.config.update (CHERRYPY_CONFIG) - for config_filename in LOCAL_CONFIG: - try: - cherrypy.config.update (config_filename) - break - except IOError: - pass - # Rotating Logs # @@ -121,6 +111,8 @@ def main (): h.setLevel (logging.DEBUG) h.setFormatter (cherrypy._cplogging.logfmt) cherrypy.log.access_log.addHandler (h) + + if not cherrypy.config['daemonize']: ch = logging.StreamHandler () @@ -132,8 +124,15 @@ def main (): # cherrypy.log ('*' * 80, context = 'ENGINE', severity = logging.INFO) - cherrypy.log ("Using config file '%s'." % config_filename, + cherrypy.log ("Using config file '%s'." % CHERRYPY_CONFIG, context = 'ENGINE', severity = logging.INFO) + for config_filename in LOCAL_CONFIG: + try: + cherrypy.config.update (config_filename) + cherrypy.log ('loaded %s' % config_filename, context = 'ENGINE', severity = logging.INFO) + break + except IOError: + pass # after cherrypy.config is parsed Formatters.init () @@ -308,7 +307,7 @@ def main (): cherrypy.log ("Mounting root", context = 'ENGINE', severity = logging.INFO) - app = cherrypy.tree.mount (root = None, config = config_filename) + app = cherrypy.tree.mount (root = None, config = CHERRYPY_CONFIG) app.merge ({'/': {'request.dispatch': d}}) return app diff --git a/CloudStorage.py b/CloudStorage.py index f9ec8e6..054b481 100644 --- a/CloudStorage.py +++ b/CloudStorage.py @@ -65,9 +65,10 @@ class CloudOAuth2Session (requests_oauthlib.OAuth2Session): # pylint: disable=R0 prefix = self.name_prefix host = config['file_host'] + host_https = config['host_https'] urlgen = routes.URLGenerator (cherrypy.routes_mapper, { 'HTTP_HOST': host, - 'HTTPS': 1 + 'HTTPS': host_https }) client_id = config[prefix + '_client_id'] @@ -297,7 +298,11 @@ class EbookMetaData (object): def get_source_url (self): """ Return the url of the ebook file on gutenberg.org. """ - + protocol = 'https://' if cherrypy.config['host_https'] else 'http://' + if self.id == 99999: + # test filename + return urllib.parse.urljoin ( + protocol + str(cherrypy.config['file_host']) , 'test.pdf') return urllib.parse.urljoin ( - 'https://' + cherrypy.config['file_host'], + protocol + cherrypy.config['file_host'], 'ebooks/%d.%s' % (self.id, self.filetype)) diff --git a/templates/index.html b/templates/index.html deleted file mode 100644 index 7d6870e..0000000 --- a/templates/index.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - -
-

Download Test

-

-Dropbox -

-

-Google Drive -

-

-OneDrive -

-
- - \ No newline at end of file diff --git a/test/index.html b/test/index.html new file mode 100644 index 0000000..4267333 --- /dev/null +++ b/test/index.html @@ -0,0 +1,19 @@ + + + + + +
+

Download Test

+

+Dropbox +

+

+Google Drive +

+

+OneDrive +

+
+ + \ No newline at end of file diff --git a/test/test.pdf b/test/test.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d2b1fd86a2e8302e1950b151082f2006b5cdf951 GIT binary patch literal 13295 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