peerlink/example/server.py

135 lines
3.5 KiB
Python
Executable File

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, print_function
import json
import os
import signal
import mimetypes
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.web import Application
import tornado
import websocket
from websocket import trigger_event
import state
from tasks import Tasks
import link
import logging
logger = logging.getLogger('server')
root_dir = os.path.normpath(os.path.abspath(os.path.dirname(__file__)))
STATIC_PATH = os.path.join(root_dir, 'static')
class BaseHandler(tornado.web.RequestHandler):
def serve_static(self, path, mimetype=None, include_body=True):
if not mimetype:
mimetype = mimetypes.guess_type(path)[0]
logging.debug('serve %s', path)
if os.path.exists(path):
self.set_header('Content-Type', mimetype)
self.set_header('Content-Length', str(os.stat(path).st_size))
if include_body:
with open(path) as fd:
self.write(fd.read())
else:
self.set_status(404)
return
def render_json(self, response):
response = json.dumps(response)
self.set_header('Content-Type', 'application/json')
self.set_header('Content-Length', str(len(response)))
self.write(response)
self.finish()
class RemoteHandler(BaseHandler):
def post(self, action):
data = json.loads(self.request.body)
response = {}
print ('GOT remote request', action, data)
if action == 'info':
response = state.info
elif action == 'message':
data['from'] = self.request.headers['From']
trigger_event(action, data)
else:
response = {'error': 'unknown action'}
return self.render_json(response)
class MainHandler(BaseHandler):
def get(self, path):
path = path[1:]
if not path:
path = 'index.html'
path = os.path.join(STATIC_PATH, path)
self.serve_static(path)
def post(self, path):
action = path.split('/')[1]
data = json.loads(self.request.body)
response = {}
if action in ('info', 'ping'):
if 'id' in data:
id = data['id']
del data['id']
response = link.remote_json(id, action, data)
return self.render_json(response)
if __name__ == '__main__':
address = ''
port = int(os.environ.get('PORT', 8000))
logging.basicConfig(level=logging.DEBUG)
options = {
'debug': True,
}
handlers = [
(r'/ws', websocket.Handler),
(r"/remote/(.*)", RemoteHandler),
(r"(.*)", MainHandler),
]
http_server = HTTPServer(Application(handlers, **options))
http_server.listen(port, address)
state.tasks = Tasks()
state.main = IOLoop.instance()
state._status = PeriodicCallback(lambda: state.info.update(link.post('info')), 60000)
state._status.start()
if ':' in address:
host = '[%s]' % address
elif not address:
host = '[::1]'
else:
host = address
url = 'http://%s:%s/' % (host, port)
link.add('chat', url + 'remote/')
state.info = link.post('info')
print('listening at %s' % url)
def shutdown():
state.tasks.join()
http_server.stop()
signal.signal(signal.SIGTERM, shutdown)
try:
state.main.start()
except:
print('shutting down...')
shutdown()