Module urest.http

Network interface and helper classes for abstracting the underlying HTTP stream

Overview

This module provides the abstraction of the underlying socket handling code, using in marshaling requests from clients and building the response. All the socket handling is built around the Python 3 asyncio library for the low-level network interface, and for the use of co-routines to simplify request handling.

In most cases, consumers of this module only need to provide an asynio event loop: see "Creating the Network Server" in the Section Using the Module below. By default the module will also bind to the network address of the host on the standard port 80 used by HTTP requests. This can be changed in the instantiation of the RESTServer class.

Implementation

During the instantiation of the RESTServer class, the resulting object creates a socket bound to the specified address and port (or the host network address and port 80 by default). This binding is undertaken as part of the asyncio

Using The Module

Creating the Network Server

All network clients are assumed to be handled by an instance of the RESTServer class from the urest.http.server module. The RESTServer class provides both an event loop for the asyncio library, and also takes care of the lower-level networking interface for the clients. Unless working with multiple instances (e.g. via a thread library), most model consumers are assumed have a single instance of the RESTServerbut the module will not check this.

In most cases, something similar to the following will suffice

  # Import the Asynchronous IO Library
  try:
    import uasyncio as asyncio
  except ImportError:
    import asyncio

  from urest.http import RESTServer

  app = RESTServer()

  if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.create_task(app.start())
    loop.run_forever()

Warning

There is no guarantee of thread-safety in this module, and all 'concurrency' is assumed to be via co-routines provided by the asyncio library. For an overview of how multiple clients can be handled using co-routines, Async IO in Python is highly recommended reading.

Creating the API Responses

Most module consumers will not use the urest.http.response module directly: but will instead sub-class APIBase to provide the core of the response to the network clients. For details of how the RESTServer and APIBase classes interact, the module documentation for urest.api should be consulted. In addition, the documentation for the SimpleLED class might prove useful as an example of a simple implementation of the API.

Tested Implementations

This version is written for MicroPython 3.4, and has been tested on:

  • Raspberry Pi Pico W

Licence

This module, and all included code, is made available under the terms of the MIT Licence

Copyright 2021–2022 (c) Erik de Lange, Copyright (c) 2022–2023 David Love

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Expand source code
"""
Network interface and helper classes for abstracting the underlying HTTP stream

Overview
--------

This module provides the abstraction of the underlying socket handling code,
using in marshaling requests from clients and building the response. All the
socket handling is built around the Python 3 `asyncio` library for the low-level
network interface, and for the use of co-routines to simplify request handling.

In most cases, consumers of this module only need to provide an `asynio` event
loop: see "Creating the Network Server" in the Section _Using the Module_ below.
By default the module will also bind to the _network_ address of the host on the
standard port 80 used by HTTP requests. This can be changed in the instantiation
of the  `urest.http.server.RESTServer` class.

Implementation
--------------

During the instantiation of the `urest.http.server.RESTServer` class, the resulting
object creates a socket bound to the specified address and port (or the host network
address and port 80 by default). This binding is undertaken as part of the `asyncio`


Using the Module
----------------

### Creating the Network Server

All network clients are assumed to be handled by an instance of the
`urest.http.server.RESTServer` class from the `urest.http.server` module. The
`urest.http.server.RESTServer` class provides both an event loop for the
`asyncio` library, and also takes care of the lower-level networking interface
for the clients. Unless working with multiple instances (e.g. via a thread
library), most model consumers are assumed have a single instance of the
`urest.http.server.RESTServer` --- **but the module will not check this**.

In most cases, something similar to the following will suffice

```python
  # Import the Asynchronous IO Library
  try:
    import uasyncio as asyncio
  except ImportError:
    import asyncio

  from urest.http import RESTServer

  app = RESTServer()

  if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.create_task(app.start())
    loop.run_forever()
```

.. Warning::

  There is no guarantee of thread-safety in this module, and all
  'concurrency' is assumed to be via co-routines provided by the `asyncio`
  library. For an overview of how multiple clients can be handled using
  co-routines, [Async IO in Python](https://realpython.com/async-io-python) is
  highly recommended reading.

### Creating the API Responses

Most module consumers will not use the `urest.http.response` module directly:
but will instead sub-class `urest.api.base.APIBase` to provide the core of the
response to the network clients. For details of how the `urest.http.server.RESTServer` and `urest.api.base.APIBase` classes interact, the module documentation for `urest.api` should be consulted. In addition, the documentation for the `urest.examples.simpleled.SimpleLED` class might prove useful as an example of a simple implementation of the API.


Tested Implementations
----------------------

This version is written for MicroPython 3.4, and has been tested on:

  * Raspberry Pi Pico W

Licence
-------

This module, and all included code, is made available under the terms of the MIT Licence

> Copyright 2021--2022 (c) Erik de Lange, Copyright (c) 2022--2023 David Love

> Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

> The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""

### Expose the `http` module interface
from .server import RESTServer
from .response import HTTPResponse

Sub-modules

urest.http.response

Formats a basic HTTP/1.1 response. The actual body of the response is largely determined by the callers API layer: HTTPResponse

urest.http.server

Micro HTTP server dedicated to REST-style API Requests. Inspired by the [MicroPython HTTP …