diff --git a/app.py b/app.py index 2119b87..207348a 100644 --- a/app.py +++ b/app.py @@ -6,8 +6,7 @@ import threading import time from datetime import datetime, timezone from socketserver import ThreadingMixIn -from queue import Queue -import multiprocessing +import os # Define the target server to proxy requests to class ProxyHandler(http.server.BaseHTTPRequestHandler): @@ -40,26 +39,28 @@ class ProxyHandler(http.server.BaseHTTPRequestHandler): def handle_request(self, method): #print(self.headers.get('Host').split(":")[0]) - proxy_host_configuration = next(filter(lambda host: host['domain'] == self.headers.get('Host').split(":")[0], self.configuration['proxy_hosts'])) - + parsed_request_host = self.headers.get('Host') + + if (':' in parsed_request_host): + parsed_request_host = parsed_request_host.split(":")[0] + + proxy_host_configuration = next(filter(lambda host: host['domain'] == parsed_request_host, self.configuration['proxy_hosts'])) + starting = False for container in proxy_host_configuration['containers']: - container_object = self.docker_client.containers.list(all=True, filters = { 'name' : container['container_name'] })[0] + container_objects = self.docker_client.containers.list(all=True, filters = { 'name' : container['container_name'] }) + if (container_objects == []): + self.send_404(proxy_host_configuration['domain']) + return + + container_object = container_objects[0] if (container_object.status != 'running'): print("starting container: {0}".format(container['container_name'])) container_object.start() starting = True if (starting == True): - self.send_response(201) - self.send_header('Content-Type', 'text/plain') - self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate') - self.send_header('Pragma', 'no-cache') - self.send_header('Expires', '0') - self.send_header('refresh', proxy_host_configuration['proxy_timeout_seconds']) - self.end_headers() - self.wfile.write(bytes("starting container: {0} waiting for {1}s".format(container['container_name'], proxy_host_configuration['proxy_timeout_seconds']),"utf-8")) - self.wfile.flush() + self.send_loading(proxy_host_configuration['proxy_load_seconds'], proxy_host_configuration['domain']) return activity[proxy_host_configuration['domain']] = datetime.now(timezone.utc) @@ -78,6 +79,48 @@ class ProxyHandler(http.server.BaseHTTPRequestHandler): self.wfile.write(response.read()) conn.close() + + def send_404(self, service_name): + self.send_response(404) + self.send_header('Content-Type', 'text/html; charset=utf-8') + self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate') + self.send_header('Pragma', 'no-cache') + self.send_header('Expires', '0') + self.end_headers() + + with open(os.path.dirname(os.path.realpath(__file__)) + '/templates/404.html', 'r') as file: + html = file.read() + html = html.replace("{{SERVICE}}", service_name) + self.wfile.write(bytes(html,"utf-8")) + + self.wfile.flush() + + def send_loading(self, wait_time, service_name): + self.send_response(201) + self.send_header('Content-Type', 'text/html; charset=utf-8') + self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate') + self.send_header('Pragma', 'no-cache') + self.send_header('Expires', '0') + self.send_header('refresh', wait_time) + self.end_headers() + + with open(os.path.dirname(os.path.realpath(__file__)) + '/templates/wait.html', 'r') as file: + html = file.read() + self.wfile.write(bytes(html,"utf-8")) + + #self.wfile.write(bytes("starting service: {0} waiting for {1}s".format(self.headers.get('Host').split(":")[0], proxy_host_configuration['proxy_timeout_seconds']),"utf-8")) + #self.wfile.write(bytes("\nlast started at: {0} ".format(activity[proxy_host_configuration['domain']]),"utf-8")) + + self.wfile.flush() + + def finish(self,*args,**kw): + try: + if not self.wfile.closed: + self.wfile.flush() + self.wfile.close() + except socket.error: + pass + self.rfile.close() class ThreadedHTTPServer(ThreadingMixIn, http.server.HTTPServer): """Handle requests in a separate thread.""" @@ -97,17 +140,20 @@ class BackgroundTasks(threading.Thread): sleep_time = apps['proxy_timeout_seconds'] for container in apps['containers']: - container_object = self.docker_client.containers.get(container['container_name']) - if (container_object.status == 'running'): + try: + container_object = self.docker_client.containers.get(container['container_name']) + if (container_object.status == 'running'): - dt = datetime.now(timezone.utc) - if (apps['domain'] in activity): - dt = activity[apps['domain']] + dt = datetime.now(timezone.utc) + if (apps['domain'] in activity): + dt = activity[apps['domain']] - diff_seconds = (datetime.now(timezone.utc) - dt).total_seconds() - if(diff_seconds > apps['proxy_timeout_seconds']): - print("stopping container: {0} ({1}) after {2}s".format(container['container_name'], container_object.id, diff_seconds)) - container_object.stop() + diff_seconds = (datetime.now(timezone.utc) - dt).total_seconds() + if(diff_seconds > apps['proxy_timeout_seconds']): + print("stopping container: {0} ({1}) after {2}s".format(container['container_name'], container_object.id, diff_seconds)) + container_object.stop() + except docker.errors.NotFound: + pass time.sleep(sleep_time) diff --git a/config.yml b/config.yml index 84bbb45..4b13ead 100644 --- a/config.yml +++ b/config.yml @@ -1,9 +1,10 @@ -proxy_port: 8888 +proxy_port: 80 proxy_hosts: - domain: wp.local containers: - container_name: wp-dev-db-1 - container_name: wp-dev-wordpress-1 proxy_host: localhost - proxy_port: 80 - proxy_timeout_seconds: 10 \ No newline at end of file + proxy_port: 8888 + proxy_timeout_seconds: 10 + proxy_load_seconds: 5 \ No newline at end of file diff --git a/templates/404.html b/templates/404.html new file mode 100644 index 0000000..eebf178 --- /dev/null +++ b/templates/404.html @@ -0,0 +1,28 @@ + +