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.

This commit is contained in:
Maff 2018-05-31 23:43:31 +01:00
parent fd173c0f73
commit 7ed40e46a7
4 changed files with 93 additions and 540 deletions

View File

@ -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 import time
from ustruct import unpack, unpack_from from ustruct import unpack, unpack_from
from array import array from array import array
@ -51,7 +17,6 @@ BME280_REGISTER_CONTROL = 0xF4
class BME280: class BME280:
def __init__(self, def __init__(self,
mode=BME280_OSAMPLE_1, mode=BME280_OSAMPLE_1,
address=BME280_I2CADDR, address=BME280_I2CADDR,

13
boot.py
View File

@ -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 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 #make sure AP mode is off and station mode is on
if wlan(apif).active() == True: if wlan(apif).active() == True:
wlan(apif).active(False) wlan(apif).active(False)
@ -30,7 +25,7 @@ if wlan(staif).isconnected() != True:
break break
if found_net == False: if found_net == False:
print("couldn't connect to wifi, nets found: %s" % nets) 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 #exit
else: else:
#Loop until wifi is connected and passes DHCP, or until 30 seconds have elapsed. #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: while wlan(staif).ifconfig()[0] == '0.0.0.0' or wlan(staif).isconnected() == False:
if slept > 300: if slept > 300:
break break
time.sleep_ms(100) sleep_ms(100)
slept+=1 slept+=1
#import webrepl #import webrepl

38
main.py
View File

@ -6,58 +6,48 @@ hw = uPyConfig.esp8266(variant='d1-r2')
#init_sample.init_sample(hw) #init_sample.init_sample(hw)
# Main app # 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={ wshead={
'Server':'horny', 'Server':'horny',
} }
wsctype='application/json' wsctype='application/json'
wscharset='UTF-8' 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('/') @MicroWebSrv.route('/')
def get_root(wscl, wsres): def get_root(wscl, wsres):
wsres.WriteResponseOk( wsres.WriteResponseOk(
headers=wshead, headers=wshead,
contentType=wsctype, contentType=wsctype,
contentCharset=wscharset,
content='{"result":"error","message":"use /bme280, /lm75a or /sht21 for sensor readings"}' content='{"result":"error","message":"use /bme280, /lm75a or /sht21 for sensor readings"}'
) )
@MicroWebSrv.route('/bme280') @MicroWebSrv.route('/bme280')
def get_bme280(wscl, wsres): def get_bme280(wscl, wsres):
sensors['bme280'].update_sensor() bme280.update_sensor()
json = '{"temperature":"%0.2f","humidity":"%0.2f","pressure":"%0.2f"}' % (
sensors['bme280'].temperature, sensors['bme280'].humidity, sensors['bme280'].pressure)
wsres.WriteResponseOk( wsres.WriteResponseOk(
headers=wshead, headers=wshead,
contentType=wsctype, contentType=wsctype,
contentCharset=wscharset, content='{"temperature":"%0.2f","humidity":"%0.2f","pressure":"%0.2f"}' % (
content=None bme280.temperature, bme280.humidity, bme280.pressure)
) )
@MicroWebSrv.route('/lm75a') @MicroWebSrv.route('/lm75a')
def get_lm75a(wscl, wsres): def get_lm75a(wscl, wsres):
json = '{"temperature":"%0.1f"}' % sensors['lm75a'].read_tempC()
wsres.WriteResponseOk( wsres.WriteResponseOk(
headers=wshead, headers=wshead,
contentType=wsctype, contentType=wsctype,
contentCharset=wscharset, content='{"temperature":"%0.1f"}' % lm75a.read_tempC()
content=json
) )
@MicroWebSrv.route('/sht21') @MicroWebSrv.route('/sht21')
def sht21(wscl, wsres): def sht21(wscl, wsres):
json = '{"temperature":"%0.3f","humidity":"%0.3f"}' % (sensors['sht21'].read_tempC(), sensors['sht21'].read_hum())
wsres.WriteResponseOk( wsres.WriteResponseOk(
headers=wshead, headers=wshead,
contentType=wsctype, contentType=wsctype,
contentCharset=wscharset, content='{"temperature":"%0.3f","humidity":"%0.3f"}' % (sht21.read_tempC(), sht21.read_hum())
content=json
) )
ws.Start(threaded=False, stackSize=8192) ws = MicroWebSrv()
ws.Start()

View File

@ -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 socket
import gc from ure import compile
import re
class MicroWebSrvRoute: class MicroWebSrvRoute:
def __init__(self, route, method, func, routeArgNames, routeRegex): def __init__(self, route, method, func, routeArgNames, routeRegex):
@ -21,12 +9,7 @@ class MicroWebSrvRoute:
self.routeArgNames = routeArgNames self.routeArgNames = routeArgNames
self.routeRegex = routeRegex self.routeRegex = routeRegex
class MicroWebSrv: class MicroWebSrv:
# ============================================================================
# ===( Constants )============================================================
# ============================================================================
_html_escape_chars = { _html_escape_chars = {
"&": "&", "&": "&",
'"': """, '"': """,
@ -34,62 +17,29 @@ class MicroWebSrv:
">": ">", ">": ">",
"<": "&lt;" "<": "&lt;"
} }
_decoratedRouteHandlers = []
# ============================================================================
# ===( Class globals )=======================================================
# ============================================================================
_docoratedRouteHandlers = []
# ============================================================================
# ===( Utils )===============================================================
# ============================================================================
@classmethod @classmethod
def route(cls, url, method='GET'): def route(cls, url, method='GET'):
""" Adds a route handler function to the routing list """
def route_decorator(func): def route_decorator(func):
item = (url, method, func) item = (url, method, func)
cls._docoratedRouteHandlers.append(item) cls._decoratedRouteHandlers.append(item)
return func return func
return route_decorator return route_decorator
# ----------------------------------------------------------------------------
@staticmethod @staticmethod
def HTMLEscape(s): def HTMLEscape(s):
return ''.join(MicroWebSrv._html_escape_chars.get(c, c) for c in s) return ''.join(MicroWebSrv._html_escape_chars.get(c, c) for c in s)
# ----------------------------------------------------------------------------
@staticmethod @staticmethod
def _tryAllocByteArray(size): def _tryAllocByteArray(size):
for x in range(10): for x in range(10):
try: try:
gc.collect()
return bytearray(size) return bytearray(size)
except: except:
pass pass
return None 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 @staticmethod
def _unquote(s): def _unquote(s):
r = s.split('%') r = s.split('%')
@ -101,33 +51,22 @@ class MicroWebSrv:
r[i] = '%' + s r[i] = '%' + s
return ''.join(r) return ''.join(r)
# ----------------------------------------------------------------------------
@staticmethod @staticmethod
def _unquote_plus(s): def _unquote_plus(s):
return MicroWebSrv._unquote(s.replace('+', ' ')) return MicroWebSrv._unquote(s.replace('+', ' '))
# ============================================================================
# ===( Constructor )==========================================================
# ============================================================================
def __init__(self, def __init__(self,
routeHandlers=[], routeHandlers=[],
port=80, port=80,
bindIP='0.0.0.0'): bindIP='0.0.0.0'):
self._srvAddr = (bindIP, port) self._srvAddr = (bindIP, port)
self._notFoundUrl = None
self._started = False self._started = False
self.thID = None
self.isThreaded = False
self._state = "Stopped"
self._routeHandlers = [] self._routeHandlers = []
routeHandlers += self._docoratedRouteHandlers routeHandlers += self._decoratedRouteHandlers
for route, method, func in routeHandlers: for route, method, func in routeHandlers:
routeParts = route.split('/') routeParts = route.split('/')
# -> ['', 'users', '<uID>', 'addresses', '<addrID>', 'test', '<anotherID>']
routeArgNames = [] routeArgNames = []
routeRegex = '' routeRegex = ''
for s in routeParts: for s in routeParts:
@ -137,133 +76,59 @@ class MicroWebSrv:
elif s: elif s:
routeRegex += '/' + s routeRegex += '/' + s
routeRegex += '$' routeRegex += '$'
# -> '/users/(\w*)/addresses/(\w*)/test/(\w*)$' routeRegex = compile(routeRegex)
routeRegex = re.compile(routeRegex)
self._routeHandlers.append(MicroWebSrvRoute(route, method, func, routeArgNames, routeRegex)) self._routeHandlers.append(MicroWebSrvRoute(route, method, func, routeArgNames, routeRegex))
# ============================================================================
# ===( Server Process )=======================================================
# ============================================================================
def _serverProcess(self): def _serverProcess(self):
self._started = True self._started = True
self._state = "Running"
while True: while True:
try: try:
client, cliAddr = self._server.accepted() client, cliAddr = self._server.accepted()
if client == None: if client == None: continue
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
except Exception as e: except Exception as e:
if not self.isThreaded: print(e)
print(e)
break break
self._client(self, client, cliAddr) self._client(self, client, cliAddr)
self._started = False self._started = False
self._state = "Stopped"
self.thID = None
# ============================================================================ def Start(self):
# ===( Functions )============================================================ if self._started: return
# ============================================================================ self._server = socket.socket(socket.AF_INET,
socket.SOCK_STREAM,
def Start(self, threaded=True, stackSize=8192): socket.IPPROTO_TCP)
if not self._started: self._server.setsockopt(socket.SOL_SOCKET,
if not network.WLAN().wifiactive(): socket.SO_REUSEADDR,
print("WLAN not connected!") 1)
return self._server.bind(self._srvAddr)
gc.collect() self._server.listen(1)
self._server = socket.socket(socket.AF_INET, self._server.settimeout(0.5)
socket.SOCK_STREAM, self._serverProcess()
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 Stop(self): def Stop(self):
if self._started: if not self._started: return
self._server.close() 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
# ----------------------------------------------------------------------------
def GetRouteHandler(self, resUrl, method): def GetRouteHandler(self, resUrl, method):
if self._routeHandlers: if not self._routeHandlers:
# resUrl = resUrl.upper() return (None, None)
if resUrl.endswith('/'): if resUrl.endswith('/'):
resUrl = resUrl[:-1] resUrl = resUrl[:-1]
method = method.upper() method = method.upper()
for rh in self._routeHandlers: for rh in self._routeHandlers:
if rh.method == method: if rh.method == method:
m = rh.routeRegex.match(resUrl) m = rh.routeRegex.match(resUrl)
if m: # found matching route? if m and rh.routeArgNames:
if rh.routeArgNames: routeArgs = {}
routeArgs = {} for i, name in enumerate(rh.routeArgNames):
for i, name in enumerate(rh.routeArgNames): value = m.group(i + 1)
value = m.group(i + 1) try: value = int(value)
try: except: pass
value = int(value) routeArgs[name] = value
except: return (rh.func, routeArgs)
pass elif m: return (rh.func, None)
routeArgs[name] = value
return (rh.func, routeArgs)
else:
return (rh.func, None)
return (None, None) return (None, None)
# ============================================================================
# ===( Class Client )========================================================
# ============================================================================
class _client: class _client:
# ------------------------------------------------------------------------
def __init__(self, microWebSrv, socket, addr): def __init__(self, microWebSrv, socket, addr):
socket.settimeout(2) socket.settimeout(2)
self._microWebSrv = microWebSrv self._microWebSrv = microWebSrv
@ -281,63 +146,43 @@ class MicroWebSrv:
self._processRequest() self._processRequest()
# ------------------------------------------------------------------------
def _processRequest(self): def _processRequest(self):
try: try:
response = MicroWebSrv._response(self) response = MicroWebSrv._response(self)
if self._parseFirstLine(response): if self._parseFirstLine(response) and self._parseHeader(response):
if self._parseHeader(response): routeHandler, routeArgs = self._microWebSrv.GetRouteHandler(self._resPath, self._method)
upg = self._getConnUpgrade() if routeHandler and routeArgs is not None:
if not upg: routeHandler(self, response, routeArgs)
routeHandler, routeArgs = self._microWebSrv.GetRouteHandler(self._resPath, self._method) elif routeHandler:
if routeHandler: routeHandler(self, response)
if routeArgs is not None: else: response.WriteResponseNotFound()
routeHandler(self, response, routeArgs) except: response.WriteResponseInternalServerError()
else: try: self._socket.close()
routeHandler(self, response) except: pass
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
# ------------------------------------------------------------------------
def _parseFirstLine(self, response): def _parseFirstLine(self, response):
try: try:
elements = self._socket.readline().decode().strip().split() elements = self._socket.readline().decode().strip().split()
if len(elements) == 3: if len(elements) != 3: return False
self._method = elements[0].upper() self._method = elements[0].upper()
self._path = elements[1] self._path = elements[1]
self._httpVer = elements[2].upper() self._httpVer = elements[2].upper()
elements = self._path.split('?', 1) elements = self._path.split('?', 1)
if len(elements) > 0: if len(elements) < 1: return True
self._resPath = MicroWebSrv._unquote_plus(elements[0]) self._resPath = MicroWebSrv._unquote_plus(elements[0])
if len(elements) > 1: if len(elements) < 2: return True
self._queryString = elements[1] self._queryString = elements[1]
elements = self._queryString.split('&') elements = self._queryString.split('&')
for s in elements: for s in elements:
param = s.split('=', 1) param = s.split('=', 1)
if len(param) > 0: if len(param) > 0:
value = MicroWebSrv._unquote(param[1]) if len(param) > 1 else '' value = MicroWebSrv._unquote(param[1]) if len(param) > 1 else ''
self._queryParams[MicroWebSrv._unquote(param[0])] = value self._queryParams[MicroWebSrv._unquote(param[0])] = value
return True return True
except: except:
pass pass
return False return False
# ------------------------------------------------------------------------
def _parseHeader(self, response): def _parseHeader(self, response):
while True: while True:
elements = self._socket.readline().decode().strip().split(':', 1) elements = self._socket.readline().decode().strip().split(':', 1)
@ -351,75 +196,6 @@ class MicroWebSrv:
else: else:
return False 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): def ReadRequestContent(self, size=None):
self._socket.setblocking(False) self._socket.setblocking(False)
b = None b = None
@ -433,59 +209,34 @@ class MicroWebSrv:
self._socket.setblocking(True) self._socket.setblocking(True)
return b if b else b'' return b if b else b''
# ------------------------------------------------------------------------
def ReadRequestPostedFormData(self): def ReadRequestPostedFormData(self):
res = {} res = {}
data = self.ReadRequestContent() data = self.ReadRequestContent()
if len(data) > 0: if len(data) < 1: return res
elements = data.decode().split('&') elements = data.decode().split('&')
for s in elements: for s in elements:
param = s.split('=', 1) param = s.split('=', 1)
if len(param) > 0: if len(param) < 1: next
value = MicroWebSrv._unquote(param[1]) if len(param) > 1 else '' value = MicroWebSrv._unquote(param[1]) if len(param) > 1 else ''
res[MicroWebSrv._unquote(param[0])] = value res[MicroWebSrv._unquote(param[0])] = value
return res return res
# ------------------------------------------------------------------------
def ReadRequestContentAsJSON(self):
try:
return loads(self.ReadRequestContent())
except:
return None
# ============================================================================
# ===( Class Response )======================================================
# ============================================================================
class _response: class _response:
# ------------------------------------------------------------------------
def __init__(self, client): def __init__(self, client):
self._client = client self._client = client
# ------------------------------------------------------------------------
def _write(self, data): def _write(self, data):
if type(data) == str: if type(data) == str:
data = data.encode() data = data.encode()
return self._client._socket.write(data) return self._client._socket.write(data)
# ------------------------------------------------------------------------
def _writeFirstLine(self, code): def _writeFirstLine(self, code):
reason = self._responseCodes.get(code, ('Unknown reason',))[0] reason = self._responseCodes.get(code, ('Unknown reason',))[0]
self._write("HTTP/1.1 %s %s\r\n" % (code, reason)) self._write("HTTP/1.1 %s %s\r\n" % (code, reason))
# ------------------------------------------------------------------------
def _writeHeader(self, name, value): def _writeHeader(self, name, value):
self._write("%s: %s\r\n" % (name, value)) self._write("%s: %s\r\n" % (name, value))
# ------------------------------------------------------------------------
def _writeContentTypeHeader(self, contentType, charset=None): def _writeContentTypeHeader(self, contentType, charset=None):
if contentType: if contentType:
ct = contentType \ ct = contentType \
@ -494,18 +245,12 @@ class MicroWebSrv:
ct = "application/octet-stream" ct = "application/octet-stream"
self._writeHeader("Content-Type", ct) self._writeHeader("Content-Type", ct)
# ------------------------------------------------------------------------
def _writeServerHeader(self): def _writeServerHeader(self):
self._writeHeader("Server", "MicroWebSrv by JC`zic") self._writeHeader("Server", "MicroWebSrv lite")
# ------------------------------------------------------------------------
def _writeEndHeader(self): def _writeEndHeader(self):
self._write("\r\n") self._write("\r\n")
# ------------------------------------------------------------------------
def _writeBeforeContent(self, code, headers, contentType, contentCharset, contentLength): def _writeBeforeContent(self, code, headers, contentType, contentCharset, contentLength):
self._writeFirstLine(code) self._writeFirstLine(code)
if isinstance(headers, dict): if isinstance(headers, dict):
@ -518,20 +263,6 @@ class MicroWebSrv:
self._writeHeader("Connection", "close") self._writeHeader("Connection", "close")
self._writeEndHeader() 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): def WriteResponse(self, code, headers, contentType, contentCharset, content):
try: try:
contentLength = len(content) if content else 0 contentLength = len(content) if content else 0
@ -542,175 +273,47 @@ class MicroWebSrv:
except: except:
return False return False
# ------------------------------------------------------------------------
def WriteResponseOk(self, headers=None, contentType=None, contentCharset=None, content=None): def WriteResponseOk(self, headers=None, contentType=None, contentCharset=None, content=None):
return self.WriteResponse(200, headers, contentType, contentCharset, content) 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): def WriteResponseRedirect(self, location):
headers = {"Location": location} headers = {"Location": location}
return self.WriteResponse(302, headers, None, None, None) return self.WriteResponse(302, headers, None, None, None)
# ------------------------------------------------------------------------
def WriteResponseError(self, code): def WriteResponseError(self, code):
responseCode = self._responseCodes.get(code, ('Unknown reason', '')) responseCode = self._responseCodes.get(code, ('Unknown reason', ''))
return self.WriteResponse(code, return self.WriteResponse(code,
None, None,
"text/html", "text/html",
"UTF-8", "UTF-8",
self._errCtnTmpl % { '{"code":"%s","reason":"%s","message":"%s"}' % (
'code': code, code, responseCode[0], responseCode[1]))
'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 {}))
# ------------------------------------------------------------------------
def WriteResponseBadRequest(self): def WriteResponseBadRequest(self):
return self.WriteResponseError(400) return self.WriteResponseError(400)
# ------------------------------------------------------------------------
def WriteResponseForbidden(self): def WriteResponseForbidden(self):
return self.WriteResponseError(403) return self.WriteResponseError(403)
# ------------------------------------------------------------------------
def WriteResponseNotFound(self): def WriteResponseNotFound(self):
if self._client._microWebSrv._notFoundUrl: return self.WriteResponseError(404)
self.WriteResponseRedirect(self._client._microWebSrv._notFoundUrl)
else:
return self.WriteResponseError(404)
# ------------------------------------------------------------------------
def WriteResponseMethodNotAllowed(self):
return self.WriteResponseError(405)
# ------------------------------------------------------------------------
def WriteResponseInternalServerError(self): def WriteResponseInternalServerError(self):
return self.WriteResponseError(500) return self.WriteResponseError(500)
# ------------------------------------------------------------------------
def WriteResponseNotImplemented(self):
return self.WriteResponseError(501)
# ------------------------------------------------------------------------
_errCtnTmpl = """\
<html>
<head>
<title>Error</title>
</head>
<body>
<h1>%(code)d %(reason)s</h1>
%(message)s
</body>
</html>
"""
# ------------------------------------------------------------------------
_execErrCtnTmpl = """\
<html>
<head>
<title>Page execution error</title>
</head>
<body>
<h1>%(module)s page execution error</h1>
%(message)s
</body>
</html>
"""
# ------------------------------------------------------------------------
_responseCodes = { _responseCodes = {
100: ('Continue', 'Request received, please continue'), 100: ('Continue', 'Request received, please continue'),
101: ('Switching Protocols', 101: ('Switching Protocols',
'Switching to new protocol; obey Upgrade header'), 'Switching to new protocol; obey Upgrade header'),
200: ('OK', 'Request fulfilled, document follows'), 200: ('OK', 'Request fulfilled, document follows'),
201: ('Created', 'Document created, URL follows'), 201: ('Created', 'Document created, URL follows'),
202: ('Accepted', 202: ('Accepted',
'Request accepted, processing continues off-line'), 'Request accepted, processing continues off-line'),
203: ('Non-Authoritative Information', 'Request fulfilled from cache'),
204: ('No Content', 'Request fulfilled, nothing follows'), 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'), 301: ('Moved Permanently', 'Object moved permanently -- see URI list'),
302: ('Found', 'Object moved temporarily -- 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'), 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'), 500: ('Internal Server Error', 'Server got itself in trouble'),
501: ('Not Implemented', 501: ('Not Implemented',
'Server does not support this operation'), '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.'),
} }
# ============================================================================
# ============================================================================
# ============================================================================