diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..85e7c1d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/.idea/
diff --git a/ESP8266WebServer.py b/ESP8266WebServer.py
index 24edf5a..4c61097 100644
--- a/ESP8266WebServer.py
+++ b/ESP8266WebServer.py
@@ -22,8 +22,17 @@
docPath = "/"
# Data for template
tplData = {}
+# Max. POST/PUT-Data size
+maxContentLength = 1024
-def begin(port):
+# MIME types
+mimeTypes = {
+ ".css":"text/css",
+ ".jpg":"image/jpg",
+ ".png":"image/png",
+}
+
+def begin(port=80):
"""Function to start http server
"""
global server, poller
@@ -47,6 +56,7 @@ def handleClient():
res = poller.poll(1)
if res: # There's a new client connection
(socket, sockaddr) = server.accept()
+ socket.settimeout(0.02) # set timeout for readline to avoid blocking
handle(socket)
socket.close()
@@ -107,11 +117,53 @@ def __fileExist(path):
print("Not Found.")
return False
+def __serveFile(socket, path):
+ """Serves a file from the filesystem
+ """
+ filePath = path
+ fileFound = True
+ # find the file
+ if not __fileExist(filePath):
+ if not path.endswith("/"):
+ fileFound = False
+ else:
+ filePath = path + "index.html"
+ # find index.html in the path
+ if not __fileExist(filePath):
+ filePath = path + "index.p.html"
+ # find index.p.html in the path
+ if not __fileExist(filePath): # no default html file found
+ fileFound = False
+ if not fileFound: # file or default html file specified in path not found
+ if notFoundHandler:
+ notFoundHandler(socket)
+ else:
+ err(socket, "404", "Not Found")
+ return
+ # Responds the header first
+ socket.write("HTTP/1.1 200 OK\r\n")
+ contentType = "text/html"
+ for ext in mimeTypes:
+ if filePath.endswith(ext):
+ contentType = mimeTypes[ext]
+ socket.write("Content-Type: " + contentType + "\r\n\r\n")
+ # Responds the file content
+ if filePath.endswith(".p.html"):
+ f = open(filePath, "r")
+ for l in f:
+ socket.write(l.format(**tplData))
+ f.close()
+ else:
+ __sendPage(socket, filePath)
+
def handle(socket):
"""Processing new GET request
"""
global docPath, handlers
- currLine = str(socket.readline(), 'utf-8')
+ try: # capture timeout for wainting a line
+ currLine = str(socket.readline(), 'utf-8')
+ except:
+ currLine = "" # readline timeout (not a complete line)
request = currLine.split(" ")
if len(request) != 3: # Discarded if it's a bad header
return
@@ -121,62 +173,53 @@ def handle(socket):
else:
(path, query) = (url, "")
args = {}
+ contentType = ""
+ content = b""
+ contentLength = 0
+
if query: # Parsing the querying string
argPairs = query.split("&")
for argPair in argPairs:
arg = argPair.split("=")
args[arg[0]] = arg[1]
+
while True: # Read until blank line after header
header = socket.readline()
- if header == b"":
+ if header.startswith(b"Content-Length"):
+ (key, contentLengthStr) = str(header).split(" ")
+ contentLength = int(contentLengthStr[0:-5])
+ if (contentLength > maxContentLength):
+ err(socket, "400", "Bad Request")
+ return
+ if (header.startswith(b"Content-Type")):
+ (key, contentType) = str(header).split(" ")
+ contentType = contentType[0:-5]
+ if (header == b""):
return
- if header == b"\r\n":
+ if (header == b"\r\n" and contentLength > 0):
+ while(len(content) < contentLength):
+ content = content + socket.recv(contentLength)
+ if (len(content) > maxContentLength):
+ err(socket, "400", "Bad Request")
+ return
break
-
+ elif header == b"\r\n":
+ break
+
# Check for supported HTTP version
if version != "HTTP/1.0\r\n" and version != "HTTP/1.1\r\n":
err(socket, "505", "Version Not Supported")
- elif method != "GET": # Only accept GET request
+ elif (method != "GET" and method != "PUT" and method != "POST"): # Only accept GET,PUT and POST request
err(socket, "501", "Not Implemented")
elif path in handlers: # Check for registered path
- handlers[path](socket, args)
- #elif not path.startswith(docPath): # Check for path to any document
- # err(socket, "400", "Bad Request")
- else:
+ handlers[path](socket, args, method, contentType, content)
+ elif not path.startswith(docPath): # Check for wrong path
+ err(socket, "400", "Bad Request")
+ else: # find file in the document path
filePath = path
- # find the file
- if not __fileExist(filePath):
- filePath = path + ("index.html" if path.endswith("/") else "/index.html")
- # find index.html in the path
- if not __fileExist(filePath):
- filePath = path + ("index.p.html" if path.endswith("/") else "/index.p.html")
- # find index.p.html in the path
- if not __fileExist(filePath):
- if notFoundHandler:
- notFoundHandler(socket)
- else:
- err(socket, "404", "Not Found")
- return
- socket.write("HTTP/1.1 302 Found\r\n")
- socket.write("Location: " + filePath + "\r\n\r\n")
- return
-
- # Responds the header first
- socket.write("HTTP/1.1 200 OK\r\n")
- socket.write("Content-Type: text/html\r\n\r\n")
-# if filePath.endswith(".css"):
-# socket.write("Content-Type: text/css\r\n\r\n")
-# else:
-# socket.write("Content-Type: text/html\r\n\r\n")
- # Responds the file content
- if filePath.endswith(".p.html"):
- print("template file.")
- f = open(filePath, "r")
- for l in f:
- socket.write(l.format(**tplData))
- f.close()
- else:
- __sendPage(socket, filePath)
+ print("Serve File " + filePath)
+ __serveFile(socket, filePath)
+
def onPath(path, handler):
"""Register handler for processing request of specified path
@@ -201,3 +244,9 @@ def setTplData(data):
"""
global tplData
tplData = data
+
+def setMaxContentLength(max):
+ """Set the maximum content lenpth for incomming data bodies
+ """
+ global maxContentLength
+ maxContentLength = max
diff --git a/README.md b/README.md
index 5420389..47d2937 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,9 @@
+This Library is no longer supported. Visit https://github.com/codemee/ESPWebServer for a version that supports ESP8266 and ESP32.
+
+----
# ESP8266WebServer
-This is a very lightweight web server for MicroPython on ESP8266.It only accept GET requests.It adopts the programming style of ESP8266WebServer library in ESP8266 Arduino Core.This make it suitable for serving REST API.The original code was inspired from the project [Controlling a GPIO through an ESP8266-based web server](https://lab.whitequark.org/notes/2016-10-20/controlling-a-gpio-through-an-esp8266-based-web-server/).
+This is a very lightweight web server for MicroPython on ESP8266. It only accept GET, POST and PUT requests. It adopts the programming style of ESP8266WebServer library in ESP8266 Arduino Core.This make it suitable for serving REST API.The original code was inspired from the project [Controlling a GPIO through an ESP8266-based web server](https://lab.whitequark.org/notes/2016-10-20/controlling-a-gpio-through-an-esp8266-based-web-server/).
## Installation
@@ -46,6 +49,10 @@ Specified the directory in the filesystem containing all the HTML files.
Specified the dictionary for template file. `dic` sould be a dictionary with all keys are string and contains all the names in replacing fields in all the template files.
+### setMaxContentLength(size)
+
+Defines the maximum Content Length of incoming request bodies (POST, PUT) in bytes. Default: 1024
+
### handleClient()
Check for new request and call corresponding handler to process it.
@@ -54,8 +61,10 @@ Check for new request and call corresponding handler to process it.
You can upload www directory and index.p.html to "/" on ESP8266 board and run TestWebServer.py to see how it works.
-TestWebServer.py will show its own IP address through serial monitor.Just open your browser and connect it to http://serverIP:8899 or http://serverIP:8899/index.p.html, you'll get the main page that can turn on/off the buildin led on ESP8266 board. The main also demonstrate the template file usage.
+`main.py` contains an example for handling Request Body content.
+
+TestWebServer.py will show its own IP address through serial monitor.Just open your browser and connect it to http://serverIP:8899 or http://serverIP:8899/index.p.html, you'll get the main page that can turn on/off the buildin led on ESP8266 board. The main page also demonstrate the template file usage.
-You can also open http://serverip:8899/www/index.html or http://serverip:8899/www to view alternative version of controlling page that use AJAX to asynchronously turn on/off led.
+You can also open http://serverip:8899/www/index.html or http://serverip:8899/www/ to view alternative version of controlling page that use AJAX to asynchronously turn on/off led.
You can use http://serverip:8899/switch to switch led on/off led directly. Or you can use http://serverip:8899/cmd?led=on to turn the led on and http://serverip:8899/cmd?led=off to turn the led off.
diff --git a/TestWebServer.py b/TestWebServer.py
index f4e83a2..72a3779 100644
--- a/TestWebServer.py
+++ b/TestWebServer.py
@@ -66,7 +66,8 @@ def handleSwitch(socket, args):
updateInfo(socket)
# Start the server @ port 8899
-ESP8266WebServer.begin(8899)
+# ESP8266WebServer.begin(8899)
+ESP8266WebServer.begin() # use default 80 port
# Register handler for each path
# ESP8266WebServer.onPath("/", handleRoot)
diff --git a/index.p.html b/index.p.html
index 65c5ea8..ae8ee42 100644
--- a/index.p.html
+++ b/index.p.html
@@ -7,5 +7,15 @@
{title} Status:{status}
Turn {switch}
HOME
+
+