From ae38910979d0a13960d85e2cc01dce93c48669f2 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Fri, 9 Oct 2020 11:11:47 -0600 Subject: [PATCH] Handle HTTP errors and content type better --- adafruit_pyportal.py | 65 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 12 deletions(-) mode change 100644 => 100755 adafruit_pyportal.py diff --git a/adafruit_pyportal.py b/adafruit_pyportal.py old mode 100644 new mode 100755 index a87cab5..12bbe42 --- a/adafruit_pyportal.py +++ b/adafruit_pyportal.py @@ -46,6 +46,7 @@ import os import time import gc +from micropython import const import board import busio from digitalio import DigitalInOut @@ -108,20 +109,29 @@ LOCALFILE = "local.txt" # pylint: enable=line-too-long +CONTENT_TEXT = const(1) +CONTENT_JSON = const(2) +CONTENT_IMAGE = const(3) + class Fake_Requests: """For faking 'requests' using a local file instead of the network.""" def __init__(self, filename): self._filename = filename - with open(filename, "r") as file: - self.text = file.read() def json(self): """json parsed version for local requests.""" import json # pylint: disable=import-outside-toplevel - return json.loads(self.text) + with open(self._filename, "r") as file: + return json.load(file) + + @property + def text(self): + """raw text version for local requests.""" + with open(self._filename, "r") as file: + return file.read() class PyPortal: @@ -729,14 +739,17 @@ def wget(self, url, filename, *, chunk_size=12000): self.neo_status((100, 100, 0)) r = requests.get(url, stream=True) + headers = {} + for title, content in r.headers.items(): + headers[title.lower()] = content if self._debug: - print(r.headers) - if "content-length" in r.headers: - content_length = int(r.headers["content-length"]) - remaining = content_length + print(headers) + if "content-length" in headers: + content_length = int(headers["content-length"]) else: - raise RuntimeError("Content-length missing from headers") + raise RuntimeError("Content-Length missing from headers") + remaining = content_length print("Saving data to ", filename) stamp = time.monotonic() file = open(filename, "wb") @@ -871,6 +884,7 @@ def fetch(self, refresh_url=None, timeout=10): json_out = None image_url = None values = [] + content_type = CONTENT_TEXT gc.collect() if self._debug: @@ -888,14 +902,41 @@ def fetch(self, refresh_url=None, timeout=10): self.neo_status((100, 100, 0)) # yellow = fetching data gc.collect() r = requests.get(self._url, headers=self._headers, timeout=timeout) + headers = {} + for title, content in r.headers.items(): + headers[title.lower()] = content gc.collect() - self.neo_status((0, 0, 100)) # green = got data - print("Reply is OK!") + if self._debug: + print("Headers:", headers) + if r.status_code == 200: + print("Reply is OK!") + self.neo_status((0, 0, 100)) # green = got data + if "content-type" in headers: + if "image/" in headers["content-type"]: + content_type = CONTENT_IMAGE + elif "application/json" in headers["content-type"]: + content_type = CONTENT_JSON + else: + print( + "HTTP Error {}: {}".format(r.status_code, r.reason.decode("utf-8")) + ) + if self._debug: + if "content-length" in headers: + print( + "Content-Length: {}".format(int(headers["content-length"])) + ) + if "date" in headers: + print("Date: {}".format(headers["date"])) + self.neo_status((100, 0, 0)) # red = http error + return None - if self._debug and not self._image_json_path and not self._json_path: + if self._debug and content_type == CONTENT_TEXT: print(r.text) - if self._image_json_path or self._json_path: + if self._debug: + print("Detected Content Type", content_type) + + if content_type == CONTENT_JSON: try: gc.collect() json_out = r.json()