server/server.py
author Eugen Sawin <sawine@me73.com>
Sun, 11 Dec 2011 04:30:28 +0100
changeset 11 4d3f6e49e8fc
parent 10 ab694dc54515
permissions -rwxr-xr-x
Basic HTTP handling.
     1 #! /usr/bin/env python3
     2 """
     3 Name: Machine Server
     4 Author: Eugen Sawin <sawine@me73.com>
     5 """
     6 
     7 import socketserver
     8 import logging
     9 import os.path
    10 from urllib.parse import urlparse
    11 from argparse import ArgumentParser
    12 from http.server import BaseHTTPRequestHandler, HTTPServer
    13 
    14 ENCODING = "utf-8"
    15 
    16 def parse_args():
    17     parser = ArgumentParser(description="")
    18     parser.add_argument("-p", type=int, default=8080, help="port")
    19     parser.add_argument("-a", default="localhost", help="host address")
    20     parser.add_argument("-l", default="log/server.log", help="log file")
    21     parser.add_argument("-d", default="../client", help="http docs path")
    22     return parser.parse_args()	
    23 
    24 
    25 def main():
    26     args = parse_args()
    27     logging.basicConfig(filename=args.l, level=logging.DEBUG,
    28                         format="[%(levelname)s@%(asctime)s] %(message)s",
    29                         datefmt="%d.%m.%Y %I:%M:%S")
    30     server = Server(args.a, args.p, args.d, GetHandler)
    31     server.run()
    32 
    33 
    34 class GetHandler(BaseHTTPRequestHandler):
    35 
    36     def do_GET(self):
    37         request = Request(self.path, self.server.docs_path)
    38         logging.info("Request: %s" % request)
    39         code, content_type, data = request()
    40         self.send_response(code)       
    41         self.send_header("Content-type", content_type)
    42         self.end_headers()
    43         self.wfile.write(data)
    44         
    45     def log_message(self, format, *args):
    46         pass
    47 
    48 		
    49 class Server(HTTPServer):
    50 
    51     def __init__(self, host, port, docs_path, handler):
    52         HTTPServer.__init__(self, (host, port), handler)
    53         self.host = host
    54         self.port = port
    55         self.docs_path = docs_path
    56 
    57     def run(self):
    58         logging.info("Server ready and listening at port %i." % self.port)
    59         self.serve_forever()
    60 
    61 
    62 class Request:
    63 
    64     _request_types = {"help": []}
    65 
    66     @classmethod
    67     def _content_type(cls, doc):
    68         if doc.endswith(".html"):
    69             return "text/html"
    70         elif doc.endswith(".css"):
    71             return "text/css"
    72         elif doc.endswith(".js"):
    73             return "application/javascript"
    74         else:
    75             return "text/plain"
    76             
    77     def __init__(self, query, docs_path):       
    78         self.args = {}
    79         self.docs_path = docs_path
    80         self.parsed = urlparse(query)     
    81         if self.parsed.query == "":
    82             self.__class__ = WebRequest     
    83             self.args["doc"] = self.parsed.path
    84         else:            
    85             com = self.parsed.path.strip("/")
    86             self.args = dict([q.split("=") for q in self.parsed.query.split("&")])           
    87 
    88     def __str__(self):
    89         return "%s(%s)" % (str(self.__class__).partition(".")[-1].rstrip("'>"),
    90                            ", ".join(["%s: %s" % (k, str(v))
    91                                       for k, v in self.args.items()]))
    92 
    93 
    94 class WebRequest(Request):
    95 
    96     def __call__(self):
    97         if self.args["doc"] == "/":
    98             self.args["doc"] = "/machine.html"
    99         content_type = self._content_type(self.args["doc"])
   100         data = ""
   101         rel_path = self.docs_path + self.args["doc"]
   102         if os.path.exists(rel_path):
   103             data = open(rel_path).read()
   104             code = 200
   105         else:
   106             code = 404
   107         return (code, content_type, bytes(data, ENCODING))
   108 
   109 
   110 if __name__ == "__main__":
   111 	main()
   112