usrv
: the lightest python web framework
Package (usrv
) is a pure python micro server implementation. It allows python function bindings for all HTTP methods. HTTP body can be encrypted on demand using secp256k1 keypairs.
Install
Developpment version
$ python -m pip install git+https://github.com/Moustikitos/micro-server#egg=usrv
last version (0.4.1)
$ python -m pip install usrv
usrv.route
Bind python code to any HTTP requests easily using decorator syntax.
route
module can be used in standalone mode outside of usrv
package.
usrv.app
Run a low footprint python server or PEP#3333 WSGI server.
import waitress # wsgi server for windows
from usrv import app, route
@route.bind("/index")
def index(**kw):
return 200, "Index page", kw
waitress.serve(app.uApp(), threads=2)
Fast and simple
Let’s create a server with /test
endpoint in a python module named test.py
:
from usrv import route, app
@route.bind("/test")
def do_test(a, b):
# write some code and return something
return 200, a, b
def launchApp():
route.run(host="127.0.0.1", port=5000, loglevel=20)
Bound functions have to return a tuple with a valid HTTP status code as first item. Server can be run from python interpreter:
>>> import test
>>> test.launchApp()
INFO:usrv.srv:listening on 127.0.0.1:5000
CTRL+C to stop...
Now going to http://127.0.0.1:5000/test
with any browser gives:
[null, null]
Extracting values from url query
[null, null]
above are the returned values a
and b
from do_test
function. Values can be extracted from query string. Let’s type http://127.0.0.1:5000/test?b=12&a=Paris
in the address bar:
["Paris", "12"]
Returned value from query are str
only. Unexpected values are ignored but there is a convenient way to catch them.
Extracting values from url path
Values can also be extracted from url path with or without a typing precision.
@route.bind("/<int:b>/<a>")
def do_test(a, b):
# write some code and return something
return 200, a, b
This binding creates multiple endpoint possibilities. Let’s try http://127.0.0.1:5000/5/test
:
["test", 5]
Values from url can be overrided by thoses from query… http://127.0.0.1:5000/5/test?a=2&b=6
:
["2", "6"]
It can only be overrided with
str
type values.
Catching unexpected values
Using varargs or/and keywordargs is a convenient way to catch unexpected values from url query and HTTP context. HTTP Context is defined an headers and data (HTTP requests with body).
When HTTP context is catched by *args
, unexpected values from query string are appended next.
Url used for this chapter http://127.0.0.1:5000/test?b=12&a=Paris&unexpected=there
.
Variable args (*args
)
@route.bind("/test")
def do_test(a, b, *args):
# write some code and return something
# args is a tuple
return 200, a, b, args
With
*args
method, HTTP headers and data will be postionned at the end ofjson
response
[
"Paris",
"12",
"there",
"GET",
{
"host": "127.0.0.1:5000",
"connection": "keep-alive",
"sec-ch-ua": "\"Brave\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
"sec-gpc": "1",
"accept-language": "fr-FR,fr",
"sec-fetch-site": "none",
"sec-fetch-mode": "navigate",
"sec-fetch-user": "?1",
"sec-fetch-dest": "document",
"accept-encoding": "gzip, deflate, br, zstd"
},
null
]
Keyword args (**kwargs
)
@route.bind("/test")
def do_test(a, b, **kwargs):
# write some code and return something
# kwargs is a dict
return 200, a, b, kwargs
using
**kwargs
is the recommended way to retrieve unexpected values by names. Unexpected mapping is positionned at the end ofjson
response.
[
"Paris",
"12",
{
"unexpected": "there",
"method": "GET",
"headers": {
"host": "127.0.0.1:5000",
"connection": "keep-alive",
"sec-ch-ua": "\"Brave\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
"sec-gpc": "1",
"accept-language": "fr-FR,fr",
"sec-fetch-site": "none",
"sec-fetch-mode": "navigate",
"sec-fetch-user": "?1",
"sec-fetch-dest": "document",
"accept-encoding": "gzip, deflate, br, zstd"
},
"data": null,
}
]
Command line
WSGI server can be launched from command line.
$ python wsgi_srv.py -h
Usage: wsgi_srv.py [options] BINDINGS...
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-t THREADS, --threads=THREADS
set thread number [default: 2]
-l LOGLEVEL, --log-level=LOGLEVEL
set log level from 1 to 100 [default: 20]
-i HOST, --ip=HOST ip to run from [default: 127.0.0.1]
-p PORT, --port=PORT port to use [default: 5000]
BINDINGS
is a space-separated-list of python module names (ie no *.py
extention) containing boud python functions. Modules containing bound functions have to be in one of sys.path
folder. Specific folder can be added using wsgi_srv.path
file.
Changes
0.4.1
- major changes and improvement, no backward compatibility with 0.3.0
0.4.2 (dev)
- improved
route.uHTTPRequstHandler
response - added body encryption/decryption based on
secp256k1
andAES
- added multipart/form-data body management to req module
- added custom client/server identification
- added secured secret dump and load
- added endpoint builder
- added pinata plugin
- added binance plugin