diff --git a/README.md b/README.md
index aadf9c5..8162cf3 100644
--- a/README.md
+++ b/README.md
@@ -78,11 +78,6 @@ A (very) simple web server written in Lua for the ESP8266 running the NodeMCU fi
For example, if the client requests _http://2.2.2.2/foo.lua?color=red_ then the server will execute the function
in your Lua script _foo.lua_ and pass in _connection_ and _args_, where _args.color = "red"_.
- If you are going to be sending lots (as in over a KB) of data in your script, you should yield the thread/coroutine
- every now and then in order to avoid overflowing the send buffer in the microcontroller. Use:
-
- coroutine.yield()
-
Look at the included example scripts for more ideas.
### Example: Garage door opener
diff --git a/http/file_list.lua b/http/file_list.lua
index 9e92a23..6879900 100644
--- a/http/file_list.lua
+++ b/http/file_list.lua
@@ -2,7 +2,6 @@ return function (connection, req, args)
connection:send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nCache-Control: private, no-store\r\n\r\n")
connection:send('
Server File Listing')
connection:send('')
- coroutine.yield()
connection:send('Server File Listing
')
local remaining, used, total=file.fsinfo()
@@ -20,8 +19,6 @@ return function (connection, req, args)
if isHttpFile then
local url = string.match(name, ".*/(.*)")
connection:send(' ' .. url .. " (" .. size .. " bytes)\n")
- -- this list could be very long, so we'll yield in order to avoid overflowing the send buffer.
- coroutine.yield()
end
end
connection:send("\n")
diff --git a/http/node_info.lua b/http/node_info.lua
index 86e55eb..8ab0df9 100644
--- a/http/node_info.lua
+++ b/http/node_info.lua
@@ -4,14 +4,16 @@ local function sendHeader(connection)
end
local function sendAttr(connection, attr, val)
- connection:send("".. attr .. ": " .. val .. "
\n")
+ if val then
+ connection:send("".. attr .. ": " .. val .. "
\n")
+ end
end
return function (connection, req, args)
collectgarbage()
sendHeader(connection)
connection:send('A Lua script sampleNode info
')
- majorVer, minorVer, devVer, chipid, flashid, flashsize, flashmode, flashspeed = node.info();
+ local majorVer, minorVer, devVer, chipid, flashid, flashsize, flashmode, flashspeed = node.info();
sendAttr(connection, "NodeMCU version" , majorVer.."."..minorVer.."."..devVer)
sendAttr(connection, "chipid" , chipid)
sendAttr(connection, "flashid" , flashid)
diff --git a/httpserver-static.lua b/httpserver-static.lua
index 5a57bd5..d7cb86f 100644
--- a/httpserver-static.lua
+++ b/httpserver-static.lua
@@ -20,7 +20,6 @@ return function (connection, req, args)
if chunk == nil then
continue = false
else
- coroutine.yield()
connection:send(chunk)
bytesSent = bytesSent + #chunk
chunk = nil
diff --git a/httpserver.lua b/httpserver.lua
index 1f8f818..273eb16 100644
--- a/httpserver.lua
+++ b/httpserver.lua
@@ -13,9 +13,50 @@ return function (port)
-- We do it in a separate thread because we need to yield when sending lots
-- of data in order to avoid overflowing the mcu's buffer.
local connectionThread
-
+
local allowStatic = {GET=true, HEAD=true, POST=false, PUT=false, DELETE=false, TRACE=false, OPTIONS=false, CONNECT=false, PATCH=false}
+ local function startServing(fileServeFunction, connection, req, args)
+ local bufferedConnection = {}
+ connectionThread = coroutine.create(function(fileServeFunction, bconnection, req, args)
+ fileServeFunction(bconnection, req, args)
+ if not bconnection:flush() then
+ connection:close()
+ connectionThread = nil
+ end
+ end)
+ function bufferedConnection:flush()
+ if self.size > 0 then
+ connection:send(table.concat(self.data, ""))
+ self.data = {}
+ self.size = 0
+ return true
+ end
+ return false
+ end
+ function bufferedConnection:send(payload)
+ local l = payload:len()
+ if l + self.size > 1000 then
+ if self:flush() then
+ coroutine.yield()
+ end
+ end
+ if l > 800 then
+ connection:send(payload)
+ coroutine.yield()
+ else
+ table.insert(self.data, payload)
+ self.size = self.size + l
+ end
+ end
+ bufferedConnection.size = 0
+ bufferedConnection.data = {}
+ local status, err = coroutine.resume(connectionThread, fileServeFunction, bufferedConnection, req, args)
+ if not status then
+ print(err)
+ end
+ end
+
local function onRequest(connection, req)
collectgarbage()
local method = req.method
@@ -59,8 +100,7 @@ return function (port)
end
end
end
- connectionThread = coroutine.create(fileServeFunction)
- coroutine.resume(connectionThread, connection, req, uri.args)
+ startServing(fileServeFunction, connection, req, uri.args)
end
local function onReceive(connection, payload)
@@ -89,18 +129,20 @@ return function (port)
else
args = {code = 400, errorString = "Bad Request"}
end
- connectionThread = coroutine.create(fileServeFunction)
- coroutine.resume(connectionThread, connection, req, args)
+ startServing(fileServeFunction, connection, req, args)
end
end
local function onSent(connection, payload)
collectgarbage()
if connectionThread then
- local connectionThreadStatus = coroutine.status(connectionThread)
+ local connectionThreadStatus = coroutine.status(connectionThread)
if connectionThreadStatus == "suspended" then
-- Not finished sending file, resume.
- coroutine.resume(connectionThread)
+ local status, err = coroutine.resume(connectionThread)
+ if not status then
+ print(err)
+ end
elseif connectionThreadStatus == "dead" then
-- We're done sending file.
connection:close()