|
1 | 1 | import http.server
|
2 | 2 | import socketserver
|
3 | 3 | import os
|
| 4 | +import sys |
4 | 5 | from pathlib import Path
|
| 6 | +import urllib.parse |
5 | 7 |
|
6 | 8 | SCRIPT_DIR = Path(__file__).parent.absolute()
|
7 | 9 | DIRECTORY = os.path.join(SCRIPT_DIR, "../build-em/bin")
|
8 | 10 | DIRECTORY = os.path.abspath(DIRECTORY)
|
9 | 11 |
|
| 12 | +# The context root we want for all applications |
| 13 | +CONTEXT_ROOT = "/whisper.cpp" |
| 14 | + |
10 | 15 | class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
|
11 | 16 | def __init__(self, *args, **kwargs):
|
12 | 17 | super().__init__(*args, directory=DIRECTORY, **kwargs)
|
13 | 18 |
|
14 | 19 | def do_GET(self):
|
15 |
| - # If requesting a worker file from any subdirectory |
16 |
| - if '.worker.js' in self.path: |
| 20 | + # Redirect root to the context root |
| 21 | + if self.path == '/': |
| 22 | + self.send_response(302) |
| 23 | + self.send_header('Location', CONTEXT_ROOT + '/') |
| 24 | + self.end_headers() |
| 25 | + return |
| 26 | + |
| 27 | + # Handle requests under the context root |
| 28 | + if self.path.startswith(CONTEXT_ROOT): |
| 29 | + # Remove the context root prefix to get the actual path |
| 30 | + actual_path = self.path[len(CONTEXT_ROOT):] |
| 31 | + |
| 32 | + if not actual_path: |
| 33 | + self.send_response(302) |
| 34 | + self.send_header('Location', CONTEXT_ROOT + '/') |
| 35 | + self.end_headers() |
| 36 | + return |
| 37 | + |
| 38 | + if '.worker.js' in actual_path: |
| 39 | + worker_file = os.path.basename(actual_path) |
| 40 | + worker_path = os.path.join(DIRECTORY, worker_file) |
| 41 | + |
| 42 | + if os.path.exists(worker_path): |
| 43 | + print(f"Found worker file: {worker_path}") |
| 44 | + self.path = '/' + worker_file |
| 45 | + else: |
| 46 | + print(f"Worker file not found: {worker_path}") |
| 47 | + |
| 48 | + elif actual_path == '/': |
| 49 | + self.path = '/whisper.wasm/index.html' |
| 50 | + elif actual_path.startswith('/bench.wasm/') or actual_path.startswith('/command.wasm/') or actual_path.startswith('/stream.wasm/'): |
| 51 | + # Keep the path as is, just remove the context root |
| 52 | + self.path = actual_path |
| 53 | + # For all other paths under the context root |
| 54 | + else: |
| 55 | + # Check if this is a request to a file in whisper.wasm |
| 56 | + potential_file = os.path.join(DIRECTORY, 'whisper.wasm', actual_path.lstrip('/')) |
| 57 | + if os.path.exists(potential_file) and not os.path.isdir(potential_file): |
| 58 | + self.path = '/whisper.wasm' + actual_path |
| 59 | + else: |
| 60 | + # Try to resolve the file from the base directory |
| 61 | + potential_file = os.path.join(DIRECTORY, actual_path.lstrip('/')) |
| 62 | + if os.path.exists(potential_file): |
| 63 | + self.path = actual_path |
| 64 | + |
| 65 | + # For direct requests to worker files (without context root as these |
| 66 | + # are in the build-em/bin directory |
| 67 | + elif '.worker.js' in self.path: |
17 | 68 | worker_file = os.path.basename(self.path)
|
18 | 69 | worker_path = os.path.join(DIRECTORY, worker_file)
|
19 | 70 |
|
20 | 71 | if os.path.exists(worker_path):
|
21 | 72 | self.path = '/' + worker_file
|
22 | 73 |
|
| 74 | + # Handle coi-serviceworker.js separately |
| 75 | + if 'coi-serviceworker.js' in self.path: |
| 76 | + worker_file = "coi-serviceworker.js" |
| 77 | + worker_path = os.path.join(SCRIPT_DIR, worker_file) |
| 78 | + if os.path.exists(worker_path): |
| 79 | + self.send_response(200) |
| 80 | + self.send_header('Content-type', 'application/javascript') |
| 81 | + self.end_headers() |
| 82 | + with open(worker_path, 'rb') as file: |
| 83 | + self.wfile.write(file.read()) |
| 84 | + return |
| 85 | + else: |
| 86 | + print(f"Warning: Could not find {worker_path}") |
| 87 | + |
23 | 88 | return super().do_GET()
|
24 | 89 |
|
25 | 90 | def end_headers(self):
|
26 | 91 | # Add required headers for SharedArrayBuffer
|
27 | 92 | self.send_header("Cross-Origin-Opener-Policy", "same-origin")
|
28 | 93 | self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
|
29 |
| - self.send_header("Access-Control-Allow-Origin", "*"); |
| 94 | + self.send_header("Access-Control-Allow-Origin", "*") |
30 | 95 | super().end_headers()
|
31 | 96 |
|
32 | 97 | PORT = 8000
|
33 | 98 |
|
34 |
| -with socketserver.TCPServer(("", PORT), CustomHTTPRequestHandler) as httpd: |
35 |
| - print(f"Serving directory '{DIRECTORY}' at http://localhost:{PORT}") |
36 |
| - try: |
37 |
| - httpd.serve_forever() |
38 |
| - except KeyboardInterrupt: |
39 |
| - print("\nServer stopped.") |
| 99 | +# Enable address reuse |
| 100 | +class CustomServer(socketserver.TCPServer): |
| 101 | + allow_reuse_address = True |
| 102 | + |
| 103 | +try: |
| 104 | + with CustomServer(("", PORT), CustomHTTPRequestHandler) as httpd: |
| 105 | + print(f"Serving directory '{DIRECTORY}' at http://localhost:{PORT}") |
| 106 | + print(f"Application context root: http://localhost:{PORT}{CONTEXT_ROOT}/") |
| 107 | + try: |
| 108 | + httpd.serve_forever() |
| 109 | + except KeyboardInterrupt: |
| 110 | + print("\nServer stopped.") |
| 111 | + # Force complete exit |
| 112 | + sys.exit(0) |
| 113 | +except OSError as e: |
| 114 | + print(f"Error: {e}") |
| 115 | + sys.exit(1) |
0 commit comments