Julian Bilcke
commited on
Commit
·
b8eae92
1
Parent(s):
8cc1429
up
Browse files- Dockerfile +2 -2
- client/client.js +15 -1
- client/index.html +1 -1
- run_hf_space.py +32 -0
- server.py +28 -8
Dockerfile
CHANGED
|
@@ -48,5 +48,5 @@ EXPOSE 8080
|
|
| 48 |
|
| 49 |
ENV PORT 8080
|
| 50 |
|
| 51 |
-
# Run the
|
| 52 |
-
CMD ["python3", "
|
|
|
|
| 48 |
|
| 49 |
ENV PORT 8080
|
| 50 |
|
| 51 |
+
# Run the HF space launcher script which sets up the correct paths
|
| 52 |
+
CMD ["python3", "run_hf_space.py"]
|
client/client.js
CHANGED
|
@@ -57,7 +57,21 @@ const mouseState = {
|
|
| 57 |
|
| 58 |
// Connect to WebSocket server
|
| 59 |
function connectWebSocket() {
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
logMessage(`Connecting to ${serverUrl}...`);
|
| 62 |
|
| 63 |
socket = new WebSocket(serverUrl);
|
|
|
|
| 57 |
|
| 58 |
// Connect to WebSocket server
|
| 59 |
function connectWebSocket() {
|
| 60 |
+
// Use secure WebSocket (wss://) if the page is loaded over HTTPS
|
| 61 |
+
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
| 62 |
+
|
| 63 |
+
// Get base path by extracting path from the script tag's src attribute
|
| 64 |
+
let basePath = '';
|
| 65 |
+
const scriptTags = document.getElementsByTagName('script');
|
| 66 |
+
for (const script of scriptTags) {
|
| 67 |
+
if (script.src.includes('client.js')) {
|
| 68 |
+
const url = new URL(script.src);
|
| 69 |
+
basePath = url.pathname.replace('/assets/client.js', '');
|
| 70 |
+
break;
|
| 71 |
+
}
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
const serverUrl = `${protocol}//${window.location.hostname}${window.location.port ? ':' + window.location.port : ''}${basePath}/ws`;
|
| 75 |
logMessage(`Connecting to ${serverUrl}...`);
|
| 76 |
|
| 77 |
socket = new WebSocket(serverUrl);
|
client/index.html
CHANGED
|
@@ -233,6 +233,6 @@
|
|
| 233 |
</div>
|
| 234 |
</div>
|
| 235 |
|
| 236 |
-
<script src="
|
| 237 |
</body>
|
| 238 |
</html>
|
|
|
|
| 233 |
</div>
|
| 234 |
</div>
|
| 235 |
|
| 236 |
+
<script src="./assets/client.js"></script>
|
| 237 |
</body>
|
| 238 |
</html>
|
run_hf_space.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
# -*- coding: utf-8 -*-
|
| 3 |
+
|
| 4 |
+
"""
|
| 5 |
+
Hugging Face Space launcher for MatrixGame WebSocket Server
|
| 6 |
+
This script launches the server with the appropriate configuration for Hugging Face Spaces.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
import os
|
| 10 |
+
import sys
|
| 11 |
+
import subprocess
|
| 12 |
+
|
| 13 |
+
def main():
|
| 14 |
+
# Get the port from environment variable in Hugging Face Space
|
| 15 |
+
port = int(os.environ.get("PORT", 7860))
|
| 16 |
+
|
| 17 |
+
# Determine if this is running in a Hugging Face Space
|
| 18 |
+
is_hf_space = os.environ.get("SPACE_ID") is not None
|
| 19 |
+
|
| 20 |
+
# Pass the appropriate path if in a space
|
| 21 |
+
path_arg = ""
|
| 22 |
+
if is_hf_space:
|
| 23 |
+
# In a space, we're usually behind a proxy, so we need to handle base path
|
| 24 |
+
path_arg = f"--path /{os.environ.get('SPACE_ID', '')}"
|
| 25 |
+
|
| 26 |
+
# Construct and run the command
|
| 27 |
+
cmd = f"{sys.executable} server.py --host 0.0.0.0 --port {port} {path_arg}"
|
| 28 |
+
print(f"Running command: {cmd}")
|
| 29 |
+
subprocess.run(cmd, shell=True)
|
| 30 |
+
|
| 31 |
+
if __name__ == "__main__":
|
| 32 |
+
main()
|
server.py
CHANGED
|
@@ -562,7 +562,7 @@ async def websocket_handler(request: web.Request) -> web.WebSocketResponse:
|
|
| 562 |
|
| 563 |
return ws
|
| 564 |
|
| 565 |
-
async def init_app() -> web.Application:
|
| 566 |
app = web.Application(
|
| 567 |
client_max_size=1024**2*10 # 10MB max size
|
| 568 |
)
|
|
@@ -574,15 +574,34 @@ async def init_app() -> web.Application:
|
|
| 574 |
|
| 575 |
app.on_shutdown.append(cleanup)
|
| 576 |
|
| 577 |
-
# Add routes
|
| 578 |
-
|
| 579 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 580 |
|
| 581 |
-
|
| 582 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 583 |
|
| 584 |
# Set up static file serving for the client assets
|
| 585 |
-
app.router.add_static('/assets', path=pathlib.Path(__file__).parent / 'client')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 586 |
|
| 587 |
return app
|
| 588 |
|
|
@@ -590,9 +609,10 @@ def parse_args() -> argparse.Namespace:
|
|
| 590 |
parser = argparse.ArgumentParser(description="MatrixGame WebSocket Server")
|
| 591 |
parser.add_argument("--host", type=str, default="0.0.0.0", help="Host IP to bind to")
|
| 592 |
parser.add_argument("--port", type=int, default=8080, help="Port to listen on")
|
|
|
|
| 593 |
return parser.parse_args()
|
| 594 |
|
| 595 |
if __name__ == '__main__':
|
| 596 |
args = parse_args()
|
| 597 |
-
app = asyncio.run(init_app())
|
| 598 |
web.run_app(app, host=args.host, port=args.port)
|
|
|
|
| 562 |
|
| 563 |
return ws
|
| 564 |
|
| 565 |
+
async def init_app(base_path="") -> web.Application:
|
| 566 |
app = web.Application(
|
| 567 |
client_max_size=1024**2*10 # 10MB max size
|
| 568 |
)
|
|
|
|
| 574 |
|
| 575 |
app.on_shutdown.append(cleanup)
|
| 576 |
|
| 577 |
+
# Add routes with CORS headers for WebSockets
|
| 578 |
+
# Configure CORS for all routes
|
| 579 |
+
async def cors_middleware(request, handler):
|
| 580 |
+
response = await handler(request)
|
| 581 |
+
response.headers['Access-Control-Allow-Origin'] = '*'
|
| 582 |
+
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
|
| 583 |
+
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, X-Requested-With'
|
| 584 |
+
return response
|
| 585 |
|
| 586 |
+
app.middlewares.append(cors_middleware)
|
| 587 |
+
|
| 588 |
+
# Set up routes with the base_path
|
| 589 |
+
app.router.add_get(f'{base_path}/ws', websocket_handler)
|
| 590 |
+
app.router.add_get(f'{base_path}/api/status', status_handler)
|
| 591 |
+
|
| 592 |
+
# Serve the client at both the base path and root path for compatibility
|
| 593 |
+
app.router.add_get(f'{base_path}/', root_handler)
|
| 594 |
+
|
| 595 |
+
# Always serve at the root path for Hugging Face Spaces compatibility
|
| 596 |
+
if base_path:
|
| 597 |
+
app.router.add_get('/', root_handler)
|
| 598 |
|
| 599 |
# Set up static file serving for the client assets
|
| 600 |
+
app.router.add_static(f'{base_path}/assets', path=pathlib.Path(__file__).parent / 'client')
|
| 601 |
+
|
| 602 |
+
# Add static file serving at root for compatibility
|
| 603 |
+
if base_path:
|
| 604 |
+
app.router.add_static('/assets', path=pathlib.Path(__file__).parent / 'client')
|
| 605 |
|
| 606 |
return app
|
| 607 |
|
|
|
|
| 609 |
parser = argparse.ArgumentParser(description="MatrixGame WebSocket Server")
|
| 610 |
parser.add_argument("--host", type=str, default="0.0.0.0", help="Host IP to bind to")
|
| 611 |
parser.add_argument("--port", type=int, default=8080, help="Port to listen on")
|
| 612 |
+
parser.add_argument("--path", type=str, default="", help="Base path for the server (for proxy setups)")
|
| 613 |
return parser.parse_args()
|
| 614 |
|
| 615 |
if __name__ == '__main__':
|
| 616 |
args = parse_args()
|
| 617 |
+
app = asyncio.run(init_app(base_path=args.path))
|
| 618 |
web.run_app(app, host=args.host, port=args.port)
|