Skip to content

Instantly share code, notes, and snippets.

@ahmetuludag
Forked from artizirk/index.html
Last active February 15, 2020 06:49
Show Gist options
  • Save ahmetuludag/85d206f750788f9cb32d00a406daa59e to your computer and use it in GitHub Desktop.
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
<!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>
#!/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