uhttpd
— micro HTTP server¶
This module provides micro HTTP server with automatic file serving, file uploading, basic authentication handing, REPL over a websocket, etc.
The server runs as a separate thread (task), custom url handlers can be registered. The python function, provided via the callback argument during the url registration, will be called when the request arrives.
The callback function will be executed in the HTTP thread (not the micropython thread). The atomicity is guaranteed by the GIL.
The callback function can only be executed when the HTTP thread aquires the GIL. Therefore the main code must “idle” on a regular basis to give the HTTP thread an opportunity to execute pending tasks.
Currently, the module is implemented only for the ESP32 port.
Example:
# import the module
import uhttpd
# setup the network connection
def setup_network():
pass
# Custom url handler
def handle_my_url(req):
req.write('Hello World', mime='text/plain')
# Setup the server
httpd = uhttpd.Server()
# - register the custom handler
httpd.route('/my', uhttpd.GET, handle_my_url)
# - initialize REPL
httpd.ws('/ws', None)
# - initialize file server
httpd.serve()
class Server¶
The server is configured via calling the corresponding class methods, however, there is no runner function or an async task - the server does all the work in a separate thread (created internally inside the constructor). Therefore, it is necessary to keep the class instance from being garbage-collected.
Constructors¶
- class uhttpd.Server(port=80, ...)¶
Construct a http server object and start the server on the given port (defaults to
80
). Additional parameters are:acl
. Defines the access control mode. Can beuhttpd.AUTH_OPEN
,uhttpd.AUTH_BASIC
, oruhttpd.AUTH_CUSTOM
.cors
. A boolean parameter controlling the CORS policy. If set toTrue
, theAccess-Control-Allow-Origin: *
header will be set automatically for all the server replies. If set toFalse
(the default), the CORS header will not be present, unless it is explicitly added by the callback function.routes
. Can be an integer (sets the maximum number of URL handlers. Defaults to8
. Please see the note below.) or an iterable. If an iterable is provided, each item must itself be an iterable of 3 elements: the url, the method, and the callback - essentialy the same arguments, that are passed to theuhttpd.Server.route()
call. Please note, that in this case, no further calls to the route() method should be made.auth
. Ifuhttpd.AUTH_BASIC
has been selected, provide the authorization header value (as a bytes-like object). Please note, that the complete value should be provided. In case of basic authorization with theanswer:42
login-password, the auth value should beb'Basic YW5zd2VyOjQy'
. Ifuhttpd.AUTH_CUSTOM
has been selected, provide a function to be called for each incoming request. The handler must take exactly one argument which is the Request instance.events
- the maximum number of the Server-sent event sockets, that this server can serve simultaneously. Please note, that the board has a limited number of sockets available (globally), therefore 3, at most 4 is a resonable maximum value for this parameter. Default valus is0
.
Note
About calculating the number of routes.
one slot is reserved for the
OPTIONS
requestfile server occupies one slot
file uploader occupies one slot if the
DELETE
verb is not supported, and two if it is.websocket occupies one slot
custom handler occupies one to three slots (depends on the number of verbs supported).
Note
About routes regiteration order.
The routes support wildcards (
*
)The routes are matched in the order of registration (the first registered is the first probed)
As a general rule, the wildcard routes must be the last registered (including the file server and uploader).
Methods¶
- Server.port()¶
Returns the port number that this server instance is using
- Server.route(url, methods, callback)¶
Note
If an list of routed has been passed to the constructor, do not call this method.
Registers the handler for
url
(may be a wildcard). The handler will accept the requests withmethods
verbs (may be any combination ofuhttpd.GET
,uhttpd.POST
, anduhttpd.DELETE
). The callback function must accept exactly one argument which is the Request instance
- Server.serve(prefix, base=none, dirs=True, ext=False)¶
Initialize this file server. The file server will respond to GET requests to
<prefix>/*
.The prefix must start with a slash (
/
). If the prefix is not specified, an empty prefix will be used (i.e. the url wildcard will be/*
).The file path resolution is as follows:
The url
/prefix/path/to/file
will be first resolved to/path/to/file
, thenbase
will be prepended (if notNone
). For example ifprefix='/fs'
andbase=/www/data
, the request/fs/subdir/hello.txt
will try to read the/www/data/subdir/hello.txt
file. If the resolved path ends with a slash anddirs=True
, a JSON document describing the requested directory contents will be returned. Thebase
value (if notNone
) must start with a slash (/
).Directory document example:
{ "path" : "/var/", "list" : [ { "path": "..", "type": "directory", "size": 0 }, { "path": "my_folder", "type": "directory", "size": 0 }, { "path": "hello.txt", "type": "file", "size": 42 } ] }
If
ext=True
, the external storage mount path will be prepended to the resolved filename, and if the resulting file (or directory) exists, it will be served. If no such file or directory exists, the prepended path will be removed and the original resolved path will be processed.
- Server.receive(dynamic, prefix=None, extonly=False, delete=False)¶
Initialize the file receiver. The prefix (if not
None
) must start with a slash (/
). Ifextonly=True
, the file receiver will refuse to upload files to the internal storage.If
dynamic=True
(the default variant):The file receive will respond to the following POST requests (and DELETE requests if
delete=True
):<prefix>/*
The url/prefix/path/to/file
will be resolved to/path/to/file
. The server will try to open this file for writing (the parent directory will be created automatically) and forward all data received to this file (verbatim). If the resolved path ends with a slash (/
), the corresponding directory will be created, the success or failure code returned. The request body will be ignored (do not transmit one). If the verb isDELETE
, the resolved path will be deleted (if it ends with a slash, thermdir
command will be executed, if not - the corresponding file will be removed). Ifforce=1
is present in the query string, the directory will be removed recursively.If
dynamic==False
, the server behaviour is as described above with the following differences:The
prefix
is treated as the endpoint location, and therefore it must not beNone
.The file path is taken from the
Content-Disposition
header which is mandatory in this case.
The Content-Disposition header must be of the following format:
Content-Disposition: attachement; filename="/path/to/file"
- Server.event(url)¶
A GET request to this url will return a text/event-stream to be used by the EventSource (see, for example, MDN). The
url
must not be a wildcard.Note
At most one such url can be registered per server. Not to be confused with the maximum number of EvenSource clients being served simultaneously (see the
events
parameter of the constructor).
- Server.dispatch(data, event)¶
Send
data
to all EventSource clients currently listening. The optional parameterevent
can be used to set the name of the event. ReturnsFalse
if noone is listening at this time.
- Server.file_acl(cb)¶
Sets the callback function to be called when a file is read or written or a directory is accessed or created. The callback must take exactly one argument which is the path (the path will end with a slash for directories). The callback must return an integer. The return value can be one of
uhttpd.ACL_RO
(if only read access should be granted),uhttpd.ACL_RW
(if only write access should be granted), anduhttpd.ACL_RW
(if read and write access is allowed) or a HTTP error code (greater o equal to 400). If an invalid value is returned, the default403
HTTP code is used. The access to the file is denied, the request aborted.
- Server.ws(url, pwd)¶
Note
May be unavailable in some firmwares.
A GET request to
url
will be upgraded to the WebSocket connection, that gives access to the micropython REPL. An optionalpwd
argument password protects the access to the REPL (indepenent of the Server authentication).At most one handler can be registered (not only per Server object instance, but globally).
class Request¶
When a custom request arrives, the server calls the corresponding handler (registered via the Server.route
method).
The handler receives the Request object as the only argument.
Constructors¶
No public constructor is available. An instance is created internally and passed to the handler.
Methods¶
- Request.server()¶
Returns the server object associated with this request.
- Request.method()¶
Returns the HTTP verb for this request. The returned value is an integer - one of the
uhttpd.GET
,uhttpd.POST
,uhttpd.DELETE
- Request.uri()¶
Returns the full uri of the request including the query and fragment, if present.
- Request.length()¶
Returns the content length of the request (as reported by the Content-Length header)
- Request.path()¶
Returns the path of the request (the URI without the query and fragment parts).
- Request.query(key)¶
Search the query string for the
key
entry and return its value. If multiple entries with this key exist in the query string, the value of the first one is returned. If the key is found an has a value, the value is returned (asbytes
). If only the key is found (without a value),True
is returned. In any other case,None
is returned.
- Request.parse_qs()¶
Parses the query string and returns it as a
dict
. Every key is abytes
object. Values are eitherbytes
(if the value is present) orTrue
(if the value is missing in the query string). If multiple entries with the same key exist in the query string, the last one will be returned.
- Request.read(len=- 1)¶
Reads the body of the request (at most
len
bytes iflen > 0
or all available bytes iflen
is negative). Returns the result as abytes
object.
- Request.readinto(buffer)¶
Reads at most
len(buffer)
bytes of the request body and puts then in thebuffer
. Returns the number of bytes received.
- Request.write(data, status=None, mime=None, headers=None, allow_cors=False)¶
Sends
data
as the response to the request. This method can be called only once per request and is not compatible with theRequest.send_chunk
and theRequest.send
methods (i.e. cannot be called after one of those methods have been called).Optional arguments:
status
. If notNone
, the HTTP status is set to this value (a string or a bytes-like object is expected, no HTTP validity check). The default is 200 OK.mime
. IF notNone
, sets the Content-Type header to this value (a string or a bytes-like object is expected, no HTTP validity check). The default is text/htmlheaders
- an optionaldict
with auxiliary headers. Each key and value must be a string or a bytes-like object.allow_cors
- is set toTrue
, overrides the global parametercors
of the server object. Do not set toTrue
if already enabled by the global config.
- Request.send_chunk(data, status=None, mime=None, headers=None, allow_cors=False)¶
Sends
data
as chunks (ref. Chunked transfer encoding). If this is the first call for this request, optional argument can be provided. For their meaning, refer to theRequest.write
method description. If this is not the first call fot this request, do not provide additional arguments - they will be ignored.If
data=None
, finalizes the request (no furtherRequest.send_chunk
calls are permitted). After one or moresend_chunk(data)
calls, the finalsend_chunk(None)
call is mandatory.
- Request.send(data)¶
Sends
data
to the HTTP socket verbatim. When using this api, the callee is responsible for formatting the data accoding to the HTTP protocol (i.e the status lines, all the headers, etc).
Constants¶
- uhttpd.AUTH_OPEN¶
Open access server
- uhttpd.AUTH_BASIC¶
Basic authentication (user and password)
- uhttpd.AUTH_CUSTOM¶
Custom authentication (via a callback function)
- uhttpd.ACL_RW¶
File/Directory read-write access granted
- uhttpd.ACL_RO¶
File/Directory read-only access
- uhttpd.ACL_WO¶
File/Directory write-only access