1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright (C) 2024 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import logging 17import argparse 18import http.server 19import mimetypes 20import os 21import socket 22import socketserver 23import threading 24import time 25import urllib 26import webbrowser 27import signal 28 29logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') 30 31 32class StaticFileServerHandler(http.server.SimpleHTTPRequestHandler): 33 def do_GET(self): 34 if self.path == '/get_filename': 35 self.handle_get_filename() 36 elif self.path.startswith('/download'): 37 self.handle_download() 38 else: 39 super().do_GET() 40 41 def guess_type(self, path): 42 base, ext = os.path.splitext(path) 43 mime_type = mimetypes.guess_type(path)[0] or 'application/octet-stream' 44 if ext.lower() == '.js': 45 mime_type = 'application/javascript' 46 return mime_type 47 48 def handle_download(self): 49 query_params = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query) 50 filename = query_params.get('filename', [None])[0] 51 if filename: 52 file_to_load = os.path.join(os.path.dirname(self.server.file_to_load), filename) 53 if os.path.exists(file_to_load): 54 file_to_load = os.path.abspath(file_to_load) 55 self.send_response(200) 56 self.send_header('Content-Type', 'application/octet-stream') 57 self.send_header('Content-Disposition', f'attachment; filename="{filename}"') 58 self.end_headers() 59 60 with open(file_to_load, 'rb') as file: 61 self.wfile.write(file.read()) 62 else: 63 self.send_error(404, "File not found") 64 else: 65 self.send_error(400, "Filename parameter is required") 66 67 def handle_get_filename(self): 68 filename = os.path.basename(self.server.file_to_load) 69 self.send_response(200) 70 self.send_header('Content-Type', 'text/plain') 71 self.end_headers() 72 self.wfile.write(filename.encode('utf-8')) 73 74 75class SimpleServer(socketserver.ThreadingTCPServer): 76 allow_reuse_address = True 77 78 def __init__(self, server_address, RequestHandlerClass, file_to_load): 79 self.file_to_load = file_to_load 80 super().__init__(server_address, RequestHandlerClass) 81 82 83def open_webpage(url): 84 webbrowser.open_new_tab(url) 85 86 87def start_server_with_webpage_opening(): 88 parser = argparse.ArgumentParser(description="Start a simple HTTP server.") 89 parser.add_argument('--port', '-p', type=int, default=9000, help='Specify the port number.') 90 parser.add_argument('--file', type=str, help='Specify a file to handle.') 91 args = parser.parse_args() 92 93 if not args.file: 94 logging.error("No file specified using --file option.") 95 return 96 97 if not os.path.exists(args.file): 98 logging.error(f"The file '{args.file}' does not exist.") 99 return 100 101 server_address = ('', args.port) 102 with SimpleServer(server_address, StaticFileServerHandler, args.file) as httpd: 103 logging.info(f"Serving HTTP on port {args.port}...") 104 logging.info(f"Loading file from path: {args.file}") 105 server_thread = threading.Thread(target=httpd.serve_forever) 106 server_thread.daemon = True 107 server_thread.start() 108 time.sleep(1) 109 url = f'http://localhost:{args.port}/index.html' 110 open_webpage(url) 111 time.sleep(2) 112 httpd.shutdown() 113 httpd.server_close() 114 115 116if __name__ == '__main__': 117 start_server_with_webpage_opening() 118