diff --git a/adafruit_esp32spi/adafruit_esp32spi_requests.py b/adafruit_esp32spi/adafruit_esp32spi_requests.py deleted file mode 100755 index 994af94..0000000 --- a/adafruit_esp32spi/adafruit_esp32spi_requests.py +++ /dev/null @@ -1,266 +0,0 @@ -# The MIT License (MIT) -# -# Copyright (c) 2019 Paul Sokolovsky & ladyada for Adafruit Industries -# -# 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. - - -""" -`adafruit_esp32spi_requests` -================================================================================ -A requests-like library for web interfacing - - -* Author(s): ladyada, Paul Sokolovsky - -Implementation Notes --------------------- - -Adapted from https://github.com/micropython/micropython-lib/tree/master/urequests - -micropython-lib consists of multiple modules from different sources and -authors. Each module comes under its own licensing terms. Short name of -a license can be found in a file within a module directory (usually -metadata.txt or setup.py). Complete text of each license used is provided -at https://github.com/micropython/micropython-lib/blob/master/LICENSE - -author='Paul Sokolovsky' -license='MIT' -""" - -# pylint: disable=no-name-in-module - -import gc -import adafruit_esp32spi.adafruit_esp32spi_socket as socket - -_the_interface = None # pylint: disable=invalid-name -def set_interface(iface): - """Helper to set the global internet interface""" - global _the_interface # pylint: disable=invalid-name, global-statement - _the_interface = iface - socket.set_interface(iface) - -class Response: - """The response from a request, contains all the headers/content""" - encoding = None - - def __init__(self, sock): - self.socket = sock - self.encoding = "utf-8" - self._cached = None - self.status_code = None - self.reason = None - self._read_so_far = 0 - self.headers = {} - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.close() - - def close(self): - """Close, delete and collect the response data""" - if self.socket: - self.socket.close() - del self.socket - del self._cached - gc.collect() - - @property - def content(self): - """The HTTP content direct from the socket, as bytes""" - #print(self.headers) - try: - content_length = int(self.headers['content-length']) - except KeyError: - content_length = 0 - #print("Content length:", content_length) - if self._cached is None: - try: - self._cached = self.socket.read(content_length) - finally: - self.socket.close() - self.socket = None - #print("Buffer length:", len(self._cached)) - return self._cached - - @property - def text(self): - """The HTTP content, encoded into a string according to the HTTP - header encoding""" - return str(self.content, self.encoding) - - def json(self): - """The HTTP content, parsed into a json dictionary""" - try: - import json as json_module - except ImportError: - import ujson as json_module - return json_module.loads(self.content) - - def iter_content(self, chunk_size=1, decode_unicode=False): - """An iterator that will stream data by only reading 'chunk_size' - bytes and yielding them, when we can't buffer the whole datastream""" - if decode_unicode: - raise NotImplementedError("Unicode not supported") - - while True: - chunk = self.socket.read(chunk_size) - if chunk: - yield chunk - else: - return - -# pylint: disable=too-many-branches, too-many-statements, unused-argument, too-many-arguments, too-many-locals -def request(method, url, data=None, json=None, headers=None, stream=False, timeout=1): - """Perform an HTTP request to the given url which we will parse to determine - whether to use SSL ('https://') or not. We can also send some provided 'data' - or a json dictionary which we will stringify. 'headers' is optional HTTP headers - sent along. 'stream' will determine if we buffer everything, or whether to only - read only when requested - """ - global _the_interface # pylint: disable=global-statement, invalid-name - - if not headers: - headers = {} - - try: - proto, dummy, host, path = url.split("/", 3) - # replace spaces in path - path = path.replace(" ", "%20") - except ValueError: - proto, dummy, host = url.split("/", 2) - path = "" - if proto == "http:": - port = 80 - elif proto == "https:": - port = 443 - else: - raise ValueError("Unsupported protocol: " + proto) - - if ":" in host: - host, port = host.split(":", 1) - port = int(port) - - addr_info = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)[0] - sock = socket.socket(addr_info[0], addr_info[1], addr_info[2]) - resp = Response(sock) # our response - - sock.settimeout(timeout) # socket read timeout - - try: - if proto == "https:": - conntype = _the_interface.TLS_MODE - sock.connect((host, port), conntype) # for SSL we need to know the host name - else: - conntype = _the_interface.TCP_MODE - sock.connect(addr_info[-1], conntype) - sock.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) - if "Host" not in headers: - sock.write(b"Host: %s\r\n" % host) - if "User-Agent" not in headers: - sock.write(b"User-Agent: Adafruit CircuitPython\r\n") - # Iterate over keys to avoid tuple alloc - for k in headers: - sock.write(k.encode()) - sock.write(b": ") - sock.write(headers[k].encode()) - sock.write(b"\r\n") - if json is not None: - assert data is None - try: - import json as json_module - except ImportError: - import ujson as json_module - data = json_module.dumps(json) - sock.write(b"Content-Type: application/json\r\n") - if data: - sock.write(b"Content-Length: %d\r\n" % len(data)) - sock.write(b"\r\n") - if data: - sock.write(bytes(data, 'utf-8')) - - line = sock.readline() - #print(line) - line = line.split(None, 2) - status = int(line[1]) - reason = "" - if len(line) > 2: - reason = line[2].rstrip() - resp.headers = parse_headers(sock) - if "chunked" in resp.headers.get("transfer-encoding"): - raise ValueError("Unsupported " + line) - elif resp.headers.get("location") and not 200 <= status <= 299: - raise NotImplementedError("Redirects not yet supported") - - except: - sock.close() - raise - - resp.status_code = status - resp.reason = reason - return resp -# pylint: enable=too-many-branches, too-many-statements, unused-argument -# pylint: enable=too-many-arguments, too-many-locals - -def parse_headers(sock): - """ - Parses the header portion of an HTTP request/response from the socket. - Expects first line of HTTP request/response to have been read already - return: header dictionary - rtype: Dict - """ - headers = {} - while True: - line = sock.readline() - if not line or line == b"\r\n": - break - - #print("**line: ", line) - title, content = line.split(b': ', 1) - if title and content: - title = str(title.lower(), 'utf-8') - content = str(content, 'utf-8') - headers[title] = content - return headers - -def head(url, **kw): - """Send HTTP HEAD request""" - return request("HEAD", url, **kw) - -def get(url, **kw): - """Send HTTP GET request""" - return request("GET", url, **kw) - -def post(url, **kw): - """Send HTTP POST request""" - return request("POST", url, **kw) - -def put(url, **kw): - """Send HTTP PUT request""" - return request("PUT", url, **kw) - -def patch(url, **kw): - """Send HTTP PATCH request""" - return request("PATCH", url, **kw) - -def delete(url, **kw): - """Send HTTP DELETE request""" - return request("DELETE", url, **kw) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 28b08b0..8d9a97a 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -34,7 +34,8 @@ from time import sleep from micropython import const from adafruit_esp32spi import adafruit_esp32spi -import adafruit_esp32spi.adafruit_esp32spi_requests as requests +import adafruit_esp32spi.adafruit_esp32spi_socket as socket +import adafruit_requests as requests class ESPSPI_WiFiManager: """ @@ -61,7 +62,7 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type= self.password = secrets['password'] self.attempts = attempts self._connection_type = connection_type - requests.set_interface(self.esp) + requests.set_socket(socket, esp) self.statuspix = status_pixel self.pixel_status(0) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index 0d538e8..8bd15b4 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py @@ -50,7 +50,7 @@ import gc from micropython import const import adafruit_esp32spi.adafruit_esp32spi_socket as socket -from adafruit_esp32spi.adafruit_esp32spi_requests import parse_headers +from adafruit_requests import parse_headers _the_interface = None # pylint: disable=invalid-name def set_interface(iface): diff --git a/docs/api.rst b/docs/api.rst index a952f25..bee5de4 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -7,8 +7,5 @@ .. automodule:: adafruit_esp32spi.adafruit_esp32spi :members: -.. automodule:: adafruit_esp32spi.adafruit_esp32spi_requests - :members: - .. automodule:: adafruit_esp32spi.adafruit_esp32spi_socket :members: diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index 252723a..31dc67d 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -1,9 +1,9 @@ import board import busio from digitalio import DigitalInOut - +import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi -import adafruit_esp32spi.adafruit_esp32spi_requests as requests +import adafruit_requests as requests print("ESP32 SPI webclient test") @@ -24,7 +24,7 @@ spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) -requests.set_interface(esp) +requests.set_socket(socket, esp) if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode") diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index 2eb06b6..553590e 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -12,8 +12,9 @@ import busio from digitalio import DigitalInOut +import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi -import adafruit_esp32spi.adafruit_esp32spi_requests as requests +import adafruit_requests as requests # Version number comparison code. Credit to gnud on stackoverflow # (https://stackoverflow.com/a/1714190), swapping out cmp() to @@ -40,7 +41,7 @@ def normalize(v): spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) -requests.set_interface(esp) +requests.set_socket(socket, esp) if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode")