Browse Source

Refactored server to move request parsing into a separate file. This allows the server to be used in firmware builds with floating point enabled.

Marcos Kirsch 9 years ago
parent
commit
75ed944678
4 changed files with 66 additions and 64 deletions
  1. 54 0
      httpserver-request.lua
  2. 9 61
      httpserver.lua
  3. 2 2
      init.lua
  4. 1 1
      makefile

+ 54 - 0
httpserver-request.lua

@@ -0,0 +1,54 @@
+-- httpserver-request
+-- Part of nodemcu-httpserver, parses incoming client requests.
+-- Author: Marcos Kirsch
+
+local function validateMethod(method)
+   local httpMethods = {GET=true, HEAD=true, POST=true, PUT=true, DELETE=true, TRACE=true, OPTIONS=true, CONNECT=true, PATCH=true}
+   if httpMethods[method] then return true else return false end
+end
+
+local function uriToFilename(uri)
+   return "http/" .. string.sub(uri, 2, -1)
+end
+
+local function parseArgs(args)
+   local r = {}; i=1
+   if args == nil or args == "" then return r end
+   for arg in string.gmatch(args, "([^&]+)") do
+      local name, value = string.match(arg, "(.*)=(.*)")
+      if name ~= nil then r[name] = value end
+      i = i + 1
+   end
+   return r
+end
+
+local function parseUri(uri)
+   local r = {}
+   if uri == nil then return r end
+   if uri == "/" then uri = "/index.html" end
+   questionMarkPos, b, c, d, e, f = uri:find("?")
+   if questionMarkPos == nil then
+      r.file = uri:sub(1, questionMarkPos)
+      r.args = {}
+   else
+      r.file = uri:sub(1, questionMarkPos - 1)
+      r.args = parseArgs(uri:sub(questionMarkPos+1, #uri))
+   end
+   _, r.ext = r.file:match("(.+)%.(.+)")
+   r.isScript = r.ext == "lua" or r.ext == "lc"
+   r.file = uriToFilename(r.file)
+   return r
+end
+
+-- Parses the client's request. Returns a dictionary containing pretty much everything
+-- the server needs to know about the uri.
+return function (request)
+   local e = request:find("\r\n", 1, true)
+   if not e then return nil end
+   local line = request:sub(1, e - 1)
+   local r = {}
+   _, i, r.method, r.request = line:find("^([A-Z]+) (.-) HTTP/[1-9]+.[0-9]+$")
+   r.methodIsValid = validateMethod(r.method)
+   r.uri = parseUri(r.request)
+   return r
+end

+ 9 - 61
httpserver.lua

@@ -1,59 +1,6 @@
 -- httpserver
 -- Author: Marcos Kirsch
 
-module("httpserver", package.seeall)
-
--- Functions below aren't part of the public API
--- Clients don't need to worry about them.
-
--- given an HTTP method, returns it or if invalid returns nil
-local function validateMethod(method)
-   local httpMethods = {GET=true, HEAD=true, POST=true, PUT=true, DELETE=true, TRACE=true, OPTIONS=true, CONNECT=true, PATCH=true}
-   if httpMethods[method] then return method else return nil end
-end
-
-local function parseRequest(request)
-   local e = request:find("\r\n", 1, true)
-   if not e then return nil end
-   local line = request:sub(1, e - 1)
-   local r = {}
-   _, i, r.method, r.uri = line:find("^([A-Z]+) (.-) HTTP/[1-9]+.[0-9]+$")
-   return r
-end
-
-local function uriToFilename(uri)
-   return "http/" .. string.sub(uri, 2, -1)
-end
-
-local function parseArgs(args)
-   local r = {}; i=1
-   if args == nil or args == "" then return r end
-   for arg in string.gmatch(args, "([^&]+)") do
-      local name, value = string.match(arg, "(.*)=(.*)")
-      if name ~= nil then r[name] = value end
-      i = i + 1
-   end
-   return r
-end
-
-local function parseUri(uri)
-   local r = {}
-   if uri == nil then return r end
-   if uri == "/" then uri = "/index.html" end
-   questionMarkPos, b, c, d, e, f = uri:find("?")
-   if questionMarkPos == nil then
-      r.file = uri:sub(1, questionMarkPos)
-      r.args = {}
-   else
-      r.file = uri:sub(1, questionMarkPos - 1)
-      r.args = parseArgs(uri:sub(questionMarkPos+1, #uri))
-   end
-   _, r.ext = r.file:match("(.+)%.(.+)")
-   r.isScript = r.ext == "lua" or r.ext == "lc"
-   r.file = uriToFilename(r.file)
-   return r
-end
-
 -- Starts web server in the specified port.
 return function (port)
 
@@ -68,7 +15,6 @@ return function (port)
          local connectionThread
 
          local function onGet(connection, uri)
-            local uri = parseUri(uri)
             local fileServeFunction = nil
             if #(uri.file) > 32 then
                -- nodemcu-firmware cannot handle long filenames.
@@ -95,14 +41,16 @@ return function (port)
          end
 
          local function onReceive(connection, payload)
-            --print(payload) -- for debugging
+            -- print(payload) -- for debugging
             -- parse payload and decide what to serve.
-            local req = parseRequest(payload)
-            print("Requested URI: " .. req.uri)
-            req.method = validateMethod(req.method)
-            if req.method == "GET" then onGet(connection, req.uri)
-            elseif req.method == nil then dofile("httpserver-static.lc")(conection, {code=400})
-            else dofile("httpserver-static.lc")(conection, {code=501}) end
+            local req = dofile("httpserver-request.lc")(payload)
+            print("Requested URI: " .. req.request)
+            if req.methodIsValid then
+               if req.method == "GET" then onGet(connection, req.uri)
+               else dofile("httpserver-static.lc")(conection, {code=501}) end
+            else
+               dofile("httpserver-static.lc")(conection, {code=400})
+            end
          end
 
          local function onSent(connection, payload)

+ 2 - 2
init.lua

@@ -4,7 +4,7 @@ print('set mode=STATION (mode='..wifi.getmode()..')')
 print('MAC: ',wifi.sta.getmac())
 print('chip: ',node.chipid())
 print('heap: ',node.heap())
-wifi.sta.config("Internet","")
+wifi.sta.config("Kirsch Extreme","1151511515")
 
 -- Compile server code and remove original .lua files.
 -- This only happens the first time afer the .lua files are uploaded.
@@ -17,7 +17,7 @@ local compileAndRemoveIfNeeded = function(f)
    end
 end
 
-local serverFiles = {'httpserver.lua', 'httpserver-static.lua', 'httpserver-error.lua'}
+local serverFiles = {'httpserver.lua', 'httpserver-request.lua', 'httpserver-static.lua', 'httpserver-error.lua'}
 for i, f in ipairs(serverFiles) do compileAndRemoveIfNeeded(f) end
 
 compileAndRemoveIfNeeded = nil

+ 1 - 1
makefile

@@ -10,7 +10,7 @@ PORT=/dev/cu.usbserial-A602HRAZ
 # End of user config
 ######################################################################
 HTTP_FILES := $(wildcard http/*)
-LUA_FILES := init.lua httpserver.lua httpserver-static.lua httpserver-error.lua
+LUA_FILES := init.lua httpserver.lua httpserver-request.lua httpserver-static.lua httpserver-error.lua
 
 # Print usage
 usage: