From 7ed40e46a7ea71bf9b7ba9c4dc690f51dc7c90ae Mon Sep 17 00:00:00 2001 From: Maff Date: Thu, 31 May 2018 23:43:31 +0100 Subject: [PATCH] this isn't working right now; refactored and drastically minified microWebSrv, unfortunately on an esp8266 it won't import due to low memory. unsure why, will work out another day. --- bme280.py | 35 ---- boot.py | 13 +- main.py | 38 ++-- microWebSrv.py | 547 +++++++------------------------------------------ 4 files changed, 93 insertions(+), 540 deletions(-) diff --git a/bme280.py b/bme280.py index ad150b2..4eb6d2a 100644 --- a/bme280.py +++ b/bme280.py @@ -1,37 +1,3 @@ -# Authors: Paul Cunnane 2016, Peter Dahlebrg 2016 -# -# This module borrows from the Adafruit BME280 Python library. Original -# Copyright notices are reproduced below. -# -# Those libraries were written for the Raspberry Pi. This modification is -# intended for the MicroPython and esp8266 boards. -# -# Copyright (c) 2014 Adafruit Industries -# Author: Tony DiCola -# -# Based on the BMP280 driver with BME280 changes provided by -# David J Taylor, Edinburgh (www.satsignal.eu) -# -# Based on Adafruit_I2C.py created by Kevin Townsend. -# -# 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. - import time from ustruct import unpack, unpack_from from array import array @@ -51,7 +17,6 @@ BME280_REGISTER_CONTROL = 0xF4 class BME280: - def __init__(self, mode=BME280_OSAMPLE_1, address=BME280_I2CADDR, diff --git a/boot.py b/boot.py index d7b1404..84c470e 100644 --- a/boot.py +++ b/boot.py @@ -1,12 +1,7 @@ -# This file is executed on every boot (including wake-boot from deepsleep) -#import esp -#esp.osdebug(None) - -import network from network import WLAN as wlan, STA_IF as staif, AP_IF as apif -import time +from time import sleep_ms -time.sleep_ms(100) +sleep_ms(100) #make sure AP mode is off and station mode is on if wlan(apif).active() == True: wlan(apif).active(False) @@ -30,7 +25,7 @@ if wlan(staif).isconnected() != True: break if found_net == False: print("couldn't connect to wifi, nets found: %s" % nets) - print("to fix temporarily, run: from network import STA_IF,WLAN as wlan;wlan(STA_IF).connect('yournet','yourpass'), followed shortly after by wlan(STA_IF).ifconfig()") + print("to fix temporarily, run: wlan(staif).connect('yournet','yourpass'), followed shortly after by wlan(staif).ifconfig()") #exit else: #Loop until wifi is connected and passes DHCP, or until 30 seconds have elapsed. @@ -38,7 +33,7 @@ if wlan(staif).isconnected() != True: while wlan(staif).ifconfig()[0] == '0.0.0.0' or wlan(staif).isconnected() == False: if slept > 300: break - time.sleep_ms(100) + sleep_ms(100) slept+=1 #import webrepl diff --git a/main.py b/main.py index 6ea3112..2f04921 100644 --- a/main.py +++ b/main.py @@ -6,58 +6,48 @@ hw = uPyConfig.esp8266(variant='d1-r2') #init_sample.init_sample(hw) # Main app -import uPySensor -sensors={ - 'bme280': uPySensor.BME280(hw.i2c.bus), - 'lm75a': uPySensor.LM75A(hw.i2c.bus), - 'sht21': uPySensor.SHT21(hw.i2c.bus), -} - -from microWebSrv import MicroWebSrv -ws = MicroWebSrv() -ws.WebSocketThreaded = False - wshead={ 'Server':'horny', } wsctype='application/json' wscharset='UTF-8' + +import uPySensor +bme280=uPySensor.BME280(hw.i2c.bus) +lm75a =uPySensor.LM75A(hw.i2c.bus) +sht21 =uPySensor.SHT21(hw.i2c.bus) + +from microWebSrv import MicroWebSrv @MicroWebSrv.route('/') def get_root(wscl, wsres): wsres.WriteResponseOk( headers=wshead, contentType=wsctype, - contentCharset=wscharset, content='{"result":"error","message":"use /bme280, /lm75a or /sht21 for sensor readings"}' ) @MicroWebSrv.route('/bme280') def get_bme280(wscl, wsres): - sensors['bme280'].update_sensor() - json = '{"temperature":"%0.2f","humidity":"%0.2f","pressure":"%0.2f"}' % ( - sensors['bme280'].temperature, sensors['bme280'].humidity, sensors['bme280'].pressure) + bme280.update_sensor() wsres.WriteResponseOk( headers=wshead, contentType=wsctype, - contentCharset=wscharset, - content=None + content='{"temperature":"%0.2f","humidity":"%0.2f","pressure":"%0.2f"}' % ( + bme280.temperature, bme280.humidity, bme280.pressure) ) @MicroWebSrv.route('/lm75a') def get_lm75a(wscl, wsres): - json = '{"temperature":"%0.1f"}' % sensors['lm75a'].read_tempC() wsres.WriteResponseOk( headers=wshead, contentType=wsctype, - contentCharset=wscharset, - content=json + content='{"temperature":"%0.1f"}' % lm75a.read_tempC() ) @MicroWebSrv.route('/sht21') def sht21(wscl, wsres): - json = '{"temperature":"%0.3f","humidity":"%0.3f"}' % (sensors['sht21'].read_tempC(), sensors['sht21'].read_hum()) wsres.WriteResponseOk( headers=wshead, contentType=wsctype, - contentCharset=wscharset, - content=json + content='{"temperature":"%0.3f","humidity":"%0.3f"}' % (sht21.read_tempC(), sht21.read_hum()) ) -ws.Start(threaded=False, stackSize=8192) +ws = MicroWebSrv() +ws.Start() diff --git a/microWebSrv.py b/microWebSrv.py index d9b407f..18db587 100644 --- a/microWebSrv.py +++ b/microWebSrv.py @@ -1,17 +1,5 @@ -""" -The MIT License (MIT) -Copyright © 2018 Jean-Christophe Bos & HC² (www.hc2.fr) -Copyright © 2018 LoBo (https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo) -""" - -from json import loads, dumps -from os import stat -import _thread -import network -import time import socket -import gc -import re +from ure import compile class MicroWebSrvRoute: def __init__(self, route, method, func, routeArgNames, routeRegex): @@ -21,12 +9,7 @@ class MicroWebSrvRoute: self.routeArgNames = routeArgNames self.routeRegex = routeRegex - class MicroWebSrv: - # ============================================================================ - # ===( Constants )============================================================ - # ============================================================================ - _html_escape_chars = { "&": "&", '"': """, @@ -34,62 +17,29 @@ class MicroWebSrv: ">": ">", "<": "<" } - - # ============================================================================ - # ===( Class globals )======================================================= - # ============================================================================ - - _docoratedRouteHandlers = [] - - # ============================================================================ - # ===( Utils )=============================================================== - # ============================================================================ + _decoratedRouteHandlers = [] @classmethod def route(cls, url, method='GET'): - """ Adds a route handler function to the routing list """ - def route_decorator(func): item = (url, method, func) - cls._docoratedRouteHandlers.append(item) + cls._decoratedRouteHandlers.append(item) return func - return route_decorator - # ---------------------------------------------------------------------------- - @staticmethod def HTMLEscape(s): return ''.join(MicroWebSrv._html_escape_chars.get(c, c) for c in s) - # ---------------------------------------------------------------------------- - @staticmethod def _tryAllocByteArray(size): for x in range(10): try: - gc.collect() return bytearray(size) except: pass return None - # ---------------------------------------------------------------------------- - - @staticmethod - def _tryStartThread(func, args=(), stacksize=8192): - _ = _thread.stack_size(stacksize) - for x in range(10): - try: - gc.collect() - th = _thread.start_new_thread("MicroWebServer", func, args) - return th - except: - time.sleep_ms(100) - return False - - # ---------------------------------------------------------------------------- - @staticmethod def _unquote(s): r = s.split('%') @@ -101,33 +51,22 @@ class MicroWebSrv: r[i] = '%' + s return ''.join(r) - # ---------------------------------------------------------------------------- - @staticmethod def _unquote_plus(s): return MicroWebSrv._unquote(s.replace('+', ' ')) - # ============================================================================ - # ===( Constructor )========================================================== - # ============================================================================ - def __init__(self, routeHandlers=[], port=80, bindIP='0.0.0.0'): self._srvAddr = (bindIP, port) - self._notFoundUrl = None self._started = False - self.thID = None - self.isThreaded = False - self._state = "Stopped" self._routeHandlers = [] - routeHandlers += self._docoratedRouteHandlers + routeHandlers += self._decoratedRouteHandlers for route, method, func in routeHandlers: routeParts = route.split('/') - # -> ['', 'users', '', 'addresses', '', 'test', ''] routeArgNames = [] routeRegex = '' for s in routeParts: @@ -137,133 +76,59 @@ class MicroWebSrv: elif s: routeRegex += '/' + s routeRegex += '$' - # -> '/users/(\w*)/addresses/(\w*)/test/(\w*)$' - routeRegex = re.compile(routeRegex) - + routeRegex = compile(routeRegex) self._routeHandlers.append(MicroWebSrvRoute(route, method, func, routeArgNames, routeRegex)) - # ============================================================================ - # ===( Server Process )======================================================= - # ============================================================================ - def _serverProcess(self): self._started = True - self._state = "Running" while True: try: client, cliAddr = self._server.accepted() - if client == None: - if self.isThreaded: - notify = _thread.getnotification() - if notify == _thread.EXIT: - break - elif notify == _thread.SUSPEND: - self._state = "Suspended" - while _thread.wait() != _thread.RESUME: - pass - self._state = "Running" - # gc.collect() - time.sleep_ms(2) - continue + if client == None: continue except Exception as e: - if not self.isThreaded: - print(e) + print(e) break self._client(self, client, cliAddr) self._started = False - self._state = "Stopped" - self.thID = None - # ============================================================================ - # ===( Functions )============================================================ - # ============================================================================ - - def Start(self, threaded=True, stackSize=8192): - if not self._started: - if not network.WLAN().wifiactive(): - print("WLAN not connected!") - return - gc.collect() - self._server = socket.socket(socket.AF_INET, - socket.SOCK_STREAM, - socket.IPPROTO_TCP) - self._server.setsockopt(socket.SOL_SOCKET, - socket.SO_REUSEADDR, - 1) - self._server.bind(self._srvAddr) - self._server.listen(1) - self.isThreaded = threaded - # using non-blocking socket - self._server.settimeout(0.5) - if threaded: - th = MicroWebSrv._tryStartThread(self._serverProcess, stacksize=stackSize) - if th: - self.thID = th - else: - self._serverProcess() - - # ---------------------------------------------------------------------------- + def Start(self): + if self._started: return + self._server = socket.socket(socket.AF_INET, + socket.SOCK_STREAM, + socket.IPPROTO_TCP) + self._server.setsockopt(socket.SOL_SOCKET, + socket.SO_REUSEADDR, + 1) + self._server.bind(self._srvAddr) + self._server.listen(1) + self._server.settimeout(0.5) + self._serverProcess() def Stop(self): - if self._started: - self._server.close() - if self.isThreaded: - _ = _thread.notify(self.thID, _thread.EXIT) - - # ---------------------------------------------------------------------------- - - def IsStarted(self): - return self._started - - # ---------------------------------------------------------------------------- - - def threadID(self): - return self.thID - - # ---------------------------------------------------------------------------- - - def State(self): - return self._state - - # ---------------------------------------------------------------------------- - - def SetNotFoundPageUrl(self, url=None): - self._notFoundUrl = url - - # ---------------------------------------------------------------------------- + if not self._started: return + self._server.close() def GetRouteHandler(self, resUrl, method): - if self._routeHandlers: - # resUrl = resUrl.upper() - if resUrl.endswith('/'): - resUrl = resUrl[:-1] - method = method.upper() - for rh in self._routeHandlers: - if rh.method == method: - m = rh.routeRegex.match(resUrl) - if m: # found matching route? - if rh.routeArgNames: - routeArgs = {} - for i, name in enumerate(rh.routeArgNames): - value = m.group(i + 1) - try: - value = int(value) - except: - pass - routeArgs[name] = value - return (rh.func, routeArgs) - else: - return (rh.func, None) + if not self._routeHandlers: + return (None, None) + if resUrl.endswith('/'): + resUrl = resUrl[:-1] + method = method.upper() + for rh in self._routeHandlers: + if rh.method == method: + m = rh.routeRegex.match(resUrl) + if m and rh.routeArgNames: + routeArgs = {} + for i, name in enumerate(rh.routeArgNames): + value = m.group(i + 1) + try: value = int(value) + except: pass + routeArgs[name] = value + return (rh.func, routeArgs) + elif m: return (rh.func, None) return (None, None) - # ============================================================================ - # ===( Class Client )======================================================== - # ============================================================================ - class _client: - - # ------------------------------------------------------------------------ - def __init__(self, microWebSrv, socket, addr): socket.settimeout(2) self._microWebSrv = microWebSrv @@ -281,63 +146,43 @@ class MicroWebSrv: self._processRequest() - # ------------------------------------------------------------------------ - def _processRequest(self): try: response = MicroWebSrv._response(self) - if self._parseFirstLine(response): - if self._parseHeader(response): - upg = self._getConnUpgrade() - if not upg: - routeHandler, routeArgs = self._microWebSrv.GetRouteHandler(self._resPath, self._method) - if routeHandler: - if routeArgs is not None: - routeHandler(self, response, routeArgs) - else: - routeHandler(self, response) - elif self._method.upper() == "GET": - response.WriteResponseNotFound() - else: - response.WriteResponseMethodNotAllowed() - else: - response.WriteResponseNotImplemented() - else: - response.WriteResponseBadRequest() - except: - response.WriteResponseInternalServerError() - try: - self._socket.close() - except: - pass - - # ------------------------------------------------------------------------ + if self._parseFirstLine(response) and self._parseHeader(response): + routeHandler, routeArgs = self._microWebSrv.GetRouteHandler(self._resPath, self._method) + if routeHandler and routeArgs is not None: + routeHandler(self, response, routeArgs) + elif routeHandler: + routeHandler(self, response) + else: response.WriteResponseNotFound() + except: response.WriteResponseInternalServerError() + try: self._socket.close() + except: pass def _parseFirstLine(self, response): try: elements = self._socket.readline().decode().strip().split() - if len(elements) == 3: - self._method = elements[0].upper() - self._path = elements[1] - self._httpVer = elements[2].upper() - elements = self._path.split('?', 1) - if len(elements) > 0: - self._resPath = MicroWebSrv._unquote_plus(elements[0]) - if len(elements) > 1: - self._queryString = elements[1] - elements = self._queryString.split('&') - for s in elements: - param = s.split('=', 1) - if len(param) > 0: - value = MicroWebSrv._unquote(param[1]) if len(param) > 1 else '' - self._queryParams[MicroWebSrv._unquote(param[0])] = value - return True + if len(elements) != 3: return False + self._method = elements[0].upper() + self._path = elements[1] + self._httpVer = elements[2].upper() + elements = self._path.split('?', 1) + if len(elements) < 1: return True + self._resPath = MicroWebSrv._unquote_plus(elements[0]) + if len(elements) < 2: return True + self._queryString = elements[1] + elements = self._queryString.split('&') + for s in elements: + param = s.split('=', 1) + if len(param) > 0: + value = MicroWebSrv._unquote(param[1]) if len(param) > 1 else '' + self._queryParams[MicroWebSrv._unquote(param[0])] = value + return True except: pass return False - # ------------------------------------------------------------------------ - def _parseHeader(self, response): while True: elements = self._socket.readline().decode().strip().split(':', 1) @@ -351,75 +196,6 @@ class MicroWebSrv: else: return False - # ------------------------------------------------------------------------ - - def _getConnUpgrade(self): - if 'upgrade' in self._headers.get('Connection', '').lower(): - return self._headers.get('Upgrade', '').lower() - return None - - # ------------------------------------------------------------------------ - - def GetServer(self): - return self._microWebSrv - - # ------------------------------------------------------------------------ - - def GetAddr(self): - return self._addr - - # ------------------------------------------------------------------------ - - def GetIPAddr(self): - return self._addr[0] - - # ------------------------------------------------------------------------ - - def GetPort(self): - return self._addr[1] - - # ------------------------------------------------------------------------ - - def GetRequestMethod(self): - return self._method - - # ------------------------------------------------------------------------ - - def GetRequestTotalPath(self): - return self._path - - # ------------------------------------------------------------------------ - - def GetRequestPath(self): - return self._resPath - - # ------------------------------------------------------------------------ - - def GetRequestQueryString(self): - return self._queryString - - # ------------------------------------------------------------------------ - - def GetRequestQueryParams(self): - return self._queryParams - - # ------------------------------------------------------------------------ - - def GetRequestHeaders(self): - return self._headers - - # ------------------------------------------------------------------------ - - def GetRequestContentType(self): - return self._contentType - - # ------------------------------------------------------------------------ - - def GetRequestContentLength(self): - return self._contentLength - - # ------------------------------------------------------------------------ - def ReadRequestContent(self, size=None): self._socket.setblocking(False) b = None @@ -433,59 +209,34 @@ class MicroWebSrv: self._socket.setblocking(True) return b if b else b'' - # ------------------------------------------------------------------------ - def ReadRequestPostedFormData(self): res = {} data = self.ReadRequestContent() - if len(data) > 0: - elements = data.decode().split('&') - for s in elements: - param = s.split('=', 1) - if len(param) > 0: - value = MicroWebSrv._unquote(param[1]) if len(param) > 1 else '' - res[MicroWebSrv._unquote(param[0])] = value + if len(data) < 1: return res + elements = data.decode().split('&') + for s in elements: + param = s.split('=', 1) + if len(param) < 1: next + value = MicroWebSrv._unquote(param[1]) if len(param) > 1 else '' + res[MicroWebSrv._unquote(param[0])] = value return res - # ------------------------------------------------------------------------ - - def ReadRequestContentAsJSON(self): - try: - return loads(self.ReadRequestContent()) - except: - return None - - # ============================================================================ - # ===( Class Response )====================================================== - # ============================================================================ - class _response: - - # ------------------------------------------------------------------------ - def __init__(self, client): self._client = client - # ------------------------------------------------------------------------ - def _write(self, data): if type(data) == str: data = data.encode() return self._client._socket.write(data) - # ------------------------------------------------------------------------ - def _writeFirstLine(self, code): reason = self._responseCodes.get(code, ('Unknown reason',))[0] self._write("HTTP/1.1 %s %s\r\n" % (code, reason)) - # ------------------------------------------------------------------------ - def _writeHeader(self, name, value): self._write("%s: %s\r\n" % (name, value)) - # ------------------------------------------------------------------------ - def _writeContentTypeHeader(self, contentType, charset=None): if contentType: ct = contentType \ @@ -494,18 +245,12 @@ class MicroWebSrv: ct = "application/octet-stream" self._writeHeader("Content-Type", ct) - # ------------------------------------------------------------------------ - def _writeServerHeader(self): - self._writeHeader("Server", "MicroWebSrv by JC`zic") - - # ------------------------------------------------------------------------ + self._writeHeader("Server", "MicroWebSrv lite") def _writeEndHeader(self): self._write("\r\n") - # ------------------------------------------------------------------------ - def _writeBeforeContent(self, code, headers, contentType, contentCharset, contentLength): self._writeFirstLine(code) if isinstance(headers, dict): @@ -518,20 +263,6 @@ class MicroWebSrv: self._writeHeader("Connection", "close") self._writeEndHeader() - # ------------------------------------------------------------------------ - - def WriteSwitchProto(self, upgrade, headers=None): - self._writeFirstLine(101) - self._writeHeader("Connection", "Upgrade") - self._writeHeader("Upgrade", upgrade) - if isinstance(headers, dict): - for header in headers: - self._writeHeader(header, headers[header]) - self._writeServerHeader() - self._writeEndHeader() - - # ------------------------------------------------------------------------ - def WriteResponse(self, code, headers, contentType, contentCharset, content): try: contentLength = len(content) if content else 0 @@ -542,175 +273,47 @@ class MicroWebSrv: except: return False - # ------------------------------------------------------------------------ - def WriteResponseOk(self, headers=None, contentType=None, contentCharset=None, content=None): return self.WriteResponse(200, headers, contentType, contentCharset, content) - # ------------------------------------------------------------------------ - - def WriteResponseJSONOk(self, obj=None, headers=None): - return self.WriteResponse(200, headers, "application/json", "UTF-8", dumps(obj)) - - # ------------------------------------------------------------------------ - def WriteResponseRedirect(self, location): headers = {"Location": location} return self.WriteResponse(302, headers, None, None, None) - # ------------------------------------------------------------------------ - def WriteResponseError(self, code): responseCode = self._responseCodes.get(code, ('Unknown reason', '')) return self.WriteResponse(code, None, "text/html", "UTF-8", - self._errCtnTmpl % { - 'code': code, - 'reason': responseCode[0], - 'message': responseCode[1] - }) - - # ------------------------------------------------------------------------ - - def WriteResponseJSONError(self, code, obj=None): - return self.WriteResponse(code, - None, - "application/json", - "UTF-8", - dumps(obj if obj else {})) - - # ------------------------------------------------------------------------ + '{"code":"%s","reason":"%s","message":"%s"}' % ( + code, responseCode[0], responseCode[1])) def WriteResponseBadRequest(self): return self.WriteResponseError(400) - # ------------------------------------------------------------------------ - def WriteResponseForbidden(self): return self.WriteResponseError(403) - # ------------------------------------------------------------------------ - def WriteResponseNotFound(self): - if self._client._microWebSrv._notFoundUrl: - self.WriteResponseRedirect(self._client._microWebSrv._notFoundUrl) - else: - return self.WriteResponseError(404) - - # ------------------------------------------------------------------------ - - def WriteResponseMethodNotAllowed(self): - return self.WriteResponseError(405) - - # ------------------------------------------------------------------------ + return self.WriteResponseError(404) def WriteResponseInternalServerError(self): return self.WriteResponseError(500) - # ------------------------------------------------------------------------ - - def WriteResponseNotImplemented(self): - return self.WriteResponseError(501) - - # ------------------------------------------------------------------------ - - _errCtnTmpl = """\ - - - Error - - -

%(code)d %(reason)s

- %(message)s - - - """ - - # ------------------------------------------------------------------------ - - _execErrCtnTmpl = """\ - - - Page execution error - - -

%(module)s page execution error

- %(message)s - - - """ - - # ------------------------------------------------------------------------ - _responseCodes = { 100: ('Continue', 'Request received, please continue'), 101: ('Switching Protocols', 'Switching to new protocol; obey Upgrade header'), - 200: ('OK', 'Request fulfilled, document follows'), 201: ('Created', 'Document created, URL follows'), 202: ('Accepted', 'Request accepted, processing continues off-line'), - 203: ('Non-Authoritative Information', 'Request fulfilled from cache'), 204: ('No Content', 'Request fulfilled, nothing follows'), - 205: ('Reset Content', 'Clear input form for further input.'), - 206: ('Partial Content', 'Partial content follows.'), - - 300: ('Multiple Choices', - 'Object has several resources -- see URI list'), 301: ('Moved Permanently', 'Object moved permanently -- see URI list'), 302: ('Found', 'Object moved temporarily -- see URI list'), - 303: ('See Other', 'Object moved -- see Method and URL list'), - 304: ('Not Modified', - 'Document has not changed since given time'), - 305: ('Use Proxy', - 'You must use proxy specified in Location to access this ' - 'resource.'), - 307: ('Temporary Redirect', - 'Object moved temporarily -- see URI list'), - - 400: ('Bad Request', - 'Bad request syntax or unsupported method'), - 401: ('Unauthorized', - 'No permission -- see authorization schemes'), - 402: ('Payment Required', - 'No payment -- see charging schemes'), - 403: ('Forbidden', - 'Request forbidden -- authorization will not help'), 404: ('Not Found', 'Nothing matches the given URI'), - 405: ('Method Not Allowed', - 'Specified method is invalid for this resource.'), - 406: ('Not Acceptable', 'URI not available in preferred format.'), - 407: ('Proxy Authentication Required', 'You must authenticate with ' - 'this proxy before proceeding.'), - 408: ('Request Timeout', 'Request timed out; try again later.'), - 409: ('Conflict', 'Request conflict.'), - 410: ('Gone', - 'URI no longer exists and has been permanently removed.'), - 411: ('Length Required', 'Client must specify Content-Length.'), - 412: ('Precondition Failed', 'Precondition in headers is false.'), - 413: ('Request Entity Too Large', 'Entity is too large.'), - 414: ('Request-URI Too Long', 'URI is too long.'), - 415: ('Unsupported Media Type', 'Entity body in unsupported format.'), - 416: ('Requested Range Not Satisfiable', - 'Cannot satisfy request range.'), - 417: ('Expectation Failed', - 'Expect condition could not be satisfied.'), - 500: ('Internal Server Error', 'Server got itself in trouble'), 501: ('Not Implemented', 'Server does not support this operation'), - 502: ('Bad Gateway', 'Invalid responses from another server/proxy.'), - 503: ('Service Unavailable', - 'The server cannot process the request due to a high load'), - 504: ('Gateway Timeout', - 'The gateway server did not receive a timely response'), - 505: ('HTTP Version Not Supported', 'Cannot fulfill request.'), } - - # ============================================================================ - # ============================================================================ - # ============================================================================ -