Refactoring - function for sending headers is now in its own file. All errors are sent using coroutine. Some other memory usage improvements
This commit is contained in:
parent
453f38b52f
commit
ead632d131
2
Makefile
2
Makefile
@ -11,7 +11,7 @@ SPEED=9600
|
||||
# End of user config
|
||||
######################################################################
|
||||
HTTP_FILES := $(wildcard http/*)
|
||||
LUA_FILES := init.lua httpserver.lua httpserver-request.lua httpserver-static.lua httpserver-error.lua
|
||||
LUA_FILES := init.lua httpserver.lua httpserver-request.lua httpserver-static.lua httpserver-header.lua httpserver-error.lua
|
||||
|
||||
# Print usage
|
||||
usage:
|
||||
|
||||
@ -2,20 +2,13 @@
|
||||
-- Part of nodemcu-httpserver, handles sending error pages to client.
|
||||
-- Author: Marcos Kirsch
|
||||
|
||||
local function getHTTPStatusString(code)
|
||||
if code == 404 then return "Not Found" end
|
||||
if code == 400 then return "Bad Request" end
|
||||
if code == 501 then return "Not Implemented" end
|
||||
return "Unknown HTTP status"
|
||||
end
|
||||
|
||||
local function sendHeader(connection, code, codeString, mimeType)
|
||||
connection:send("HTTP/1.0 " .. code .. " " .. codeString .. "\r\nServer: nodemcu-httpserver\r\nContent-Type: " .. mimeType .. "\r\nConnection: close\r\n\r\n")
|
||||
end
|
||||
|
||||
return function (connection, args)
|
||||
local errorString = getHTTPStatusString(args.code)
|
||||
print("Error " .. args.code .. ": " .. errorString)
|
||||
sendHeader(connection, args.code, errorString, "text/html")
|
||||
connection:send("<html><head><title>" .. args.code .. " - " .. errorString .. "</title></head><body><h1>" .. args.code .. " - " .. errorString .. "</h1></body></html>\r\n")
|
||||
|
||||
local function sendHeader(connection, code, errorString, mimeType)
|
||||
connection:send("HTTP/1.0 " .. code .. " " .. errorString .. "\r\nServer: nodemcu-httpserver\r\nContent-Type: " .. mimeType .. "\r\nConnection: close\r\n\r\n")
|
||||
end
|
||||
|
||||
print("Error " .. args.code .. ": " .. args.errorString)
|
||||
sendHeader(connection, args.code, args.errorString, "text/html")
|
||||
connection:send("<html><head><title>" .. args.code .. " - " .. args.errorString .. "</title></head><body><h1>" .. args.code .. " - " .. args.errorString .. "</h1></body></html>\r\n")
|
||||
end
|
||||
|
||||
@ -2,41 +2,20 @@
|
||||
-- Part of nodemcu-httpserver, handles sending static files to client.
|
||||
-- Author: Marcos Kirsch
|
||||
|
||||
local function getMimeType(ext)
|
||||
local gzip = false
|
||||
-- A few MIME types. Keep list short. If you need something that is missing, let's add it.
|
||||
local mt = {css = "text/css", gif = "image/gif", html = "text/html", ico = "image/x-icon", jpeg = "image/jpeg", jpg = "image/jpeg", js = "application/javascript", json = "application/json", png = "image/png"}
|
||||
-- add comressed flag if file ends with gz
|
||||
if ext:find("%.gz$") then
|
||||
ext = ext:sub(1, -4)
|
||||
gzip = true
|
||||
end
|
||||
if mt[ext] then contentType = mt[ext] else contentType = "text/plain" end
|
||||
return {contentType = contentType, gzip = gzip }
|
||||
|
||||
end
|
||||
|
||||
local function sendHeader(connection, code, codeString, mimeType)
|
||||
connection:send("HTTP/1.0 " .. code .. " " .. codeString .. "\r\nServer: nodemcu-httpserver\r\nContent-Type: " .. mimeType["contentType"] .. "\r\n")
|
||||
if mimeType["gzip"] then
|
||||
connection:send("Content-Encoding: gzip\r\n")
|
||||
end
|
||||
connection:send("Connection: close\r\n\r\n")
|
||||
end
|
||||
|
||||
return function (connection, args)
|
||||
sendHeader(connection, 200, "OK", getMimeType(args.ext))
|
||||
dofile("httpserver-header.lc")(connection, 200, args.ext)
|
||||
--print("Begin sending:", args.file)
|
||||
-- Send file in little chunks
|
||||
local continue = true
|
||||
local bytesSent = 0
|
||||
while continue do
|
||||
collectgarbage()
|
||||
-- NodeMCU file API lets you open 1 file at a time.
|
||||
-- So we need to open, seek, close each time in order
|
||||
-- to support multiple simultaneous clients.
|
||||
file.open(args.file)
|
||||
file.seek("set", bytesSent)
|
||||
local chunk = file.read(512)
|
||||
local chunk = file.read(256)
|
||||
file.close()
|
||||
if chunk == nil then
|
||||
continue = false
|
||||
@ -44,6 +23,7 @@ return function (connection, args)
|
||||
coroutine.yield()
|
||||
connection:send(chunk)
|
||||
bytesSent = bytesSent + #chunk
|
||||
chunk = nil
|
||||
--print("Sent" .. args.file, bytesSent)
|
||||
end
|
||||
end
|
||||
|
||||
@ -15,32 +15,31 @@ return function (port)
|
||||
local connectionThread
|
||||
|
||||
local function onGet(connection, uri)
|
||||
collectgarbage()
|
||||
local fileServeFunction = nil
|
||||
if #(uri.file) > 32 then
|
||||
-- nodemcu-firmware cannot handle long filenames.
|
||||
uri.args['code'] = 400
|
||||
uri.args = {code = 400, errorString = "Bad Request"}
|
||||
fileServeFunction = dofile("httpserver-error.lc")
|
||||
else
|
||||
local fileExists = file.open(uri.file, "r")
|
||||
file.close()
|
||||
collectgarbage()
|
||||
if not fileExists then
|
||||
uri.args['code'] = 404
|
||||
uri.args = {code = 404, errorString = "Not Found"}
|
||||
fileServeFunction = dofile("httpserver-error.lc")
|
||||
elseif uri.isScript then
|
||||
fileServeFunction = dofile(uri.file)
|
||||
else
|
||||
uri.args['file'] = uri.file
|
||||
uri.args['ext'] = uri.ext
|
||||
uri.args = {file = uri.file, ext = uri.ext}
|
||||
fileServeFunction = dofile("httpserver-static.lc")
|
||||
end
|
||||
end
|
||||
connectionThread = coroutine.create(fileServeFunction)
|
||||
--print("Thread created", connectionThread)
|
||||
coroutine.resume(connectionThread, connection, uri.args)
|
||||
end
|
||||
|
||||
local function onReceive(connection, payload)
|
||||
collectgarbage()
|
||||
-- print(payload) -- for debugging
|
||||
-- parse payload and decide what to serve.
|
||||
local req = dofile("httpserver-request.lc")(payload)
|
||||
@ -49,25 +48,31 @@ return function (port)
|
||||
onGet(connection, req.uri)
|
||||
else
|
||||
local args = {}
|
||||
if req.methodIsValid then args['code'] = 501 else args['code'] = 400 end
|
||||
dofile("httpserver-error.lc")(connection, args)
|
||||
local fileServeFunction = dofile("httpserver-error.lc")
|
||||
if req.methodIsValid then
|
||||
args = {code = 501, errorString = "Not Implemented"}
|
||||
else
|
||||
args = {code = 400, errorString = "Bad Request"}
|
||||
end
|
||||
connectionThread = coroutine.create(fileServeFunction)
|
||||
coroutine.resume(connectionThread, connection, args)
|
||||
end
|
||||
end
|
||||
|
||||
local function onSent(connection, payload)
|
||||
collectgarbage()
|
||||
if connectionThread then
|
||||
local connectionThreadStatus = coroutine.status(connectionThread)
|
||||
-- print (connectionThread, "status is", connectionThreadStatus)
|
||||
if connectionThreadStatus == "suspended" then
|
||||
-- Not finished sending file, resume.
|
||||
-- print("Resume thread", connectionThread)
|
||||
coroutine.resume(connectionThread)
|
||||
elseif connectionThreadStatus == "dead" then
|
||||
-- We're done sending file.
|
||||
-- print("Done thread", connectionThread)
|
||||
connection:close()
|
||||
connectionThread = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
connection:on("receive", onReceive)
|
||||
connection:on("sent", onSent)
|
||||
|
||||
2
init.lua
2
init.lua
@ -43,7 +43,7 @@ local compileAndRemoveIfNeeded = function(f)
|
||||
end
|
||||
end
|
||||
|
||||
local serverFiles = {'httpserver.lua', 'httpserver-request.lua', 'httpserver-static.lua', 'httpserver-error.lua'}
|
||||
local serverFiles = {'httpserver.lua', 'httpserver-request.lua', 'httpserver-static.lua', 'httpserver-header.lua', 'httpserver-error.lua'}
|
||||
for i, f in ipairs(serverFiles) do compileAndRemoveIfNeeded(f) end
|
||||
|
||||
compileAndRemoveIfNeeded = nil
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user