Added pid file writing.
1 #! /usr/bin/env python3
4 Author: Eugen Sawin <sawine@me73.com>
17 from operator import itemgetter
18 from urllib.parse import urlparse
19 from urllib.request import urlopen
20 from tempfile import NamedTemporaryFile
21 from http.server import BaseHTTPRequestHandler, HTTPServer
22 from pseudoword import Database
25 from argparse import ArgumentParser
27 from external.argparse import ArgumentParser
32 parser = ArgumentParser(description='')
33 parser.add_argument('-p', type=int, default=8080, help='port')
34 parser.add_argument('-a', default='localhost', help='host address')
35 parser.add_argument('-l', default='log/server.log', help='log file')
36 parser.add_argument('-w', default='data/names', help='word database')
37 parser.add_argument('-d', default='httpdocs', help='http docs path')
38 parser.add_argument('--pid', default=None, help='pid file')
39 return parser.parse_args()
44 logging.basicConfig(filename=args.l, level=logging.DEBUG,
45 format='[%(levelname)s@%(asctime)s] %(message)s',
46 datefmt='%d.%m.%Y %I:%M:%S')
48 with open(args.pid, 'w') as f:
49 f.write(str(os.getpid()))
51 server = Server(args.a, args.p, args.d, db, GetHandler)
55 class GetHandler(BaseHTTPRequestHandler):
58 request = Request(self.path, self.server.docs_path, self.server.db)
59 logging.info('Request: %s' % request)
60 code, content_type, data = request()
61 self.send_response(code)
62 self.send_header('Content-type', content_type)
64 self.wfile.write(data)
66 def log_message(self, format, *args):
70 class Server(HTTPServer):
72 def __init__(self, host, port, docs_path, db, handler):
73 HTTPServer.__init__(self, (host, port), handler)
76 self.docs_path = docs_path
80 logging.info('Server ready and listening at port {0}.'.format(self.port))
87 def _content_type(cls, doc):
88 if doc.endswith('.html'):
90 elif doc.endswith('.css'):
92 elif doc.endswith('.js'):
93 return 'application/javascript'
94 elif doc.endswith('.ttf'):
95 return 'application/octet-stream'
99 def __init__(self, query, docs_path, db):
100 self.docs_path = docs_path
102 self.parsed = urlparse(query)
104 if len(self.parsed.query):
105 self.args = dict([a.split('=') for a in self.parsed.query.split('&')])
106 if self.parsed.path[1:] in commands:
107 self.__class__ = commands[self.parsed.path[1:]]
109 self.__class__ = WebRequest
110 self.args['doc'] = self.parsed.path
113 return '{0}({1})'.format(str(self.__class__).partition('.')[-1].rstrip('">'),
114 ', '.join(['{0}: {1}'.format(k, str(v))
115 for k, v in self.args.items()]))
118 def client_rating(rating):
119 return int(rating * 1000)
122 class WordsRequest(Request):
125 w1, w2 = self.db.pick_words()
126 data = '{{"words":[["{w1}", {r1}], ["{w2}", {r2}]]}}'.format(w1=w1[0],
130 return (200, 'application/javascript', bytes(data, ENCODING))
133 class RateRequest(Request):
138 w3, w4 = self.db.rate(w3, w4)
139 w1, w2 = self.db.pick_words()
140 data = '{{"words":[["{w1}",{r1}],["{w2}",{r2}],'.format(w1=w1[0], r1=client_rating(w1[1]),
141 w2=w2[0], r2=client_rating(w2[1]))
142 data += '["{w3}",{r3}],["{w4}",{r4}]]}}'.format(w3=w3[0], r3=client_rating(w3[1]),
143 w4=w4[0], r4=client_rating(w4[1]))
144 return (200, 'application/javascript', bytes(data, ENCODING))
147 commands = {'words': WordsRequest,
151 class WebRequest(Request):
154 if self.args['doc'] == '/':
155 self.args['doc'] = '/index.html'
156 content_type = self._content_type(self.args['doc'])
157 data = bytes('', ENCODING)
158 rel_path = self.docs_path + self.args['doc']
159 if os.path.exists(rel_path):
160 with open(rel_path, 'r+b') as f:
165 return (code, content_type, data)
168 if __name__ == '__main__':