Introduction: ESP8266 Webserver Serving Multiple Pages

With NodeMCU, the ESP8266 can easily serve a webpage.

In its simplest form, the server responds to a request by sending back 'client:send() one line at a time for each line in the page.

This works. However if you need to make changes in your webpage, you must upload a new .lua file and restart the module and dofile().

Also, it is pretty much limited to the webpage created by the 'server'. Only one server allowed at a time. So our server is limited to one page.

Webserver, one page?

Webserves should deliver multiple pages!

Step 1: Basic Server Setup.

To begin, we need an ESP8266, any version.

For this Instructable, the module needs to be flashed with NodeMCU.

I'm using NodeMCU release dev20150310-2.

Upload this server.lua file to your module, Restart and "dofile(server.lua)"

Ensure that your module has connected to your LAN and has an IP address assigned.

Open a browser and enter the module's IP number.
In my case, 192.168.11.44
You should see:


ESP8266
Server is working!

Step 2: This Is Great, But I Need More Flexibility!

Congratulations! Your ESP8266 webserver is working.
To make changes to this displayed page, simply edit the server.lua file, upload and Restart the module and dofile("server.lua").

Here is where things get interesting. As you know, a webserver, when receiving a request with no file specified will 'look' in the root directory for a index file. htm,html,asp,php........... and serve up that page. Our module with this server.lua file doesn't do that, it simply serves up the lines in the server.lua file that start with conn:send, from top to bottom.

How about different pages?

Lets say, for example that I want my ESP8266 to serve up different webpages for the names and contact information for each of our three employees, this information changes frequently. Oh, and I also want to know if they are in their office or not. And there is high employee turnover.

With our current setup, we would need to edit, upload, restart and dofile for each time a change is made. All this information would need to be in the server.lua file. This of course is possible, and could even be streamlined to make it not too painful.

Perhaps, I want to create a file called bob.htm and serve that file for Bob's information. Also, I can modify the index page. I can do this and not disturb the other employees information or have to restart the server.

The fun part of these modules is that there are many ways to accomplish a task. Here is an alternative.

Step 3: Lets Make Some Changes!

Hypothetically, I have three employees. Bob, Jill and Barb.

I would like my server to default to a landing page that lists hyperlinks to each employee:

___________________

ESP8266 server
Employee information:

Bob
Jill
Barb

___________________

I would like to click on an employee and be taken to their webpage for contact information and status.

Solution:

I'll create a separate htm file for each employee and a htm file for the landing page and I will serve them up by URL.

For example, the IP to my module is 192.168.11.44. for the index page the URL will be:

192.168.11.44 or 192.168.11.44/index.htm

For Bob the URL will be 192.168.11.44/bob.htm

Jill's information will be 192.168.11.44/jill.htm

etc.

In a nutshell, I will use a modified server.lua called newserver.lua file to serve up the individual files for the employees. Or for that matter, any file in the module's memory.

The archive below contains newserver.lua, index.htm and bob.htm
The archive can also be found here.

Unzip this archive and upload the files to your ESP8266 module. Restart and dofile("newserver.lua").

These files can be edited individually for each employee as needed when information changes. Editing newserver.lua will require a Restart and dofile() to implement the changes.

Step 4: Modified Server File Called Newserver.lua, the Key to Multi-webpages.

I now have uploaded the files called newserver.lua, index.htm and bob.htm to the module; Restarted and entered dofile("newserver.lua").

Entering my module'a IP number should display the index.htm file. Clicking on the link to Bob will display bob.htm, and Home will return to the index page.

Some discussion about newserver.lua:

I have coded index.htm as the 'landing' file. I want the module to serve index.htm when I enter the module's IP in a browser.

I am using some LUA code to parse the incoming header request to determine if the request specifies a file or not. A request to just my module's IP number 192.168.11.44 doesn't specify a particular file.

A portion of a typical header requesting index. may look like:

GET / HTTP/1.1
Host: 192.168.11.44 Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
..............etc.

This request is asking for bob.htm:

GET /bob.htm HTTP/1.1
Host: 192.168.11.44 Connection: keep-alive Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 ..............etc.

Parsing the first example, newserver.lua would not find a specific file to open. Since I want index.htm to be the landing file, when tgtfile returns nil, I substitute index.htm. Line 6.

Parsing the header for second request will identify that the request is specifying a file, in this case 'bob.htm'. So, bob.htm is opened and sent one line at at time with the client:send(file.read()) code.

It is important to not file.read() files that don't exist.
This will cause the module to panic and Restart.

So, before reading I test to see if the file exist with file.open(), line 7 and 8.

If no file, newserver.lua simply sends back 'file not found', and a link back to the landing page.

This happens when I click on Jill or Barb until I upload htm files for them.

------------------------------------------------------

  1. -- newserver.lua
  2. srv=net.createServer(net.TCP)
  3. srv:listen(80,function(conn)
  4. conn:on("receive", function(client,payload)
  5. tgtfile = string.sub(payload,string.find(payload,"GET /") +5,string.find(payload,"HTTP/") -2 )
  6. if tgtfile == "" then tgtfile = "index.htm" end
  7. local f = file.open(tgtfile,"r")
  8. if f ~= nil then
  9. client:send(file.read())
  10. file.close()
  11. else
  12. client:send("<html>")
  13. client:send(tgtfile.." not Found - 404 error.")
  14. client:send("<a href='index.htm'>Home</a>")
  15. end
  16. client:close()
  17. collectgarbage()
  18. f = nil
  19. tgtfile = nil
  20. end)
  21. end)

_____________________________________

Step 5: Final Thoughts.

The value of this particular process is dubious, however, it is always interesting to explore and expand what these little modules are capable of.

Some savvy LUA programming can certainly make these pages dynamic.

I mentioned earlier that I would like to know if the employees were in the office or not. Perhaps a sensor and a .LUA file that could open() and write to bob.htm on a timer would fit the bill? We can do that to.

The possibilities are endless!

I hope you have enjoyed this instructable and that it has furthered your knowledge of the ESP8266.