http_handler.py (3915B)
1 # mypy: allow-untyped-defs 2 3 import http.client as httplib 4 import sys 5 import logging 6 import traceback 7 8 9 global logger 10 logger = logging.getLogger("wave-api-handler") 11 12 class HttpHandler: 13 def __init__( 14 self, 15 static_handler, 16 sessions_api_handler, 17 tests_api_handler, 18 results_api_handler, 19 devices_api_handler, 20 general_api_handler, 21 http_port, 22 web_root 23 ): 24 self.static_handler = static_handler 25 self.sessions_api_handler = sessions_api_handler 26 self.tests_api_handler = tests_api_handler 27 self.results_api_handler = results_api_handler 28 self.general_api_handler = general_api_handler 29 self.devices_api_handler = devices_api_handler 30 self._http_port = http_port 31 self._web_root = web_root 32 33 def handle_request(self, request, response): 34 response.headers = [ 35 ("Access-Control-Allow-Origin", "*"), 36 ("Access-Control-Allow-Headers", "*"), 37 ("Access-Control-Allow-Methods", "*") 38 ] 39 if request.method == "OPTIONS": 40 return 41 42 path = self._remove_web_root(request.request_path) 43 44 is_api_call = False 45 for index, part in enumerate(path.split("/")): 46 if index > 2: 47 break 48 if part != "api": 49 continue 50 51 is_api_call = True 52 53 if (is_api_call): 54 if request.url_parts.scheme == "https": 55 self._proxy(request, response) 56 return 57 self.handle_api(request, response) 58 else: 59 self.handle_static_file(request, response) 60 61 def handle_api(self, request, response): 62 path = self._remove_web_root(request.request_path) 63 path = path.split("?")[0] 64 api_name = path.split("/")[1] 65 66 if api_name is None: 67 return 68 69 if api_name == "sessions": 70 self.sessions_api_handler.handle_request(request, response) 71 return 72 if api_name == "tests": 73 self.tests_api_handler.handle_request(request, response) 74 return 75 if api_name == "results": 76 self.results_api_handler.handle_request(request, response) 77 return 78 if api_name == "devices": 79 self.devices_api_handler.handle_request(request, response) 80 return 81 82 self.general_api_handler.handle_request(request, response) 83 84 def handle_static_file(self, request, response): 85 self.static_handler.handle_request(request, response) 86 87 def _remove_web_root(self, path): 88 if self._web_root is not None: 89 path = path[len(self._web_root):] 90 return path 91 92 93 def _proxy(self, request, response): 94 host = 'localhost' 95 port = int(self._http_port) 96 uri = request.url_parts.path 97 uri = uri + "?" + request.url_parts.query 98 content_length = request.headers.get('Content-Length') 99 data = "" 100 if content_length is not None: 101 data = request.raw_input.read(int(content_length)) 102 method = request.method 103 104 headers = {} 105 for key in request.headers: 106 value = request.headers[key] 107 headers[key.decode("utf-8")] = value.decode("utf-8") 108 109 try: 110 proxy_connection = httplib.HTTPConnection(host, port) 111 proxy_connection.request(method, uri, data, headers) 112 proxy_response = proxy_connection.getresponse() 113 response.content = proxy_response.read() 114 response.headers = proxy_response.getheaders() 115 response.status = proxy_response.status 116 117 except OSError: 118 message = "Failed to perform proxy request" 119 info = sys.exc_info() 120 traceback.print_tb(info[2]) 121 logger.error(f"{message}: {info[0].__name__}: {info[1].args[0]}") 122 response.status = 500