openmedialibrary/oml/server.py

217 lines
7.2 KiB
Python
Raw Normal View History

2014-05-04 19:26:43 +02:00
# -*- coding: utf-8 -*-
2014-09-03 00:32:44 +02:00
2024-06-08 13:31:46 +01:00
import asyncio
2014-05-04 19:26:43 +02:00
import os
import sys
import signal
2014-09-05 19:02:19 +02:00
import time
2014-05-22 01:06:08 +02:00
2014-05-04 19:26:43 +02:00
from tornado.ioloop import IOLoop
2024-06-09 14:47:36 +01:00
import tornado.web
from tornado.web import Application
2014-05-04 19:26:43 +02:00
2014-08-12 10:16:57 +02:00
from cache import Cache
from item.handlers import EpubHandler, ReaderHandler, FileHandler
2015-06-06 19:54:44 +02:00
from item.handlers import OMLHandler, UploadHandler
2024-06-09 14:47:36 +01:00
from item.handlers import CropHandler
2014-08-12 10:16:57 +02:00
from item.icons import IconHandler
2014-08-09 23:40:05 +02:00
import db
2014-05-04 19:26:43 +02:00
import node.server
2014-05-19 22:14:24 +02:00
import oxtornado
import downloads
2014-08-12 10:16:57 +02:00
import settings
import setup
import state
2014-05-28 17:36:26 +02:00
import tasks
2014-08-12 10:16:57 +02:00
import websocket
2019-01-21 10:28:08 +05:30
import ui_websocket
2016-01-12 20:30:51 +05:30
import update
2014-05-22 00:50:59 +02:00
2014-08-12 10:16:57 +02:00
import logging
2014-05-22 01:06:08 +02:00
2015-11-29 15:56:38 +01:00
logger = logging.getLogger(__name__)
2015-03-22 19:34:42 +05:30
2024-06-09 14:47:36 +01:00
class StaticFileHandler(tornado.web.StaticFileHandler):
def get_content_type(self):
if self.request.path.split('?')[0].endswith('.mjs'):
return 'application/javascript'
return super().get_content_type()
2014-05-22 01:06:08 +02:00
class MainHandler(OMLHandler):
def get(self, path):
2015-03-08 17:56:38 +05:30
version = settings.MINOR_VERSION.split('-')[0]
2014-09-05 19:02:19 +02:00
if version == 'git':
version = int(time.mktime(time.gmtime()))
2016-01-12 20:30:51 +05:30
path = os.path.join(settings.static_path, 'html', 'oml.html')
with open(path) as fd:
content = fd.read()
content = content.replace('.js?1', '.js?%s' % version)
if state.update:
content = content.replace('oml.js', 'oml.update.js')
2014-09-05 19:02:19 +02:00
self.set_header('Content-Type', 'text/html')
self.set_header('Content-Length', str(len(content)))
2016-01-14 09:33:26 +05:30
self.set_header('Cache-Control', 'no-cache, no-store, must-revalidate')
self.set_header('Pragma', 'no-cache')
self.set_header('Expires', '0')
2014-09-05 19:02:19 +02:00
self.write(content)
2014-05-04 19:26:43 +02:00
def log_request(handler):
if settings.DEBUG_HTTP:
if handler.get_status() < 400:
log_method = logger.info
elif handler.get_status() < 500:
log_method = logger.warning
else:
log_method = logger.error
request_time = 1000.0 * handler.request.request_time()
log_method("%d %s %.2fms", handler.get_status(),
handler._request_summary(), request_time)
2015-12-02 22:05:23 +01:00
2024-06-08 13:31:46 +01:00
async def shutdown():
state.shutdown = True
if state.tor:
state.tor._shutdown = True
if state.nodes:
logger.debug('shutdown nodes')
2024-06-08 13:31:46 +01:00
await state.nodes.join()
if state.downloads:
logger.debug('shutdown downloads')
state.downloads.join()
logger.debug('shutdown http_server')
if state.tasks:
logger.debug('shutdown tasks')
state.tasks.join()
2016-02-10 19:32:32 +05:30
if state.update:
logger.debug('shutdown updates')
state.update.join()
if state.node:
state.node.stop()
if state.tor:
logger.debug('shutdown tor')
state.tor.shutdown()
2016-02-10 19:32:32 +05:30
for peer in state.peers:
state.peers[peer].join()
if state.PID and os.path.exists(state.PID):
logger.debug('remove %s', state.PID)
os.unlink(state.PID)
2014-05-04 19:26:43 +02:00
def run():
PID = sys.argv[2] if len(sys.argv) > 2 else None
if len(sys.argv) > 3 and sys.argv[2] == 'debug':
PID = sys.argv[3]
debug = True
else:
debug = False
2014-05-04 19:26:43 +02:00
2019-01-17 16:00:22 +05:30
log_format = '%(asctime)s:%(levelname)s:%(name)s:%(message)s'
if debug:
logging.basicConfig(level=logging.DEBUG, format=log_format)
2015-03-07 19:17:12 +05:30
else:
logging.basicConfig(level=logging.DEBUG,
handlers=[logging.FileHandler(settings.log_path, 'w', 'utf-8')],
format=log_format)
2014-05-04 19:26:43 +02:00
options = {
2014-05-26 12:10:56 +02:00
'debug': False,
'log_function': log_request,
2014-05-25 12:59:43 +02:00
'gzip': True
2014-05-04 19:26:43 +02:00
}
2019-01-17 16:00:22 +05:30
common_handlers = [
(r'/(favicon.ico)', StaticFileHandler, {'path': settings.static_path}),
2015-03-08 00:28:24 +05:30
(r'/static/oxjs/(.*)', StaticFileHandler, {'path': os.path.join(settings.base_dir, '..', 'oxjs')}),
2015-03-14 13:05:15 +05:30
(r'/static/cbr.js/(.*)', StaticFileHandler, {'path': os.path.join(settings.base_dir, '..', 'reader', 'cbr.js')}),
2015-03-08 01:38:57 +05:30
(r'/static/epub.js/(.*)', StaticFileHandler, {'path': os.path.join(settings.base_dir, '..', 'reader', 'epub.js')}),
(r'/static/pdf.js/(.*)', StaticFileHandler, {'path': os.path.join(settings.base_dir, '..', 'reader', 'pdf.js')}),
(r'/static/txt.js/(.*)', StaticFileHandler, {'path': os.path.join(settings.base_dir, '..', 'reader', 'txt.js')}),
(r'/static/(.*)', StaticFileHandler, {'path': settings.static_path}),
2014-08-09 18:33:59 +02:00
(r'/(.*)/epub/(.*)', EpubHandler),
(r'/(.*?)/reader/', ReaderHandler),
2015-03-14 13:05:15 +05:30
(r'/(.*?)/cbr/', FileHandler),
2014-08-09 18:33:59 +02:00
(r'/(.*?)/pdf/', FileHandler),
(r'/(.*?)/txt/', FileHandler),
2014-12-13 21:01:54 +01:00
(r'/(.*?)/get/', FileHandler, {
2015-05-14 13:08:16 +02:00
'attachment': True
2014-12-13 21:01:54 +01:00
}),
2024-06-09 14:47:36 +01:00
(r'/(.*)/2048p(\d*),(\d*),(\d*),(\d*),(\d*).jpg', CropHandler),
2014-08-09 18:33:59 +02:00
(r'/(.*)/(cover|preview)(\d*).jpg', IconHandler),
2019-01-17 16:00:22 +05:30
]
handlers = common_handlers + [
2015-06-06 19:54:44 +02:00
(r'/api/upload/', UploadHandler, dict(context=db.session)),
2014-08-09 23:40:05 +02:00
(r'/api/', oxtornado.ApiHandler, dict(context=db.session)),
2019-01-21 10:28:08 +05:30
(r'/ui_socket', ui_websocket.Handler),
2014-05-04 19:26:43 +02:00
(r'/ws', websocket.Handler),
2014-08-09 18:33:59 +02:00
(r"(.*)", MainHandler),
2014-05-04 19:26:43 +02:00
]
2019-01-17 16:00:22 +05:30
public_handlers = common_handlers + [
(r'/api/', oxtornado.ApiHandler, dict(context=db.session, public=True)),
(r'/ws', websocket.Handler, dict(public=True)),
(r"(.*)", MainHandler),
]
2014-05-04 19:26:43 +02:00
2016-01-18 10:53:59 +05:30
setup.create_db()
http_server = Application(handlers, **options)
max_buffer_size = 2*1024*1024*1024
http_server.listen(settings.server['port'], settings.server['address'], max_buffer_size=max_buffer_size)
2014-05-17 02:14:15 +02:00
2019-01-17 16:00:22 +05:30
# public server
if settings.preferences.get('enableReadOnlyService'):
public_port = settings.server.get('public_port')
public_address = settings.server['public_address']
if public_port:
public_server = Application(public_handlers, **options)
public_server.listen(public_port, public_address)
2019-01-17 16:00:22 +05:30
2014-05-04 19:26:43 +02:00
if PID:
with open(PID, 'w') as pid:
pid.write('%s' % os.getpid())
2016-01-12 20:30:51 +05:30
state.update = update.update_available()
state.PID = PID
state.http_server = http_server
2014-05-17 02:14:15 +02:00
state.main = IOLoop.instance()
2016-01-05 20:42:25 +05:30
state.cache = Cache(ttl=60)
2014-05-17 02:14:15 +02:00
2014-05-04 19:26:43 +02:00
def start_node():
import nodes
import tor
2015-12-01 00:26:35 +01:00
import bandwidth
state.bandwidth = bandwidth.Bandwidth()
state.tor = tor.Tor()
state.nodes = nodes.Nodes()
state.node = node.server.start()
2017-06-03 22:50:14 +02:00
2015-12-02 22:05:23 +01:00
def publish():
if not state.tor.is_online():
2016-01-09 11:16:35 +05:30
state.main.call_later(10, publish)
else:
nodes.publish_node()
2015-12-02 22:05:23 +01:00
state.main.add_callback(publish)
2016-01-24 16:04:29 +05:30
state.main.call_later(10, lambda: state.tasks.queue('scanimport'))
2016-01-12 20:30:51 +05:30
if not state.update:
state.downloads = downloads.Downloads()
2016-01-12 20:30:51 +05:30
state.tasks = tasks.Tasks()
state.main.add_callback(start_node)
else:
2016-02-10 19:32:32 +05:30
state.update = update.Update()
2016-01-12 20:30:51 +05:30
2014-05-14 11:57:11 +02:00
if ':' in settings.server['address']:
host = '[%s]' % settings.server['address']
elif not settings.server['address']:
host = '127.0.0.1'
2014-05-14 11:57:11 +02:00
else:
host = settings.server['address']
url = 'http://%s:%s/' % (host, settings.server['port'])
2014-08-11 13:08:28 +02:00
print('open browser at %s' % url)
2015-03-22 19:34:42 +05:30
logger.debug('Starting OML %s at %s', settings.VERSION, url)
2024-06-08 13:31:46 +01:00
signal.signal(signal.SIGTERM, lambda _, __: sys.exit(0))
2014-08-09 20:32:41 +02:00
try:
state.main.start()
except:
2014-08-09 23:40:05 +02:00
print('shutting down...')
2024-06-08 13:31:46 +01:00
asyncio.run(shutdown())