1# 2# Copyright OpenEmbedded Contributors 3# 4# SPDX-License-Identifier: MIT 5# 6 7import http.server 8import logging 9import multiprocessing 10import os 11import signal 12from socketserver import ThreadingMixIn 13 14class HTTPServer(ThreadingMixIn, http.server.HTTPServer): 15 16 def server_start(self, root_dir, logger): 17 os.chdir(root_dir) 18 self.logger = logger 19 self.serve_forever() 20 21class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler): 22 23 def log_message(self, format_str, *args): 24 self.server.logger.info(format_str, *args) 25 26class HTTPService: 27 28 def __init__(self, root_dir, host='', port=0, logger=None): 29 self.root_dir = root_dir 30 self.host = host 31 self.port = port 32 if logger: 33 self.logger = logger.getChild("HTTPService") 34 else: 35 self.logger = logging.getLogger("HTTPService") 36 37 def start(self): 38 if not os.path.exists(self.root_dir): 39 self.logger.info("Not starting HTTPService for directory %s which doesn't exist" % (self.root_dir)) 40 return 41 42 self.server = HTTPServer((self.host, self.port), HTTPRequestHandler) 43 if self.port == 0: 44 self.port = self.server.server_port 45 self.process = multiprocessing.Process(target=self.server.server_start, args=[self.root_dir, self.logger]) 46 47 def handle_error(self, request, client_address): 48 import traceback 49 exception = traceback.format_exc() 50 self.logger.warn("Exception when handling %s: %s" % (request, exception)) 51 self.server.handle_error = handle_error 52 53 # The signal handler from testimage.bbclass can cause deadlocks here 54 # if the HTTPServer is terminated before it can restore the standard 55 #signal behaviour 56 orig = signal.getsignal(signal.SIGTERM) 57 signal.signal(signal.SIGTERM, signal.SIG_DFL) 58 self.process.start() 59 signal.signal(signal.SIGTERM, orig) 60 61 if self.logger: 62 self.logger.info("Started HTTPService for %s on %s:%s" % (self.root_dir, self.host, self.port)) 63 64 65 def stop(self): 66 if hasattr(self, "server"): 67 self.server.server_close() 68 if hasattr(self, "process"): 69 self.process.terminate() 70 self.process.join() 71 if self.logger: 72 self.logger.info("Stopped HTTPService on %s:%s" % (self.host, self.port)) 73 74if __name__ == "__main__": 75 import sys, logging 76 77 logger = logging.getLogger(__name__) 78 logging.basicConfig(level=logging.DEBUG) 79 httpd = HTTPService(sys.argv[1], port=8888, logger=logger) 80 httpd.start() 81