-
-
Save ahmetuludag/85d206f750788f9cb32d00a406daa59e to your computer and use it in GitHub Desktop.
Python asyncio websockets http static file server, aka http and websocket server on the same port: python-websockets/websockets#116
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>WebSocket demo</title> | |
</head> | |
<body> | |
<script> | |
var ws = new WebSocket("ws://127.0.0.1:8765/"), | |
messages = document.createElement('ul'); | |
ws.onmessage = function (event) { | |
var messages = document.getElementsByTagName('ul')[0], | |
message = document.createElement('li'), | |
content = document.createTextNode(event.data); | |
message.appendChild(content); | |
messages.appendChild(message); | |
}; | |
document.body.appendChild(messages); | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
This code allows you to serve static files from the same port as the websocket connection | |
This is only suitable for small files and as a development server! | |
open(full_path, 'rb').read() call that is used to send files will block the whole asyncio loop! | |
""" | |
import os | |
import asyncio | |
import datetime | |
import random | |
import websockets | |
from http import HTTPStatus | |
class WebSocketServerProtocolWithHTTP(websockets.WebSocketServerProtocol): | |
"""Implements a simple static file server for WebSocketServer""" | |
async def process_request(self, path, request_headers): | |
"""Serves a file when doing a GET request with a valid path""" | |
if "Upgrade" in request_headers: | |
return # Probably a WebSocket connection | |
if path == '/': | |
path = '/index.html' | |
response_headers = [ | |
('Server', 'asyncio'), | |
('Connection', 'close'), | |
] | |
server_root = os.getcwd() | |
full_path = os.path.realpath(os.path.join(server_root, path[1:])) | |
print("GET", path, end=' ') | |
# Validate the path | |
if os.path.commonpath((server_root, full_path)) != server_root or \ | |
not os.path.exists(full_path) or not os.path.isfile(full_path): | |
print("404 NOT FOUND") | |
return HTTPStatus.NOT_FOUND, [], b'404 NOT FOUND' | |
print("200 OK") | |
body = open(full_path, 'rb').read() | |
response_headers.append(('Content-Length', str(len(body)))) | |
response_headers.append(('Content-Type', 'text/html')) | |
return HTTPStatus.OK, response_headers, body | |
async def time(websocket, path): | |
while True: | |
now = datetime.datetime.utcnow().isoformat() + 'Z' | |
await websocket.send(now) | |
await asyncio.sleep(random.random() * 2) | |
if __name__ == "__main__": | |
start_server = websockets.serve(time, 'localhost', 8765, | |
create_protocol=WebSocketServerProtocolWithHTTP) | |
print("Running server at http://localhost:8765/") | |
asyncio.get_event_loop().run_until_complete(start_server) | |
asyncio.get_event_loop().run_forever() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment