From 73fbf929865193c3cb860a44c3f262fe3867ec23 Mon Sep 17 00:00:00 2001 From: ffedoroff Date: Wed, 2 Nov 2016 16:37:41 +0600 Subject: [PATCH 01/17] line shorter line is too long and luatool.py raize exception when uploading that file --- httpserver-header.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/httpserver-header.lua b/httpserver-header.lua index d218722..d3ea3fa 100644 --- a/httpserver-header.lua +++ b/httpserver-header.lua @@ -13,7 +13,8 @@ return function (connection, code, extension, isGzipped) local function getMimeType(ext) -- 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", xml = "text/xml"} + 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", xml = "text/xml"} if mt[ext] then return mt[ext] else return "text/plain" end end From ea74a6de7d6a6497446d35e674bd4d0354b8d713 Mon Sep 17 00:00:00 2001 From: Christian Fischer Date: Fri, 9 Dec 2016 17:54:31 +0100 Subject: [PATCH 02/17] modularize nodemcu-command, add start_baud parameter --- Makefile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 3b07436..2b1b523 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,8 @@ NODEMCU-UPLOADER=../nodemcu-uploader/nodemcu-uploader.py PORT=/dev/cu.SLAB_USBtoUART SPEED=9600 +NODEMCU-COMMAND=$(NODEMCU-UPLOADER) -b $(SPEED) --start_baud $(SPEED) -p $(PORT) upload + ###################################################################### # End of user config ###################################################################### @@ -33,17 +35,17 @@ usage: # Upload one files only upload: - @python $(NODEMCU-UPLOADER) -b $(SPEED) -p $(PORT) upload $(FILE) + @python $(NODEMCU-COMMAND) $(FILE) # Upload HTTP files only upload_http: $(HTTP_FILES) - @python $(NODEMCU-UPLOADER) -b $(SPEED) -p $(PORT) upload $(foreach f, $^, $(f)) + @python $(NODEMCU-COMMAND) $(foreach f, $^, $(f)) # Upload httpserver lua files (init and server module) upload_server: $(LUA_FILES) - @python $(NODEMCU-UPLOADER) -b $(SPEED) -p $(PORT) upload $(foreach f, $^, $(f)) + @python $(NODEMCU-COMMAND) $(foreach f, $^, $(f)) # Upload all upload_all: $(LUA_FILES) $(HTTP_FILES) - @python $(NODEMCU-UPLOADER) -b $(SPEED) -p $(PORT) upload $(foreach f, $^, $(f)) + @python $(NODEMCU-COMMAND) $(foreach f, $^, $(f)) From 1cc0d120f0d987ff18a45f0ee437522972acfb51 Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Sat, 17 Dec 2016 21:12:25 -0600 Subject: [PATCH 03/17] Add private to Cache-Control --- httpserver-header.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpserver-header.lua b/httpserver-header.lua index d218722..ff85bae 100644 --- a/httpserver-header.lua +++ b/httpserver-header.lua @@ -21,7 +21,7 @@ return function (connection, code, extension, isGzipped) connection:send("HTTP/1.0 " .. code .. " " .. getHTTPStatusString(code) .. "\r\nServer: nodemcu-httpserver\r\nContent-Type: " .. mimeType .. "\r\nnCache-Control: private, no-store\r\n") if isGzipped then - connection:send("Cache-Control: max-age=2592000\r\nContent-Encoding: gzip\r\n") + connection:send("Cache-Control: private, max-age=2592000\r\nContent-Encoding: gzip\r\n") end connection:send("Connection: close\r\n\r\n") From 8b46df0f750e0022d2db19b39aa34641c614a6c7 Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Mon, 26 Dec 2016 13:41:06 -0600 Subject: [PATCH 04/17] Chage baud rate to 115200 which seems to be the defualt for newer nodemcu-firmware builds/ --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3b07436..3536d60 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ NODEMCU-UPLOADER=../nodemcu-uploader/nodemcu-uploader.py # Serial port PORT=/dev/cu.SLAB_USBtoUART -SPEED=9600 +SPEED=115200 ###################################################################### # End of user config From f060295ef7789093c07738fbe472a0472fbd5ddc Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Mon, 26 Dec 2016 13:44:41 -0600 Subject: [PATCH 05/17] Remove print about server running from server code itself. Client can choose to do the prints from init.lua if client wants to, This seems more appropritate. --- httpserver.lua | 5 ----- 1 file changed, 5 deletions(-) diff --git a/httpserver.lua b/httpserver.lua index 29ac0a2..5b29773 100644 --- a/httpserver.lua +++ b/httpserver.lua @@ -155,11 +155,6 @@ return function (port) end ) - -- false and nil evaluate as false - local ip = wifi.sta.getip() - if not ip then ip = wifi.ap.getip() end - if not ip then ip = "unknown IP" end - print("nodemcu-httpserver running at http://" .. ip .. ":" .. port) return s end From badbf6e2b9c2f3285a0c5e1a7a2e6808a7ecc623 Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Mon, 26 Dec 2016 13:47:22 -0600 Subject: [PATCH 06/17] This is really annoying... normalize line endings to Unix (LF). Please use Unix line endings so things diff right with git. --- httpserver-connection.lua | 126 ++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 67 deletions(-) diff --git a/httpserver-connection.lua b/httpserver-connection.lua index 329e603..75d7c75 100644 --- a/httpserver-connection.lua +++ b/httpserver-connection.lua @@ -1,67 +1,59 @@ --- httpserver-connection --- Part of nodemcu-httpserver, provides a buffered connection object that can handle multiple --- consecutive send() calls, and buffers small payloads to send once they get big. --- For this to work, it must be used from a coroutine and owner is responsible for the final --- flush() and for closing the connection. --- Author: Philip Gladstone, Marcos Kirsch - -BufferedConnection = {} - --- parameter is the nodemcu-firmware connection -function BufferedConnection:new(connection) - local newInstance = {} - newInstance.connection = connection - newInstance.size = 0 - newInstance.data = {} - - function newInstance:flush() - if self.size > 0 then - self.connection:send(table.concat(self.data, "")) - self.data = {} - self.size = 0 - return true - end - return false - end - - function newInstance:send(payload) - local flushthreshold = 1400 - - local newsize = self.size + payload:len() - while newsize > flushthreshold do - --STEP1: cut out piece from payload to complete threshold bytes in table - local piecesize = flushthreshold - self.size - local piece = payload:sub(1, piecesize) - payload = payload:sub(piecesize + 1, -1) - --STEP2: insert piece into table - table.insert(self.data, piece) - self.size = self.size + piecesize --size should be same as flushthreshold - --STEP3: flush entire table - if self:flush() then - coroutine.yield() - end - --at this point, size should be 0, because the table was just flushed - newsize = self.size + payload:len() - end - - --at this point, whatever is left in payload should be <= flushthreshold - local plen = payload:len() - if plen == flushthreshold then - --case 1: what is left in payload is exactly flushthreshold bytes (boundary case), so flush it - table.insert(self.data, payload) - self.size = self.size + plen - if self:flush() then - coroutine.yield() - end - elseif payload:len() then - --case 2: what is left in payload is less than flushthreshold, so just leave it in the table - table.insert(self.data, payload) - self.size = self.size + plen - --else, case 3: nothing left in payload, so do nothing - end - end - - return newInstance -end - -return BufferedConnection +-- httpserver-connection +-- Part of nodemcu-httpserver, provides a buffered connection object that can handle multiple +-- consecutive send() calls, and buffers small payloads to send once they get big. +-- For this to work, it must be used from a coroutine and owner is responsible for the final +-- flush() and for closing the connection. +-- Author: Philip Gladstone, Marcos Kirsch + +BufferedConnection = {} + +-- parameter is the nodemcu-firmware connection +function BufferedConnection:new(connection) + local newInstance = {} + newInstance.connection = connection + newInstance.size = 0 + newInstance.data = {} + + -- Returns true if there was any data to be sent. + function newInstance:flush() + if self.size > 0 then + self.connection:send(table.concat(self.data, "")) + self.data = {} + self.size = 0 + return true + end + return false + end + + function newInstance:send(payload) + local flushThreshold = 1400 + local newSize = self.size + payload:len() + while newSize >= flushThreshold do + --STEP1: cut out piece from payload to complete threshold bytes in table + local pieceSize = flushThreshold - self.size + local piece = payload:sub(1, pieceSize) + payload = payload:sub(pieceSize + 1, -1) + --STEP2: insert piece into table + table.insert(self.data, piece) + piece = nil + self.size = self.size + pieceSize --size should be same as flushThreshold + --STEP3: flush entire table + if self:flush() then + coroutine.yield() + end + --at this point, size should be 0, because the table was just flushed + newSize = self.size + payload:len() + end + + --at this point, whatever is left in payload should be < flushThreshold + if payload:len() ~= 0 then + --leave remaining data in the table + table.insert(self.data, payload) + self.size = self.size + payload:len() + end + end + return newInstance + +end + +return BufferedConnection From 856ef7a590d061d55e96dc6c0df4f115c01577df Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Mon, 26 Dec 2016 13:48:54 -0600 Subject: [PATCH 07/17] There was a typo (entra n) when sending 'Cache-Control: private, no-store' in the header. I removed the whole thing because why not let browser cache? --- httpserver-header.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpserver-header.lua b/httpserver-header.lua index ff85bae..3e6fabc 100644 --- a/httpserver-header.lua +++ b/httpserver-header.lua @@ -19,7 +19,7 @@ return function (connection, code, extension, isGzipped) local mimeType = getMimeType(extension) - connection:send("HTTP/1.0 " .. code .. " " .. getHTTPStatusString(code) .. "\r\nServer: nodemcu-httpserver\r\nContent-Type: " .. mimeType .. "\r\nnCache-Control: private, no-store\r\n") + connection:send("HTTP/1.0 " .. code .. " " .. getHTTPStatusString(code) .. "\r\nServer: nodemcu-httpserver\r\nContent-Type: " .. mimeType .. "\r\n") if isGzipped then connection:send("Cache-Control: private, max-age=2592000\r\nContent-Encoding: gzip\r\n") end From 2167d7290f2f3018c5ac170c2dda52f29fa0b3bb Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Mon, 26 Dec 2016 13:51:40 -0600 Subject: [PATCH 08/17] Changed wifi config to STATION, which I think would be most common. Reworked starting the server until after IP address is acquired. Added mdns conditonal mdns registration (thank you firmware people\!) --- init.lua | 72 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/init.lua b/init.lua index fe654a8..d7c5d76 100644 --- a/init.lua +++ b/init.lua @@ -5,7 +5,7 @@ local wifiConfig = {} -- wifi.STATION -- station: join a WiFi network -- wifi.SOFTAP -- access point: create a WiFi network -- wifi.wifi.STATIONAP -- both station and access point -wifiConfig.mode = wifi.STATIONAP -- both station and access point +wifiConfig.mode = wifi.STATION wifiConfig.accessPointConfig = {} wifiConfig.accessPointConfig.ssid = "ESP-"..node.chipid() -- Name of the SSID you want to create @@ -23,7 +23,7 @@ wifiConfig.stationPointConfig.pwd = "" -- Password for the WiFi -- Tell the chip to connect to the access point wifi.setmode(wifiConfig.mode) -print('set (mode='..wifi.getmode()..')') +--print('set (mode='..wifi.getmode()..')') if (wifiConfig.mode == wifi.SOFTAP) or (wifiConfig.mode == wifi.STATIONAP) then print('AP MAC: ',wifi.ap.getmac()) @@ -44,7 +44,7 @@ collectgarbage() -- End WiFi configuration -- Compile server code and remove original .lua files. --- This only happens the first time afer the .lua files are uploaded. +-- This only happens the first time after server .lua files are uploaded. local compileAndRemoveIfNeeded = function(f) if file.open(f) then @@ -74,32 +74,48 @@ serverFiles = nil collectgarbage() -- Connect to the WiFi access point. --- Once the device is connected, you may start the HTTP server. +-- Once the device is connected, start the HTTP server. + +startServer = function(ip, hostname) + local serverPort = 80 + if (dofile("httpserver.lc")(serverPort)) then + print("nodemcu-httpserver running at:") + print(" http://" .. ip .. ":" .. serverPort) + if (mdns) then + mdns.register(hostname, { description="A tiny server", service="http", port=serverPort, location='Earth' }) + print (' http://' .. hostname .. '.local.:' .. serverPort) + end + end +end if (wifi.getmode() == wifi.STATION) or (wifi.getmode() == wifi.STATIONAP) then - local joinCounter = 0 - local joinMaxAttempts = 5 - tmr.alarm(0, 3000, 1, function() - local ip = wifi.sta.getip() - if ip == nil and joinCounter < joinMaxAttempts then - print('Connecting to WiFi Access Point ...') - joinCounter = joinCounter +1 - else - if joinCounter == joinMaxAttempts then - print('Failed to connect to WiFi Access Point.') - else - print('IP: ',ip) - end - tmr.stop(0) - joinCounter = nil - joinMaxAttempts = nil - collectgarbage() - end - end) -end - --- Uncomment to automatically start the server in port 80 -if (not not wifi.sta.getip()) or (not not wifi.ap.getip()) then - --dofile("httpserver.lc")(80) + local joinCounter = 0 + local joinMaxAttempts = 5 + tmr.alarm(0, 3000, 1, function() + local ip = wifi.sta.getip() + if (not ip) then ip = wifi.ap.getip() end + if ip == nil and joinCounter < joinMaxAttempts then + print('Connecting to WiFi Access Point ...') + joinCounter = joinCounter + 1 + else + print("IP = " .. ip) + if joinCounter == joinMaxAttempts then + print('Failed to connect to WiFi Access Point.') + else + if (not not wifi.sta.getip()) or (not not wifi.ap.getip()) then + -- Second parameter is for mDNS (aka Zeroconf aka Bonjour) registration. + -- If the mdns module is compiled in the firmware, advertise the server with this name. + -- If no mdns is compiled, then parameter is ignored. + startServer(ip, "nodemcu") + end + end + tmr.stop(0) + joinCounter = nil + joinMaxAttempts = nil + collectgarbage() + end + end) +else + startServer() end From 10bcd2f170714259984350ce9816a9a6760a53a5 Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Mon, 26 Dec 2016 14:38:12 -0600 Subject: [PATCH 09/17] Modified to work on floating point firmware builds using changes by hazarkarabay. Fixes https://github.com/marcoskirsch/nodemcu-httpserver/issues/37 --- httpserver-b64decode.lua | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/httpserver-b64decode.lua b/httpserver-b64decode.lua index e18bea6..a79581e 100755 --- a/httpserver-b64decode.lua +++ b/httpserver-b64decode.lua @@ -1,33 +1,44 @@ #!/usr/local/bin/lua -- httpserver-b64decode.lua -- Part of nodemcu-httpserver, contains b64 decoding used for HTTP Basic Authentication. +-- Modified to use an exponentiation by multiplication method for only applicable for unsigned integers. -- Based on http://lua-users.org/wiki/BaseSixtyFour by Alex Kloss -- compatible with lua 5.1 -- http://www.it-rfc.de -- Author: Marcos Kirsch +local function uipow(a, b) + local ret = 1 + if b >= 0 then + for i = 1, b do + ret = ret * a + end + end + return ret +end + -- bitshift functions (<<, >> equivalent) -- shift left local function lsh(value,shift) - return (value*(2^shift)) % 256 + return (value*(uipow(2, shift))) % 256 end -- shift right local function rsh(value,shift) -- Lua builds with no floating point don't define math. - if math then return math.floor(value/2^shift) % 256 end - return (value/2^shift) % 256 + if math then return math.floor(value/uipow(2, shift)) % 256 end + return (value/uipow(2, shift)) % 256 end -- return single bit (for OR) local function bit(x,b) - return (x % 2^b - x % 2^(b-1) > 0) + return (x % uipow(2, b) - x % uipow(2, (b-1)) > 0) end -- logic OR for number values local function lor(x,y) result = 0 - for p=1,8 do result = result + (((bit(x,p) or bit(y,p)) == true) and 2^(p-1) or 0) end + for p=1,8 do result = result + (((bit(x,p) or bit(y,p)) == true) and uipow(2, (p-1)) or 0) end return result end @@ -62,4 +73,3 @@ return function(data) end return result end - From 79e345d964fb2b26f053254d02859c7934c427b6 Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Wed, 28 Dec 2016 14:16:58 -0600 Subject: [PATCH 10/17] Allow multiple users for basic HTTP authentication. --- httpserver-basicauth.lua | 17 ++++++++++++++--- httpserver-conf.lua | 6 +++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/httpserver-basicauth.lua b/httpserver-basicauth.lua index 09d4f78..42109ec 100644 --- a/httpserver-basicauth.lua +++ b/httpserver-basicauth.lua @@ -4,6 +4,16 @@ basicAuth = {} +-- Returns true if the user/password match one of the users/passwords in httpserver-conf.lua. +-- Returns false otherwise. +function loginIsValid(user, pwd, users) + if user == nil then return false end + if pwd == nil then return false end + if users[user] == nil then return false end + if users[user] ~= pwd then return false end + return true +end + -- Parse basic auth http header. -- Returns the username if header contains valid credentials, -- nil otherwise. @@ -15,12 +25,13 @@ function basicAuth.authenticate(header) end local credentials = dofile("httpserver-b64decode.lc")(credentials_enc) local user, pwd = credentials:match("^(.*):(.*)$") - if user ~= conf.auth.user or pwd ~= conf.auth.password then + if loginIsValid(user, pwd, conf.auth.users) then + print("httpserver-basicauth: User \"" .. user .. "\": Authenticated.") + return user + else print("httpserver-basicauth: User \"" .. user .. "\": Access denied.") return nil end - print("httpserver-basicauth: User \"" .. user .. "\": Authenticated.") - return user end function basicAuth.authErrorHeader() diff --git a/httpserver-conf.lua b/httpserver-conf.lua index 854e557..54ef5fd 100644 --- a/httpserver-conf.lua +++ b/httpserver-conf.lua @@ -6,10 +6,10 @@ local conf = {} -- Basic Authentication Conf local auth = {} -auth.enabled = false +auth.enabled = true auth.realm = "nodemcu-httpserver" -- displayed in the login dialog users get -auth.user = "user" -auth.password = "password" -- PLEASE change this +-- Add users and passwords to this table. Do not leave this unchanged if you enable authentication! +auth.users = {user1 = "password1", user2 = "password2", user3 = "password3"} conf.auth = auth return conf From 7aa44cd1a9ea79d7de6e99359efe1e3b13ac2bda Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Fri, 30 Dec 2016 14:37:15 -0600 Subject: [PATCH 11/17] Improve documentation related to HTTP Basic Authentication. Fixes https://github.com/marcoskirsch/nodemcu-httpserver/issues/71 --- README.md | 5 +++-- httpserver-conf.lua | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5d01052..a7a0930 100644 --- a/README.md +++ b/README.md @@ -65,12 +65,13 @@ Let the abuse begin. 4. How to use HTTP Basic Authentication. - Enable and configure HTTP Basic Authentication by editing "httpserver-conf.lua" file. + Modify variables in configuration file httpserver-conf.lua in order to enable and to configure usernames/passwords. + See comments in that file for more details. When enabled, HTTP Basic Authentication is global to every file served by the server. Remember that HTTP Basic Authentication is a very basic authentication protocol, and should not be - considered secure if the server is not using encryption, as your username and password travel + considered as secure since the server is not using encryption. Username and passwords travel in plain text. ## How to use server-side scripting using your own Lua scripts diff --git a/httpserver-conf.lua b/httpserver-conf.lua index 54ef5fd..85ab358 100644 --- a/httpserver-conf.lua +++ b/httpserver-conf.lua @@ -4,12 +4,14 @@ local conf = {} --- Basic Authentication Conf +-- Configure Basic HTTP Authentication. local auth = {} -auth.enabled = true -auth.realm = "nodemcu-httpserver" -- displayed in the login dialog users get +-- Set to true if you want to enable. +auth.enabled = false +-- Displayed in the login dialog users see before authenticating. +auth.realm = "nodemcu-httpserver" -- Add users and passwords to this table. Do not leave this unchanged if you enable authentication! auth.users = {user1 = "password1", user2 = "password2", user3 = "password3"} -conf.auth = auth +conf.auth = auth return conf From 203448067937bbbfb4cdc16f8c6305d955641fd0 Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Sun, 1 Jan 2017 22:12:18 -0600 Subject: [PATCH 12/17] Simplify by using file object model API --- httpserver-static.lua | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/httpserver-static.lua b/httpserver-static.lua index 178b17b..59958fa 100644 --- a/httpserver-static.lua +++ b/httpserver-static.lua @@ -3,32 +3,22 @@ -- Author: Marcos Kirsch return function (connection, req, args) - --print("Begin sending:", args.file) - --print("node.heap(): ", node.heap()) dofile("httpserver-header.lc")(connection, 200, args.ext, args.isGzipped) -- Send file in little chunks - local continue = true - local size = file.list()[args.file] - local bytesSent = 0 + local bytesRemaining = file.list()[args.file] -- Chunks larger than 1024 don't work. -- https://github.com/nodemcu/nodemcu-firmware/issues/1075 local chunkSize = 1024 - 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(chunkSize) - file.close() - + fileHandle = file.open(args.file) + while bytesRemaining > 0 do + local bytesToRead = 0 + if bytesRemaining > chunkSize then bytesToRead = chunkSize else bytesToRead = bytesRemaining end + local chunk = fileHandle:read(bytesToRead) connection:send(chunk) - bytesSent = bytesSent + #chunk + bytesRemaining = bytesRemaining - #chunk chunk = nil - --print("Sent: " .. bytesSent .. " of " .. size) - if bytesSent == size then continue = false end + collectgarbage() end - --print("Finished sending: ", args.file) + print("Finished sending: ", args.file) + fileHandle:close() end From 21654844139bf00fafdf75a52719dd49fdd34462 Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Sun, 1 Jan 2017 22:12:52 -0600 Subject: [PATCH 13/17] Add file.fscfg() results to example. --- http/file_list.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/http/file_list.lua b/http/file_list.lua index 2935ec8..d994043 100644 --- a/http/file_list.lua +++ b/http/file_list.lua @@ -7,12 +7,16 @@ return function (connection, req, args)

Server File Listing

]===]) - local remaining, used, total=file.fsinfo() + local remaining, used, total = file.fsinfo() connection:send("Total size: " .. total .. " bytes
\n" .. "In Use: " .. used .. " bytes
\n" .. - "Free: " .. remaining .. " bytes
\n" .. - "

\nFiles:
\n

    \n") + "Free: " .. remaining .. " bytes
    \n") + local flashAddress, flashSize = file.fscfg () + connection:send("Flash Address: " .. flashAddress .. " bytes
    \n" .. + "Flash Size: " .. flashSize .. " bytes
    \n") + + connection:send("

    \nFiles:
    \n

      \n") for name, size in pairs(file.list()) do local isHttpFile = string.match(name, "(http/)") ~= nil if isHttpFile then From 45edb29368b9ad05c7e422869476f70ede0e36d9 Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Sun, 1 Jan 2017 22:13:51 -0600 Subject: [PATCH 14/17] Fix crash when WiFi connection fails. --- init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.lua b/init.lua index d7c5d76..17a3748 100644 --- a/init.lua +++ b/init.lua @@ -98,10 +98,10 @@ if (wifi.getmode() == wifi.STATION) or (wifi.getmode() == wifi.STATIONAP) then print('Connecting to WiFi Access Point ...') joinCounter = joinCounter + 1 else - print("IP = " .. ip) if joinCounter == joinMaxAttempts then print('Failed to connect to WiFi Access Point.') else + print("IP = " .. ip) if (not not wifi.sta.getip()) or (not not wifi.ap.getip()) then -- Second parameter is for mDNS (aka Zeroconf aka Bonjour) registration. -- If the mdns module is compiled in the firmware, advertise the server with this name. From dba1ca79683ab466b19fda2546b104bd20c9f457 Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Sun, 1 Jan 2017 23:02:18 -0600 Subject: [PATCH 15/17] Fix - make fileHandle and clean it up, so it plays nice with coroutines. --- httpserver-static.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/httpserver-static.lua b/httpserver-static.lua index 59958fa..68ba94c 100644 --- a/httpserver-static.lua +++ b/httpserver-static.lua @@ -9,16 +9,19 @@ return function (connection, req, args) -- Chunks larger than 1024 don't work. -- https://github.com/nodemcu/nodemcu-firmware/issues/1075 local chunkSize = 1024 - fileHandle = file.open(args.file) + local fileHandle = file.open(args.file) while bytesRemaining > 0 do local bytesToRead = 0 if bytesRemaining > chunkSize then bytesToRead = chunkSize else bytesToRead = bytesRemaining end local chunk = fileHandle:read(bytesToRead) connection:send(chunk) bytesRemaining = bytesRemaining - #chunk + --print(args.file .. ": Sent "..#chunk.. " bytes, " .. bytesRemaining .. " to go.") chunk = nil collectgarbage() end print("Finished sending: ", args.file) fileHandle:close() + fileHandle = nil + collectgarbage() end From c59af98e19ef1460ec491ef6c975bb61faff40ae Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Sun, 1 Jan 2017 23:09:08 -0600 Subject: [PATCH 16/17] Change reference to number of images loaded by cars.html more ambiguous, in case that ever changes rendering this incorrect. --- http/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http/index.html b/http/index.html index 5bd9224..76e2922 100644 --- a/http/index.html +++ b/http/index.html @@ -20,7 +20,7 @@

      Serve me some pages!

      • Index: This page (static)
      • -
      • Nice cars: Stress test, loads 4 "large" images. Makes the chip panic and restart :( (static)
      • +
      • Nice cars: Stress test, loads several "large" images. Makes the chip panic and restart :( (static)
      • Zipped: File is actually saved as zipped.html.gz. A compressed file! (static but gzipped)
      • Zipped: Same exact file as served above. Server is smart enough to treat the .gz extension correctly (static but gzipped)
      • Arguments: Parses arguments passed in the URL and prints them. (Lua)
      • From 76750ab99ae409ccf85db61a17d154720f00b3fb Mon Sep 17 00:00:00 2001 From: Marcos Kirsch Date: Sun, 1 Jan 2017 23:09:48 -0600 Subject: [PATCH 17/17] Fixed formatting, and added more info on how this stress test crashes and hints on further testing. --- http/cars.html | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/http/cars.html b/http/cars.html index 6467a8b..41793aa 100644 --- a/http/cars.html +++ b/http/cars.html @@ -1,17 +1,21 @@ - - - Nice cars - - -

        Nice cars!

        -

        This page loads "large" images of fancy cars. It is meant to serve as a stress test for nodemcu-httpserver.

        -
        Ferrari
        -
        Lamborghini
        -
        Maserati
        -
        Porsche
        - + + + Nice cars + + +

        Nice cars!

        +

        + This page loads "large" images of fancy cars. It is meant to serve as a stress test for nodemcu-httpserver.
        + It works with three embedded images of cars, but the server crashes with four. Edit this file and try it yourself.
        + Whoever manages to modify nodemcu-httpserver to load all four images without crashing wins a prize! +

        +
        Ferrari
        +
        Lamborghini
        +
        Maserati
        +
        Porsche
        +