Framework
basic WSGI web application framework that uses Middleware.
Features
simple routes handler
auto description to status code
headers checker
send data as soon as possible
send strings, bytes, lists(even bytes and strings mixed) or files directly
error catcher and error logger
works with many WSGI compatible servers
you should use HTTP version
1.1
Server with your WSGI framework for some clients like Firefox browser
from wsocket import WSocketApp, WebSocketError, logger, run
from time import sleep
logger.setLevel(10) # for debugging
app = WSocketApp()
# app = WSocketApp(protocol="WAMP")
@app.route("/")
def handle_websocket(environ, start_response):
wsock = environ.get("wsgi.websocket")
if not wsock:
start_response()
return "Hello World!"
while True:
try:
message = wsock.receive()
if message != None:
print("participator : " + message)
wsock.send("you : "+message)
sleep(2)
wsock.send("you : "+message)
except WebSocketError:
break
run(app)
WSocketApp
class WSocketApp(app=None, protocol=None)
Class variables
GUID
- unique ID to generate websocket accept key
SUPPORTED_VERSIONS
- 13, 8 or 7
routes
- dictionary for route handlers
websocket_class
- "wsgi.websocket"
in WSGI Environ
Methods
not_found(self, environ, start_response)
- handle 404 NOT FOUND
error
route(self, r)
- register routes
Routes
WSocket uses simple routes engine. How it works?
URL -
http://localhost:8080/hello/world?user=Ksengine&pass=1234
divided into parts(by Server)
origin
host
port
path
query
http
localhost
8080
/hello/world
user=Ksengine&pass=1234
only path is used to find routes
walk through routes dictionary
if
"/hello/world"
path found, trigger route handler@app.route("/hello/world")
else, if some route string ends with "*" and path starts with that string trigger route handler
@app.route("/hello/world")
Status and Headers
call start_response
to send status code and headers. if you returns without calling it. It will send 200 OK
status and some basic headers to client. if start_response
is called without argsuments, it will send 200 OK
status and some basic headers to client.
start_response()
start_response
has two arguments
status - status code as int(eg:-200) or str(eg:- "200 OK" or "200"). If status description(eg:-"OK") not supplied, it will find it.
headers - HTTP headers. can passed as,
list of tuples
[("header1 name", "header1 value"), ("header2 name", "header2 value") ]
dictionary
{"header1 name": "header1 value", "header2 name": "header2 value"}
status code examples:-
start_response() # start_response("200 OK",[])
start_response(200) # start_response("200 OK",[])
start_response("200") # start_response("200 OK",[])
start_response("200 OK") # start_response("200 OK",[])
send headers examples:-
list of tuples
start_response("200 OK",[ ("header1 name", "header1 value"), ("header2 name", "header2 value") ])
dictionary
start_response("200 OK",{ "header1 name": "header1 value", "header2 name": "header2 value" })
Send data
You can send following data types
str
- string, textdef sender(environ, start_response) start_response() # ...some code here return "Hello World!"
bytes
- binarydef sender(environ, start_response) start_response() # ...some code here return b"Hello World!" # b"" is binary string
def sender(environ, start_response) start_response() # ...some code here return "Hello World!".encode() # str.encode converts str to bytes
def sender(environ, start_response) start_response() # ...some code here return b"Hello World!" # open file as text file
files
- opened filesdef sender(environ, start_response) start_response() # ...some code here return open("hello.txt")
def sender(environ, start_response) start_response() # ...some code here return open("hello.txt", "b") # "b" - open as binary file
file-like object
- streams(text, binary) likeStringIO
orBytesIO
try: from io import StringIO except ImportError: from StringIO import StringIO def sender(environ, start_response) start_response() # ...some code here file_like = StringIO() return file_like
try: from io import BytesIO except ImportError: from StringIO import BytesIO def sender(environ, start_response) start_response() # ...some code here file_like = BytesIO() return file_like
iterables
-list
,tuple
,set
dict
generators
etc.def sender(environ, start_response) start_response() # ...some code here return ["Hello ", b"World", "!".encode(), 2020] # list
def sender(environ, start_response) start_response() # ...some code here return ("Hello ", b"World", "!".encode(), 2020) # tuple
def sender(environ, start_response) start_response() # ...some code here return {"Hello ", b"World", "!".encode(), 2020} # set
def sender(environ, start_response) start_response() # ...some code here return {"Hello ":None, "World!":None} # dict
import time def sender(environ, start_response) start_response() # ...some code here yield "Hello " time.sleep(2) yield b"World" time.sleep(5) yield "!".encode() yield 2020 # generators
generators can send data one by one with time intervals. so it's like async Server
other -
def sender(environ, start_response) start_response() # ...some code here return 3.3 # float
Errors
example :-
Internal Server Error(500)ZeroDivisionError :division by zero
Traceback (most recent call last): File "wsocket.py", line 881, in process_response results = self.app(self.environ, self.start_response) File "wsocket.py", line 1068, in wsgi 1/0 ZeroDivisionError: division by zero
report
report button starts reporting issue and logger will print error to python console
Last updated
Was this helpful?