adafruit_httpserver
Socket based HTTP Server for CircuitPython
Author(s): Dan Halbert, Michał Pokusa
Software and Dependencies:
Adafruit CircuitPython firmware for the supported boards: https://github.com/adafruit/circuitpython/releases
adafruit_httpserver.server
Author(s): Dan Halbert, Michał Pokusa
A basic socket-based HTTP server.
Create a server, and get it ready to run.
socket – An object that is a source of sockets. This could be a socketpool
in CircuitPython or the socket
module in CPython.
root_path (str) – Root directory to serve files from
debug (bool) – Enables debug messages useful during development
https (bool) – If True, the server will use HTTPS
certfile (str) – Path to the certificate file, required if https
is True
keyfile (str) – Path to the private key file, required if https
is True
Add multiple routes at once.
routes (List[Route]) – List of routes to add to the server
Example:
from separate_file import external_route1, external_route2 ... server.add_routes([ Route("/example", GET, route_func1, append_slash=True), Route("/example/<my_parameter>", GET, route_func2), Route("/example/..../something", [GET, POST], route_func3), external_route1, external_route2, ]}
Headers to be sent with every response, without the need to specify them in each handler.
If a header is specified in both the handler and the server, the handler’s header will be used.
Example:
server = Server(pool, "/static") server.headers = { "X-Server": "Adafruit CircuitPython HTTP Server", "Access-Control-Allow-Origin": "*", }
Host name or IP address the server is listening on. None
if server is stopped.
Call this method inside your main loop to get the server to check for new incoming client requests. When a request comes in, it will be handled by the handler function.
Returns str representing the result of the poll e.g. NO_REQUEST
or REQUEST_HANDLED_RESPONSE_SENT
.
Port the server is listening on. None
if server is stopped.
The maximum size of the incoming request buffer. If the default size isn’t adequate to handle your incoming data you can set this after creating the server instance.
Default size is 1024 bytes.
Example:
server = Server(pool, "/static") server.request_buffer_size = 2048 server.serve_forever(str(wifi.radio.ipv4_address))
Requires authentication for all routes and files in root_path
. Any non-authenticated request will be rejected with a 401 status code.
Example:
server = Server(pool, "/static") server.require_authentication([Basic("username", "password")])
Root directory to serve files from. None
if serving files is disabled.
Decorator used to add a route.
If request matches multiple routes, the first matched one added will be used.
Example:
# Default method is GET @server.route("/example") def route_func(request): ... # It is necessary to specify other methods like POST, PUT, etc. @server.route("/example", POST) def route_func(request): ... # If you want to access URL with and without trailing slash, use append_slash=True @server.route("/example-with-slash", append_slash=True) # which is equivalent to @server.route("/example-with-slash") @server.route("/example-with-slash/") def route_func(request): ... # Multiple methods can be specified @server.route("/example", [GET, POST]) def route_func(request): ... # URL parameters can be specified @server.route("/example/<my_parameter>", GET) e.g. /example/123 def route_func(request, my_parameter): ... # It is possible to use wildcard that can match any number of path segments @server.route("/example/.../something", GET) # e.g. /example/123/something @server.route("/example/..../something", GET) # e.g. /example/123/456/something def route_func(request): ...
Wait for HTTP requests at the given host and port. Does not return. Ignores any exceptions raised by the handler function and continues to serve. Returns only when the server is stopped by calling .stop()
.
Timeout after which the socket will stop waiting for more incoming data.
Must be set to positive integer or float. Default is 1 second.
When exceeded, raises OSError
with errno.ETIMEDOUT
.
Example:
server = Server(pool, "/static") server.socket_timeout = 3 server.serve_forever(str(wifi.radio.ipv4_address))
Start the HTTP server at the given host and port. Requires calling .poll()
in a while loop to handle incoming requests.
Stops the server from listening for new connections and closes the socket. Current requests will be processed. Server can be started again by calling .start()
or .serve_forever()
.
adafruit_httpserver.request
Author(s): Dan Halbert, Michał Pokusa
Class representing a file uploaded via POST.
Examples:
file = request.form_data.files.get("uploaded_file") # File(filename="foo.txt", content_type="text/plain", size=14) file.content # "Hello, world!\n"
Content of the file.
Content of the file as bytes. It is recommended to use this instead of content
as it will always return bytes.
Example:
file = request.form_data.files.get("uploaded_file") with open(file.filename, "wb") as f: f.write(file.content_bytes)
Content type of the file.
Filename of the file.
Length of the file content.
Class for files uploaded via POST.
Returns a list of field names.
Get the value of a field.
Get the list of values of a field.
Returns a list of (name, value) tuples.
Returns a list of header names.
Returns a list of header values.
Class for parsing and storing form data from POST requests.
Supports application/x-www-form-urlencoded
, multipart/form-data
and text/plain
content types.
Examples:
form_data = FormData(b"foo=bar&baz=qux&baz=quuz", "application/x-www-form-urlencoded") # or form_data = FormData(b"foo=bar\r\nbaz=qux\r\nbaz=quux", "text/plain") # FormData({"foo": ["bar"], "baz": ["qux", "quux"]}) form_data.get("foo") # "bar" form_data["foo"] # "bar" form_data.get("non-existent-key") # None form_data.get_list("baz") # ["qux", "quux"] "unknown-key" in form_data # False form_data.fields # ["foo", "baz"]
Returns a list of field names.
Get the value of a field.
Get the list of values of a field.
Returns a list of (name, value) tuples.
Returns a list of header names.
Returns a list of header values.
Class for parsing and storing GET query parameters requests.
Examples:
query_params = QueryParams("foo=bar&baz=qux&baz=quux") # QueryParams({"foo": ["bar"], "baz": ["qux", "quux"]}) query_params.get("foo") # "bar" query_params["foo"] # "bar" query_params.get("non-existent-key") # None query_params.get_list("baz") # ["qux", "quux"] "unknown-key" in query_params # False query_params.fields # ["foo", "baz"]
Returns a list of field names.
Get the value of a field.
Get the list of values of a field.
Returns a list of (name, value) tuples.
Returns a list of header names.
Returns a list of header values.
Incoming request, constructed from raw incoming bytes. It is passed as first argument to all route handlers.
Body of the request, as bytes.
Address and port bound to the socket on the other end of the connection.
Example:
request.client_address # ('192.168.137.1', 40684)
Socket object used to send and receive data on the connection.
Cookies sent with the request.
Example:
request.headers["Cookie"] # "foo=bar; baz=qux; foo=quux" request.cookies # {"foo": "quux", "baz": "qux"}
POST data of the request.
Example:
# application/x-www-form-urlencoded request = Request(..., raw_request=b"""... foo=bar&baz=qux""" ) # or # multipart/form-data request = Request(..., raw_request=b"""... --boundary Content-Disposition: form-data; name="foo" bar --boundary Content-Disposition: form-data; name="baz" qux --boundary--""" ) # or # text/plain request = Request(..., raw_request=b"""... foo=bar baz=qux """ ) request.form_data # FormData({'foo': ['bar'], 'baz': ['qux']}) request.form_data["foo"] # "bar" request.form_data.get_list("baz") # ["qux"]
Headers from the request.
HTTP version, e.g. "HTTP/1.1"
.
Body of the request, as a JSON-decoded dictionary. Only available for POST, PUT, PATCH and DELETE requests.
Request method e.g. “GET” or “POST”.
Path of the request, e.g. "/foo/bar"
.
Query/GET parameters in the request.
Example:
request = Request(..., raw_request=b"GET /?foo=bar&baz=qux HTTP/1.1...") request.query_params # QueryParams({"foo": "bar"}) request.query_params["foo"] # "bar" request.query_params.get_list("baz") # ["qux"]
Raw bytes
that were received from the client.
Should not be modified directly.
Server object that received the request.
adafruit_httpserver.response
Author(s): Dan Halbert, Michał Pokusa
Specialized version of Response
class for sending data using chunked transfer encoding.
Instead of requiring the whole content to be passed to the constructor, it expects a generator that yields chunks of data.
Example:
@server.route(path, method) def route_func(request: Request): def body(): yield "Some ch" yield "unked co" yield "ntent" return ChunkedResponse(request, body, content_type="text/plain")
request (Request) – Request object
body (Generator) – Generator that yields chunks of data.
status (Status) – Status object or tuple with code and message.
headers (Headers) – Headers to be sent with the response.
cookies (Dict[str, str]) – Cookies to be sent with the response.
content_type (str) – Content type of the response.
Specialized version of Response
class for sending files.
Instead of body
it takes filename
and root_path
arguments. It is also possible to send only headers with head_only
argument or modify buffer_size
.
If browsers should download the file instead of displaying it, use as_attachment
and download_filename
arguments.
Example:
@server.route(path, method) def route_func(request: Request): return FileResponse(request, filename='index.html', root_path='/www')
request (Request) – Request that this is a response to.
filename (str) – Name of the file to send.
root_path (str) – Path to the root directory from which to serve files. Defaults to server’s root_path
.
status (Status) – Status code and text. Defaults to 200 OK
.
headers (Headers) – Headers to include in response.
cookies (Dict[str, str]) – Cookies to be sent with the response.
content_type (str) – Content type of response.
as_attachment (bool) – If True
, the file will be sent as an attachment.
download_filename (str) – Name of the file to send as an attachment.
buffer_size (int) – Size of the buffer used to send the file. Defaults to 1024
.
head_only (bool) – If True
, only headers will be sent. Defaults to False
.
safe (bool) – If True
, checks if filename
is valid. Defaults to True
.
Specialized version of Response
class for sending JSON data.
Instead of requiring body
to be passed to the constructor, it expects data
to be passed instead.
Example:
@server.route(path, method) def route_func(request: Request): return JSONResponse(request, {"key": "value"})
Specialized version of Response
class for redirecting to another URL.
Instead of requiring the body to be passed to the constructor, it expects a URL to redirect to.
Example:
@server.route(path, method) def route_func(request: Request): return Redirect(request, "https://www.example.com")
By default uses permament
and preserve_method
to determine the status
code to use, but if you prefer you can specify it directly.
Note that 301 Moved Permanently
and 302 Found
can change the method to GET
while 307 Temporary Redirect
and 308 Permanent Redirect
preserve the method.
More information: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages
request (Request) – Request that this is a response to.
url (str) – URL to redirect to.
permanent (bool) – Whether to use a permanent redirect or a temporary one.
preserve_method (bool) – Whether to preserve the method of the request.
status (Status) – Status object or tuple with code and message.
headers (Headers) – Headers to include in response.
cookies (Dict[str, str]) – Cookies to be sent with the response.
Response to a given Request
. Use in Server.route
handler functions.
Base class for all other response classes.
Example:
@server.route(path, method) def route_func(request: Request): return Response(request, body='Some content', content_type="text/plain")
request (Request) – Request that this is a response to.
body (str) – Body of response. Defaults to empty string.
status (Status) – Status code and text. Defaults to 200 OK.
headers (Headers) – Headers to include in response. Defaults to empty dict.
cookies (Dict[str, str]) – Cookies to be sent with the response.
content_type (str) – Content type of response. Defaults to None.
Specialized version of Response
class for sending Server-Sent Events.
Allows one way communication with the client using a persistent connection.
Keep in mind, that in order to send events, the socket must be kept open. This means that you have to store the response object somewhere, so you can send events to it and close it later.
It is very important to close the connection manually, it will not be done automatically.
Example:
sse = None @server.route(path, method) def route_func(request: Request): # Store the response object somewhere in global scope global sse sse = SSEResponse(request) return sse ... # Later, when you want to send an event sse.send_event("Simple message") sse.send_event("Message", event="event_name", id=1, retry=5000) # Close the connection sse.close()
Close the connection.
Always call this method when you are done sending events.
Send event to the client.
Specialized version of Response
class for creating a websocket connection.
Allows two way communication between the client and the server.
Keep in mind, that in order to send and receive messages, the socket must be kept open. This means that you have to store the response object somewhere, so you can send events to it and close it later.
It is very important to close the connection manually, it will not be done automatically.
Example:
ws = None @server.route(path, method) def route_func(request: Request): # Store the response object somewhere in global scope global ws ws = Websocket(request) return ws ... # Receive message from client message = ws.receive() # Later, when you want to send an event ws.send_message("Simple message") # Close the connection ws.close()
Close the connection.
Always call this method when you are done sending events.
Receive a message from the client.
fail_silently (bool) – If True, no error will be raised if the connection is closed.
Send a message to the client.
A dict-like class for storing HTTP headers.
Allows access to headers using case insensitive names.
Does not implement all dict methods.
Examples:
headers = Headers("Content-Type: text/html\r\nContent-Length: 1024\r\n") # or headers = Headers({"Content-Type": "text/html", "Content-Length": "1024"}) len(headers) # 2 headers.setdefault("Access-Control-Allow-Origin", "*") headers["Access-Control-Allow-Origin"] # '*' headers["Content-Length"] # '1024' headers["content-type"] # 'text/html' headers["User-Agent"] # KeyError: User-Agent "CONTENT-TYPE" in headers # True
Adds a header with the given field name and value. Allows adding multiple headers with the same name.
Returns a copy of the headers.
Returns a list of field names.
Returns the value for the given header name, or default if not found.
Returns the main value (directive) for the given header name, or default if not found.
Example:
headers = Headers({"Content-Type": "text/html; charset=utf-8"}) headers.get_directive("Content-Type") # 'text/html'
Get the list of values of a field.
Returns the value of the given parameter for the given header name, or default if not found.
Example:
headers = Headers({"Content-Type": "text/html; charset=utf-8"}) headers.get_parameter("Content-Type", "charset") # 'utf-8'
Returns a list of (name, value) tuples.
Returns a list of header names.
Sets the value for the given header name.
Sets the value for the given header name if it does not exist.
Updates the headers with the given dict.
Returns a list of header values.
adafruit_httpserver.status
Author(s): Dan Halbert, Michał Pokusa
HTTP status code.
Define a status code.
adafruit_httpserver.mime_types
Author(s): Michał Pokusa
Contains MIME types for common file extensions. Allows to set default type for unknown files, unregister unused types and register new ones using the MIMETypes.configure()
.
Default MIME type for unknown files. Can be changed using MIMETypes.configure(default_to=...)
.
Allows to globally configure the MIME types.
It is recommended to always call this method before starting the Server
. Unregistering unused MIME types will decrease overall memory usage.
Example:
MIMETypes.configure( default_to="text/plain", keep_for=[".jpg", ".mp4", ".txt"], register={".foo": "text/foo", ".bar": "text/bar", ".baz": "text/baz"}, )
Return the MIME type for the given file name. If the file extension is not registered, default
is returned.
adafruit_httpserver.exceptions
Author(s): Michał Pokusa
Raised by require_authentication
when the Request
is not authorized.
Backslash \
in path.
Creates a new BackslashInPathError
for the path
.
Raised when a file does not exist.
Creates a new FileNotExistsError
for the file at path
.
Parent class for all path related errors.
Path contains ..
, a reference to the parent directory.
Creates a new ParentDirectoryReferenceError
for the path
.
Raised when .poll
is called on a stopped Server
.
Raised when root_path
is not set and there is no handler for request
.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4