Compare commits
12 Commits
connect_ap
...
change_def
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53e12f21f1 | ||
|
|
9f4d7a9988 | ||
|
|
7c8fe9c164 | ||
|
|
5cf303de79 | ||
|
|
ab9a5d365f | ||
|
|
6158d4b5ba | ||
|
|
c67ed16e10 | ||
|
|
a70fa745b0 | ||
|
|
b5baf6cd48 | ||
|
|
28fbb6e7a7 | ||
|
|
0f852665ec | ||
|
|
dacaf31dc6 |
97
README.md
97
README.md
@@ -7,16 +7,16 @@ A (very) simple web server written in Lua for the ESP8266 running the NodeMCU fi
|
|||||||
> you are really abusing its intended purpose. When it comes to scoping your ESP8266
|
> you are really abusing its intended purpose. When it comes to scoping your ESP8266
|
||||||
> applications, the adage Keep It Simple Stupid truly applies.
|
> applications, the adage Keep It Simple Stupid truly applies.
|
||||||
>
|
>
|
||||||
> -- <cite>[Terry Ellison](https://github.com/TerryE)</cite>, nodemcu-firmware maintainer,
|
> -- <cite>[Terry Ellison](https://github.com/TerryE)</cite>, nodemcu-firmware maintainer
|
||||||
|
|
||||||
Let the abuse begin.
|
Let the abuse begin.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* GET, POST, PUT and minor changes to support other methods
|
* GET, POST, PUT (other methods can be supported with minor changes)
|
||||||
* Multiple MIME types
|
* Multiple MIME types
|
||||||
* Error pages (404 and others)
|
* Error pages (404 and others)
|
||||||
* Server-side execution of Lua scripts
|
* *Server-side execution of Lua scripts*
|
||||||
* Query string argument parsing with decoding of arguments
|
* Query string argument parsing with decoding of arguments
|
||||||
* Serving .gz compressed files
|
* Serving .gz compressed files
|
||||||
* HTTP Basic Authentication
|
* HTTP Basic Authentication
|
||||||
@@ -24,7 +24,9 @@ Let the abuse begin.
|
|||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
1. Upload server files using [nodemcu-uploader](https://github.com/kmpm/nodemcu-uploader).
|
1. Modify your local copy of the configuration file httpserver-conf.lua.
|
||||||
|
|
||||||
|
2. Upload server files using [nodemcu-uploader](https://github.com/kmpm/nodemcu-uploader).
|
||||||
The easiest is to use GNU Make with the bundled Makefile. Open the Makefile and modify the
|
The easiest is to use GNU Make with the bundled Makefile. Open the Makefile and modify the
|
||||||
user configuration to point to your nodemcu-uploader script and your serial port.
|
user configuration to point to your nodemcu-uploader script and your serial port.
|
||||||
Type the following to upload the server code, init.lua (which you may want to modify),
|
Type the following to upload the server code, init.lua (which you may want to modify),
|
||||||
@@ -32,28 +34,24 @@ Let the abuse begin.
|
|||||||
|
|
||||||
make upload_all
|
make upload_all
|
||||||
|
|
||||||
If you only want to upload the server code, then type:
|
If you only want to upload just the server code, then type:
|
||||||
|
|
||||||
make upload_server
|
make upload_server
|
||||||
|
|
||||||
And if you only want to upload the server files:
|
And if you only want to upload just the files that can be served:
|
||||||
|
|
||||||
make upload_http
|
make upload_http
|
||||||
|
|
||||||
Restart the server. This will execute init.lua which will compile the server code.
|
Restart the server. This will execute included init.lua which will compile the server code,
|
||||||
Then, assuming init.lua doesn't have it, start the server yourself by typing:
|
configure WiFi, and start the server.
|
||||||
|
|
||||||
dofile("httpserver.lc")(80)
|
3. Want to serve your own files? Put them under the http/ folder and upload to the chip.
|
||||||
|
For example, assuming you want to serve myfile.html, upload by typing:
|
||||||
|
|
||||||
In this example, 80 is the port your server is listening at, but you can change it.
|
make upload FILE:=http/myfile.html
|
||||||
|
|
||||||
2. Want to upload your own files? Move them to the http/ folder. Be careful though,
|
Notice that while NodeMCU's filesystem does not support folders, filenames *can* contain slashes.
|
||||||
the flash memory seems to fill up quickly and get corrupted.
|
We take advantage of that and only files that begin with "http/" will be accessible through the server.
|
||||||
|
|
||||||
All the files you upload must be prefixed with "http/". Wait, what?
|
|
||||||
|
|
||||||
Yes: NodeMCU's filesystem does not support folders, but filenames *can* contain slashes.
|
|
||||||
Only files that begin with "http/" will be accessible through the server.
|
|
||||||
|
|
||||||
3. Visit your server from a web browser.
|
3. Visit your server from a web browser.
|
||||||
|
|
||||||
@@ -63,21 +61,19 @@ Let the abuse begin.
|
|||||||
then index.html is served. By the way, unlike most HTTP servers, nodemcu_httpserver treats the URLs in a
|
then index.html is served. By the way, unlike most HTTP servers, nodemcu_httpserver treats the URLs in a
|
||||||
case-sensitive manner.
|
case-sensitive manner.
|
||||||
|
|
||||||
4. How to use HTTP Basic Authentication.
|
## HTTP Basic Authentication.
|
||||||
|
|
||||||
Modify variables in configuration file httpserver-conf.lua in order to enable and to configure usernames/passwords.
|
It's supported. Turn it on in httpserver-conf.lua.
|
||||||
See comments in that file for more details.
|
|
||||||
|
|
||||||
When enabled, HTTP Basic Authentication is global to every file served by the server.
|
Use it with care and don't fall into a false sense of security: HTTP Basic Authentication should not be
|
||||||
|
considered secure since the server is not using encryption. Username and passwords travel
|
||||||
|
in the clear.
|
||||||
|
|
||||||
Remember that HTTP Basic Authentication is a very basic authentication protocol, and should not be
|
## Server-side scripting using your own Lua scripts
|
||||||
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
|
Yes, you can upload your own Lua scripts! This is pretty powerful.
|
||||||
|
Just put it under http/ and upload it. Make sure it has a .lua extension.
|
||||||
Similar to static files, upload a Lua script called "http/[name].lua where you replace [name] with your script's name.
|
Your script should return a function that takes three parameters:
|
||||||
The script should return a function that takes three parameters:
|
|
||||||
|
|
||||||
return function (connection, req, args)
|
return function (connection, req, args)
|
||||||
-- code goes here
|
-- code goes here
|
||||||
@@ -107,42 +103,40 @@ Let the abuse begin.
|
|||||||
|
|
||||||
#### Hardware description
|
#### Hardware description
|
||||||
|
|
||||||
This example assumes that GPIO1 and GPIO2 on the ESP8266 are connected each to a relay
|
This example assumes that you are using a [Wemos D1 Pro](https://wiki.wemos.cc/products:d1:d1_mini_pro)
|
||||||
that can be controlled. How to wire such thing is outside of the scope of this document
|
with two relay shields and two reed switches.
|
||||||
[but information is easily found online](https://www.google.com/search?q=opening+a+garage+door+with+a+microcontroller).
|
|
||||||
The relays are controlled by the microcontroller and act as the push button,
|
The relays are controlled by the microcontroller and act as the push button,
|
||||||
and can actually be connected in parallel with the existing mechanical button.
|
and can actually be connected in parallel with the existing mechanical button.
|
||||||
|
The switches are wired so that the ESP8266 can tell whether the doors are open
|
||||||
|
or closed at any given time.
|
||||||
|
|
||||||
#### Software description
|
#### Software description
|
||||||
|
|
||||||
This example consists of the following files:
|
This example consists of the following files:
|
||||||
|
|
||||||
* **garage_door_opener.html**: Static HTML displays a button with a link
|
* **garage_door.html**: Static HTML displays a form with all options for controlling the
|
||||||
to the garage_door_opener.lua script. That's it!
|
two garage doors.
|
||||||
* **garage_door_opener.css**: Provides styling for garage_door_opener.html
|
* **garage_door_control.html**: Looks like a garage door remote, how neat!
|
||||||
just so it looks pretty.
|
* **garage_door_control.css**: Provides styling for garage_door_control.html.
|
||||||
* **garage_door_opener.lua**: Does the actual work. The script first sends
|
* **garage_door.lua**: Does the actual work. The script performs the desired action on
|
||||||
a little javascript snippet to redirect the client back to garage_door_opener.html
|
the requested door and returns the results as JSON.
|
||||||
and then toggles the GPIO2 line for a short amount of time (roughly equivalent to
|
|
||||||
the typical button press for opening a garage door) and then toggles it back.
|
|
||||||
* **apple-touch-icon.png**: This is optional. Provides an icon that
|
* **apple-touch-icon.png**: This is optional. Provides an icon that
|
||||||
will be used if you "Add to Home Screen" the demo on an iPhone. Now it looks like an app!
|
will be used if you "Add to Home Screen" garage_door_control.html on an iPhone.
|
||||||
|
Now it looks like an app!
|
||||||
|
|
||||||
#### Security implications
|
#### Security implications
|
||||||
|
|
||||||
Be careful permanently installing something like this in your home. The server provides
|
Be careful permanently installing something like this in your home. The server provides
|
||||||
no encryption. Your only layers of security are the WiFi network's password and simple
|
no encryption. Your only layers of security are the WiFi network's password and simple
|
||||||
HTTP authentication which sends your password unencrypted.
|
HTTP authentication (if you enable it) which sends your password unencrypted.
|
||||||
|
|
||||||
This script is provided simply as an educational example. You've been warned.
|
This script is provided for educational purposes. You've been warned.
|
||||||
|
|
||||||
## Not supported
|
## Not supported
|
||||||
|
|
||||||
* Other methods: HEAD, DELETE, TRACE, OPTIONS, CONNECT, PATCH
|
* Other methods: HEAD, DELETE, TRACE, OPTIONS, CONNECT, PATCH
|
||||||
* Encryption / SSL
|
* Encryption / SSL
|
||||||
* Multiple users (HTTP Basic Authentication)
|
* Old nodemcu-firmware versions prior to January 2017) because I don't bother to test them.
|
||||||
* Only protect certain directories (HTTP Basic Authentication)
|
|
||||||
* nodemcu-firmware versions older 1.5.1 (January 2016) because that's what I tested on.
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
@@ -151,7 +145,9 @@ Let the abuse begin.
|
|||||||
and that you add examples for new features. I won't test all your changes myself but I
|
and that you add examples for new features. I won't test all your changes myself but I
|
||||||
am very grateful of improvements and fixes. Open issues in GitHub too, that's useful.
|
am very grateful of improvements and fixes. Open issues in GitHub too, that's useful.
|
||||||
|
|
||||||
Please follow the coding style as close as possible:
|
Please keep your PRs focused on one thing. I don't mind lots of PRs. I mind PRs that fix multiple unrelated things.
|
||||||
|
|
||||||
|
Follow the coding style as closely as possible:
|
||||||
|
|
||||||
* No tabs, indent with 3 spaces
|
* No tabs, indent with 3 spaces
|
||||||
* Unix (LF) line endings
|
* Unix (LF) line endings
|
||||||
@@ -163,8 +159,9 @@ Let the abuse begin.
|
|||||||
|
|
||||||
The chip is very, very memory constrained.
|
The chip is very, very memory constrained.
|
||||||
|
|
||||||
* Use a recent nodemcu-firmware with as few optional modules as possible.
|
* Use a recent nodemcu-firmware. They've really improved memory usage and fixed leaks.
|
||||||
* Use a firmware build without floating point support. This takes up a good chunk of RAM as well.
|
* Use only the modules you need.
|
||||||
* Any help reducing the memory needs of the server without crippling its functionality is appreciated!
|
* Use a firmware build without floating point support if you can.
|
||||||
* Compile your Lua scripts in order to reduce their memory usage. The server knows to serve and treat
|
* Any help reducing the memory needs of the server without crippling its functionality is much appreciated!
|
||||||
|
* Compile your Lua scripts in order to reduce their memory usage. The server knows to serve
|
||||||
both .lua and .lc files as scripts.
|
both .lua and .lc files as scripts.
|
||||||
|
|||||||
BIN
http/cars-bugatti.jpg
Normal file
BIN
http/cars-bugatti.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
http/cars-mercedes.jpg
Normal file
BIN
http/cars-mercedes.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
51
http/cars.lua
Normal file
51
http/cars.lua
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
return function (connection, req, args)
|
||||||
|
|
||||||
|
local function showCars(nr)
|
||||||
|
if not nr then return end
|
||||||
|
connection:send([===[<figure><img src="cars-ferrari.jpg" /><figcaption>Ferrari</figcaption></figure>]===])
|
||||||
|
if nr == "1" then return end
|
||||||
|
connection:send([===[<figure><img src="cars-lambo.jpg" /><figcaption>Lamborghini</figcaption></figure>]===])
|
||||||
|
if nr == "2" then return end
|
||||||
|
connection:send([===[<figure><img src="cars-mas.jpg" /><figcaption>Maserati</figcaption></figure>]===])
|
||||||
|
if nr == "3" then return end
|
||||||
|
connection:send([===[<figure><img src="cars-porsche.jpg" /><figcaption>Porsche</figcaption></figure>]===])
|
||||||
|
if nr == "4" then return end
|
||||||
|
connection:send([===[<figure><img src="cars-bugatti.jpg" /><figcaption>Bugatti</figcaption></figure>]===])
|
||||||
|
if nr == "5" then return end
|
||||||
|
connection:send([===[<figure><img src="cars-mercedes.jpg" /><figcaption>Mercedes</figcaption></figure>]===])
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
dofile("httpserver-header.lc")(connection, 200, 'html')
|
||||||
|
connection:send([===[
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
|
<title>Nice cars</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Nice cars!</h1>
|
||||||
|
<p>
|
||||||
|
This page loads "large" images of fancy cars. It is meant to serve as a stress test for nodemcu-httpserver.<br>
|
||||||
|
It works with three embedded images of cars, but the server crashes with four. Select the number of cars you want to see below.<br>
|
||||||
|
Whoever manages to modify nodemcu-httpserver to load all four images without crashing wins a prize!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
choose: <a href="?n=1">show one car</a>
|
||||||
|
<a href="?n=2">show two cars</a>
|
||||||
|
<a href="?n=3">show three cars</a>
|
||||||
|
<a href="?n=4">show four cars</a>
|
||||||
|
<a href="?n=5">show five cars</a>
|
||||||
|
<a href="?n=6">show six cars</a>
|
||||||
|
</p>
|
||||||
|
]===])
|
||||||
|
|
||||||
|
showCars(args.n)
|
||||||
|
|
||||||
|
connection:send([===[
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]===])
|
||||||
|
end
|
||||||
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
-- Author: moononournation
|
|
||||||
-- Notes by Marcos: This example could be improved quite a bit.
|
|
||||||
-- We should provide a way to return available access points as JSON, then populated
|
|
||||||
-- a drop down list using JavaScript every 5-10 seconds. I'm not sure it's worth it,
|
|
||||||
-- however.
|
|
||||||
|
|
||||||
return function (connection, req, args)
|
|
||||||
dofile('httpserver-header.lc')(connection, 200, 'html')
|
|
||||||
|
|
||||||
connection:send('<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>Connect AP</title></head><body><h1>Connect AP</h1>')
|
|
||||||
|
|
||||||
if req.method == 'GET' then
|
|
||||||
local ip = wifi.sta.getip()
|
|
||||||
if not (ip == nil) then
|
|
||||||
connection:send('<p>IP: ' .. ip .. '</p>')
|
|
||||||
end
|
|
||||||
connection:send('<form method="POST">SSID:<br><input type="text" name="ssid"><br>PWD:<br><input type="text" name="pwd"><br><input type="submit" name="submit" value="Submit"></form>')
|
|
||||||
elseif req.method == 'POST' then
|
|
||||||
local rd = req.getRequestData()
|
|
||||||
|
|
||||||
collectgarbage()
|
|
||||||
wifi.sta.config(rd['ssid'], rd['pwd'])
|
|
||||||
wifi.sta.connect()
|
|
||||||
local joinCounter = 0
|
|
||||||
local joinMaxAttempts = 15
|
|
||||||
tmr.alarm(0, 1000, 1, function()
|
|
||||||
local ip = wifi.sta.getip()
|
|
||||||
if ip == nil and joinCounter < joinMaxAttempts then
|
|
||||||
joinCounter = joinCounter + 1
|
|
||||||
else
|
|
||||||
if joinCounter >= joinMaxAttempts then
|
|
||||||
connection:send('<p>Failed to connect to WiFi Access Point.</p>')
|
|
||||||
else
|
|
||||||
connection:send('<p>IP: ' .. ip .. '</p>')
|
|
||||||
end
|
|
||||||
tmr.stop(0)
|
|
||||||
joinCounter = nil
|
|
||||||
joinMaxAttempts = nil
|
|
||||||
collectgarbage()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
connection:send('</body></html>')
|
|
||||||
end
|
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
<li><a href="index.html">Index</a>: This page (static)</li>
|
<li><a href="index.html">Index</a>: This page (static)</li>
|
||||||
<li><a href="hello_world.txt">A text file</a>: Simple text, to verify MIME type is ok. (static)</li>
|
<li><a href="hello_world.txt">A text file</a>: Simple text, to verify MIME type is ok. (static)</li>
|
||||||
<li><a href="cars.html">Nice cars</a>: Stress test, loads several "large" images. Makes the chip panic and restart :( (static)</li>
|
<li><a href="cars.html">Nice cars</a>: Stress test, loads several "large" images. Makes the chip panic and restart :( (static)</li>
|
||||||
|
<li><a href="cars.lua">Nice cars</a>: Stress test, loads several "large" images. Makes the chip panic and restart :( (dynamic to change number of cars)</li>
|
||||||
<li><a href="counter.html">Count Requests</a>: Stress test, loads the same page over and over, counting every load. (static)</li>
|
<li><a href="counter.html">Count Requests</a>: Stress test, loads the same page over and over, counting every load. (static)</li>
|
||||||
<li><a href="zipped.html">Zipped</a>: File is actually saved as zipped.html.gz. A compressed file! (static but gzipped)</li>
|
<li><a href="zipped.html">Zipped</a>: File is actually saved as zipped.html.gz. A compressed file! (static but gzipped)</li>
|
||||||
<li><a href="zipped.html.gz">Zipped</a>: Same exact file as served above. Server is smart enough to treat the .gz extension correctly (static but gzipped)</li>
|
<li><a href="zipped.html.gz">Zipped</a>: Same exact file as served above. Server is smart enough to treat the .gz extension correctly (static but gzipped)</li>
|
||||||
|
|||||||
@@ -33,6 +33,29 @@
|
|||||||
|
|
||||||
.dropBox {width:100vw; height:100vh; margin-top: -200px; padding-top: 200px;}
|
.dropBox {width:100vw; height:100vh; margin-top: -200px; padding-top: 200px;}
|
||||||
|
|
||||||
|
#uploaddir{
|
||||||
|
background-color: #2E3134;
|
||||||
|
font-size:16px;
|
||||||
|
font-weight:bold;
|
||||||
|
color:#7f858a;
|
||||||
|
padding: 40px 50px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploaddir a{
|
||||||
|
background-color:#007a96;
|
||||||
|
padding:12px 26px;
|
||||||
|
color:#fff;
|
||||||
|
font-size:14px;
|
||||||
|
border-radius:2px;
|
||||||
|
cursor:pointer;
|
||||||
|
margin-top:12px;
|
||||||
|
line-height:1;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
#selectedDir {
|
||||||
|
margin-top:20px;
|
||||||
|
}
|
||||||
#upload{
|
#upload{
|
||||||
font-family:'PT Sans Narrow', sans-serif;
|
font-family:'PT Sans Narrow', sans-serif;
|
||||||
background-color:#373a3d;
|
background-color:#373a3d;
|
||||||
@@ -140,14 +163,24 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.delete:after{
|
||||||
|
color: #ff0000;
|
||||||
|
content: "\2718";
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploaded:after{
|
||||||
|
color: #00ff00;
|
||||||
|
content: "\2714";
|
||||||
|
}
|
||||||
|
|
||||||
#upload ul li span{
|
#upload ul li span{
|
||||||
width: 15px;
|
width: 15px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAaCAYAAABozQZiAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpFQUY1MzY0QUU3QjdFMjExODE0NkUyMUJBNERDNDk0NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCOTc5MTBDQ0I3RUYxMUUyOUVBQkNFOURERDIzQkU4NSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCOTc5MTBDQkI3RUYxMUUyOUVBQkNFOURERDIzQkU4NSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFQUY1MzY0QUU3QjdFMjExODE0NkUyMUJBNERDNDk0NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFQUY1MzY0QUU3QjdFMjExODE0NkUyMUJBNERDNDk0NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvX6SiYAAAGjSURBVHjanJRPRMRREMfbNtE19hQlolNdomsRaZUiIlHKdiml7CpFolU6pEOWTUTRJZKIakmHsqQ99UedOiT2lG6xRPSdzFtjGi+/ho99836/78z8Zt7bUN3VfElAKwcRkC/9h/AAPIKmsgDCMNgB3ezvB8m8BQZ4/QkmSVwJbsCcR7gOYrz+Av0gQ2WfgWaGvimphEsgLvwRcEQLypxVLy4KP678cbDnHMqc4GZMiQBU2huX62wWbMqSXLenWeDKW1alr4A13QjZ7YT1AmwDLFhd1KOi0naFf8lVmWYdklHuQTXo8g3eOiT07UOgFXy4zcPB2wpTjAdpcA8iVgbs0yTe8dsi90N3NdEUfifYfwBtPCZn9CzF6wJXlGt8Of3JXCVebAAXfOXIxoTQfVJYlk3n9NgIQGc9LfYpaxRcSzHdkD4jwKoStqujXOy2FUBnzPpGRQHODfErePprzjHVHGf1qom/xCTcVlXkPFMoiocNYQ/PM+MLQOIZJexlUUGsZYBOKaYRPAvhieq0DJCUt45uVZ5LrLXGIQJ0uP8uZ98CDADM9WkEBoK0xwAAAABJRU5ErkJggg==') no-repeat;
|
cursor:pointer;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 34px;
|
top: 34px;
|
||||||
right: 33px;
|
right: 33px;
|
||||||
cursor:pointer;
|
font-size:18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#upload ul li.working span{
|
#upload ul li.working span{
|
||||||
@@ -189,7 +222,7 @@
|
|||||||
var chunkSize = 128;
|
var chunkSize = 128;
|
||||||
var totalUploaded = 0;
|
var totalUploaded = 0;
|
||||||
|
|
||||||
var tpl = '<li class="working" id="file%filenum%"><div class="chart" id="graph%filenum%" data-percent="0"></div><p>%filename%<i>%filesize%</i></p><span id="fileStatus%filenum%" onclick="DeleteFiles(%filenum%);"></span></li>';
|
var tpl = '<li class="working" id="file%filenum%"><div class="chart" id="graph%filenum%" data-percent="0"></div><p>%filename%<i>%filesize%</i></p><span class="delete" id="fileStatus%filenum%" onclick="DeleteFiles(%filenum%);"></span></li>';
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
var dropbox;
|
var dropbox;
|
||||||
@@ -200,6 +233,8 @@
|
|||||||
dropbox.addEventListener("drop", drop, false);
|
dropbox.addEventListener("drop", drop, false);
|
||||||
|
|
||||||
UpdateFileList();
|
UpdateFileList();
|
||||||
|
|
||||||
|
UploadDir("http");
|
||||||
});
|
});
|
||||||
|
|
||||||
function dragenter(e) {
|
function dragenter(e) {
|
||||||
@@ -235,13 +270,13 @@
|
|||||||
var fileNames = {};
|
var fileNames = {};
|
||||||
|
|
||||||
for (var i = 0; i < filesCount; i++) {
|
for (var i = 0; i < filesCount; i++) {
|
||||||
fileNames[tfiles[i].name] = i;
|
fileNames[uploadDir + tfiles[i].name] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys(fileNames).sort(function(a,b){var c=a.toLowerCase(),d=b.toLowerCase();return c<d?-1:c>d?1:0}).forEach(function(item) {
|
Keys(fileNames).sort(function(a,b){var c=a.toLowerCase(),d=b.toLowerCase();return c<d?-1:c>d?1:0}).forEach(function(item) {
|
||||||
var i = fileNames[item];
|
var i = fileNames[item];
|
||||||
|
|
||||||
var append = tpl.replace(/%filename%/g, tfiles[i].name);
|
var append = tpl.replace(/%filename%/g, uploadDir + tfiles[i].name);
|
||||||
append = append.replace(/%filesize%/g, formatFileSize(tfiles[i].size));
|
append = append.replace(/%filesize%/g, formatFileSize(tfiles[i].size));
|
||||||
append = append.replace(/%filenum%/g, i);
|
append = append.replace(/%filenum%/g, i);
|
||||||
|
|
||||||
@@ -380,7 +415,7 @@
|
|||||||
totalUploaded = 0;
|
totalUploaded = 0;
|
||||||
|
|
||||||
if (statusElement) {
|
if (statusElement) {
|
||||||
statusElement.style["background-position"] = "0 3px";
|
statusElement.classList.add("uploaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUploadingFile < files.length) {
|
if (currentUploadingFile < files.length) {
|
||||||
@@ -396,7 +431,7 @@
|
|||||||
fileUploadRequest = 0;
|
fileUploadRequest = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastRequest = 'upload.lua?cmd=upload&filename=' + file.name + '&filesize=' + file.size + '&len=' + chunkLen + '&offset=' + sendingOffset + '&data=' + filedata;
|
lastRequest = 'upload.lua?cmd=upload&filename=' + uploadDir + file.name + '&filesize=' + file.size + '&len=' + chunkLen + '&offset=' + sendingOffset + '&data=' + filedata;
|
||||||
|
|
||||||
fileUploadRequest.timeout = 5000;
|
fileUploadRequest.timeout = 5000;
|
||||||
fileUploadRequest.open('GET', lastRequest, true);
|
fileUploadRequest.open('GET', lastRequest, true);
|
||||||
@@ -406,6 +441,16 @@
|
|||||||
fr.readAsArrayBuffer(file);
|
fr.readAsArrayBuffer(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function UploadDir(dir) {
|
||||||
|
if (uploadingInProgress == 0) {
|
||||||
|
document.getElementById('dir').innerHTML = "/" + dir;
|
||||||
|
uploadDir = dir;
|
||||||
|
if (!(uploadDir == "")) {
|
||||||
|
uploadDir += "/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function formatFileSize(bytes) {
|
function formatFileSize(bytes) {
|
||||||
if (typeof bytes !== 'number') {
|
if (typeof bytes !== 'number') {
|
||||||
return '';
|
return '';
|
||||||
@@ -494,14 +539,14 @@
|
|||||||
|
|
||||||
document.getElementById('fileInfo').innerHTML = '';
|
document.getElementById('fileInfo').innerHTML = '';
|
||||||
|
|
||||||
var tpl = '<li class="working"><p style="left: 30px;">%filenamelink%<i>%filesize%</i></p><span id="fileStatus" onclick="RemoveFile(\'%filename%\');"></span></li>';
|
var tpl = '<li class="working"><p style="left: 30px;">%filenamelink%<i>%filesize%</i></p><span class="delete" id="fileStatus" onclick="RemoveFile(\'%filename%\');"></span></li>';
|
||||||
var tplTotal = '<li class="working"><p style="left: 30px;">Used:<i>%used%</i></p></li><li class="working"><p style="left: 30px;">Free:<i>%free%</i></p></li><li class="working"><p style="left: 30px;">Total:<i>%total%</i></p></li>';
|
var tplTotal = '<li class="working"><p style="left: 30px;">Used:<i>%used%</i></p></li><li class="working"><p style="left: 30px;">Free:<i>%free%</i></p></li><li class="working"><p style="left: 30px;">Total:<i>%total%</i></p></li>';
|
||||||
|
|
||||||
var append, link;
|
var append, link;
|
||||||
|
|
||||||
Keys(fileList).sort(function(a,b){var c=a.toLowerCase(),d=b.toLowerCase();return c<d?-1:c>d?1:0}).forEach(function(item) {
|
Keys(fileList).sort(function(a,b){var c=a.toLowerCase(),d=b.toLowerCase();return c<d?-1:c>d?1:0}).forEach(function(item) {
|
||||||
if (!(item.match(/\.lc$/ig))) {
|
if (!item.match(/\.lc$/ig) && item.match(/^http\//ig)) {
|
||||||
link = item.replace(/\.gz$/g, '');
|
link = item.replace(/\.gz$/g, '').replace(/^http\//g, '');
|
||||||
append = tpl.replace(/%filenamelink%/g, '<a href="' + link + '" target="_blank">' + item + '</a>');
|
append = tpl.replace(/%filenamelink%/g, '<a href="' + link + '" target="_blank">' + item + '</a>');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -549,12 +594,16 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="dropbox" class="dropBox">
|
<div id="dropbox" class="dropBox">
|
||||||
<div id="upload">
|
<div id="upload">
|
||||||
|
<div id="uploaddir" class="uploadDir">
|
||||||
|
<a onclick='UploadDir("");'>/</a>
|
||||||
|
<a onclick='UploadDir("http");'>/http</a>
|
||||||
|
<div id="selectedDir">selected Directory: <div id = "dir">bla</div></div></div>
|
||||||
<div id="drop">
|
<div id="drop">
|
||||||
Drop Here
|
Drop Here
|
||||||
|
|
||||||
<a onclick='document.getElementById("browseInput").click();'>Browse</a>
|
<a onclick='document.getElementById("browseInput").click();'>Browse</a>
|
||||||
<a onclick='UploadFiles();'>Upload</a>
|
<a onclick='UploadFiles();'>Upload</a>
|
||||||
<input id="browseInput" type="file" name="upl" onchange="handleFiles(this.files);" multiple />
|
<form><input id="browseInput" type="file" name="upl" onclick="this.form.reset();" onchange="handleFiles(this.files);" multiple /></form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul id="fileList">
|
<ul id="fileList">
|
||||||
|
|||||||
@@ -48,23 +48,22 @@ return function (connection, req, args)
|
|||||||
|
|
||||||
if (mbCmd == 'upload') then
|
if (mbCmd == 'upload') then
|
||||||
if (fieldsCount > 5) then
|
if (fieldsCount > 5) then
|
||||||
if (mbFilename ~= 'upload.lua') then
|
if (mbFilename ~= 'http/upload.lua') then
|
||||||
connection:send('"offset":"' .. mbOffset .. '",')
|
connection:send('"offset":"' .. mbOffset .. '",')
|
||||||
connection:send('"len":"' .. mbLen .. '",')
|
connection:send('"len":"' .. mbLen .. '",')
|
||||||
connection:send('"filename":"' .. mbFilename .. '"')
|
connection:send('"filename":"' .. mbFilename .. '"')
|
||||||
|
|
||||||
mbFilename = 'http/' .. mbFilename
|
|
||||||
|
|
||||||
for i=1,string.len(mbData),2 do
|
for i=1,string.len(mbData),2 do
|
||||||
currentByte = tonumber(string.sub(mbData, i, i + 1), 16)
|
currentByte = tonumber(string.sub(mbData, i, i + 1), 16)
|
||||||
binaryData = binaryData .. string.char(currentByte)
|
binaryData = binaryData .. string.char(currentByte)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local mbTmpFilename = string.sub(mbFilename, 0, 27) .. '.dnl'
|
||||||
if (mbOffset > 0) then
|
if (mbOffset > 0) then
|
||||||
file.open(mbFilename .. '.dnl','a+')
|
file.open(mbTmpFilename,'a+')
|
||||||
else
|
else
|
||||||
file.remove(mbFilename .. '.dnl')
|
file.remove(mbTmpFilename)
|
||||||
file.open(mbFilename .. '.dnl','w+')
|
file.open(mbTmpFilename,'w+')
|
||||||
end
|
end
|
||||||
file.seek("set", mbOffset)
|
file.seek("set", mbOffset)
|
||||||
file.write(binaryData)
|
file.write(binaryData)
|
||||||
@@ -74,8 +73,8 @@ return function (connection, req, args)
|
|||||||
|
|
||||||
if (fileSize == mbLen + mbOffset) then
|
if (fileSize == mbLen + mbOffset) then
|
||||||
file.remove(mbFilename)
|
file.remove(mbFilename)
|
||||||
file.rename(mbFilename .. '.dnl', mbFilename)
|
file.rename(mbTmpFilename, mbFilename)
|
||||||
file.remove(mbFilename .. '.dnl')
|
file.remove(mbTmpFilename)
|
||||||
|
|
||||||
if (string.sub(mbFilename, -4) == '.lua') then
|
if (string.sub(mbFilename, -4) == '.lua') then
|
||||||
file.remove(string.sub(mbFilename, 0, -3) .. "lc")
|
file.remove(string.sub(mbFilename, 0, -3) .. "lc")
|
||||||
@@ -93,20 +92,16 @@ return function (connection, req, args)
|
|||||||
connection:send('"files":{')
|
connection:send('"files":{')
|
||||||
|
|
||||||
for name, size in pairs(file.list()) do
|
for name, size in pairs(file.list()) do
|
||||||
local isHttpFile = string.match(name, "(http/)") ~= nil
|
|
||||||
|
|
||||||
if isHttpFile then
|
|
||||||
if (headerExist > 0) then
|
if (headerExist > 0) then
|
||||||
connection:send(',')
|
connection:send(',')
|
||||||
end
|
end
|
||||||
|
|
||||||
local url = string.match(name, ".*/(.*)")
|
local url = string.match(name, ".*/(.*)")
|
||||||
|
url = name
|
||||||
connection:send('"' .. url .. '":"' .. size .. '"')
|
connection:send('"' .. url .. '":"' .. size .. '"')
|
||||||
|
|
||||||
headerExist = 1
|
headerExist = 1
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
connection:send('},')
|
connection:send('},')
|
||||||
|
|
||||||
@@ -115,8 +110,8 @@ return function (connection, req, args)
|
|||||||
connection:send('"free":"' .. remaining .. '"')
|
connection:send('"free":"' .. remaining .. '"')
|
||||||
elseif (mbCmd == 'remove') then
|
elseif (mbCmd == 'remove') then
|
||||||
if (fieldsCount > 1) then
|
if (fieldsCount > 1) then
|
||||||
if (mbFilename ~= 'upload.lua') and (mbFilename ~= 'upload.lc') and (mbFilename ~= 'upload.html.gz') then
|
if (mbFilename ~= 'http/upload.lua') and (mbFilename ~= 'http/upload.lc') and (mbFilename ~= 'http/upload.html.gz') then
|
||||||
file.remove('http/' .. mbFilename)
|
file.remove(mbFilename)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -124,4 +119,3 @@ return function (connection, req, args)
|
|||||||
connection:send('}')
|
connection:send('}')
|
||||||
collectgarbage()
|
collectgarbage()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -37,14 +37,14 @@ end
|
|||||||
|
|
||||||
-- logic OR for number values
|
-- logic OR for number values
|
||||||
local function lor(x,y)
|
local function lor(x,y)
|
||||||
result = 0
|
local result = 0
|
||||||
for p=1,8 do result = result + (((bit(x,p) or bit(y,p)) == true) and uipow(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
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Character decoding table
|
-- Character decoding table
|
||||||
local function toBase64Byte(char)
|
local function toBase64Byte(char)
|
||||||
ascii = string.byte(char, 1)
|
local ascii = string.byte(char, 1)
|
||||||
if ascii >= string.byte('A', 1) and ascii <= string.byte('Z', 1) then return ascii - string.byte('A', 1)
|
if ascii >= string.byte('A', 1) and ascii <= string.byte('Z', 1) then return ascii - string.byte('A', 1)
|
||||||
elseif ascii >= string.byte('a', 1) and ascii <= string.byte('z', 1) then return ascii - string.byte('a', 1) + 26
|
elseif ascii >= string.byte('a', 1) and ascii <= string.byte('z', 1) then return ascii - string.byte('a', 1) + 26
|
||||||
elseif ascii >= string.byte('0', 1) and ascii <= string.byte('9', 1) then return ascii + 4
|
elseif ascii >= string.byte('0', 1) and ascii <= string.byte('9', 1) then return ascii + 4
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
-- Part of nodemcu-httpserver, authenticates a user using http basic auth.
|
-- Part of nodemcu-httpserver, authenticates a user using http basic auth.
|
||||||
-- Author: Sam Dieck
|
-- Author: Sam Dieck
|
||||||
|
|
||||||
basicAuth = {}
|
local basicAuth = {}
|
||||||
|
|
||||||
-- Returns true if the user/password match one of the users/passwords in httpserver-conf.lua.
|
-- Returns true if the user/password match one of the users/passwords in httpserver-conf.lua.
|
||||||
-- Returns false otherwise.
|
-- Returns false otherwise.
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
-- Author: Marcos Kirsch
|
-- Author: Marcos Kirsch
|
||||||
|
|
||||||
local compileAndRemoveIfNeeded = function(f)
|
local compileAndRemoveIfNeeded = function(f)
|
||||||
if file.open(f) then
|
if file.exists(f) then
|
||||||
file.close()
|
|
||||||
print('Compiling:', f)
|
print('Compiling:', f)
|
||||||
node.compile(f)
|
node.compile(f)
|
||||||
file.remove(f)
|
file.remove(f)
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ if (conf.wifi.mode == wifi.SOFTAP) or (conf.wifi.mode == wifi.STATIONAP) then
|
|||||||
conf.wifi.accessPoint.config = {}
|
conf.wifi.accessPoint.config = {}
|
||||||
conf.wifi.accessPoint.config.ssid = "ESP-"..node.chipid() -- Name of the WiFi network to create.
|
conf.wifi.accessPoint.config.ssid = "ESP-"..node.chipid() -- Name of the WiFi network to create.
|
||||||
conf.wifi.accessPoint.config.pwd = "ESP-"..node.chipid() -- WiFi password for joining - at least 8 characters
|
conf.wifi.accessPoint.config.pwd = "ESP-"..node.chipid() -- WiFi password for joining - at least 8 characters
|
||||||
conf.wifi.accessPoint.ip = "192.168.111.1"
|
conf.wifi.accessPoint.net = {}
|
||||||
-- conf.wifi.accessPoint.netmask = "255.255.255.0"
|
conf.wifi.accessPoint.net.ip = "192.168.111.1"
|
||||||
-- conf.wifi.accessPoint.gateway = "192.168.111.1"
|
conf.wifi.accessPoint.net.netmask="255.255.255.0"
|
||||||
|
conf.wifi.accessPoint.net.gateway="192.168.111.1"
|
||||||
end
|
end
|
||||||
-- These apply only when connecting to a router as a client
|
-- These apply only when connecting to a router as a client
|
||||||
if (conf.wifi.mode == wifi.STATION) or (conf.wifi.mode == wifi.STATIONAP) then
|
if (conf.wifi.mode == wifi.STATION) or (conf.wifi.mode == wifi.STATIONAP) then
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
-- flush() and for closing the connection.
|
-- flush() and for closing the connection.
|
||||||
-- Author: Philip Gladstone, Marcos Kirsch
|
-- Author: Philip Gladstone, Marcos Kirsch
|
||||||
|
|
||||||
BufferedConnection = {}
|
local BufferedConnection = {}
|
||||||
|
|
||||||
-- parameter is the nodemcu-firmware connection
|
-- parameter is the nodemcu-firmware connection
|
||||||
function BufferedConnection:new(connection)
|
function BufferedConnection:new(connection)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ return function(connection, code, extension, isGzipped, extraHeaders)
|
|||||||
-- A few MIME types. Keep list short. If you need something that is missing, let's add it.
|
-- 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",
|
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"}
|
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
|
if mt[ext] then return mt[ext] else return "application/octet-stream" end
|
||||||
end
|
end
|
||||||
|
|
||||||
local mimeType = getMimeType(extension)
|
local mimeType = getMimeType(extension)
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ local function uri_decode(input)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function parseArgs(args)
|
local function parseArgs(args)
|
||||||
local r = {}; i=1
|
local r = {}
|
||||||
|
local i = 1
|
||||||
if args == nil or args == "" then return r end
|
if args == nil or args == "" then return r end
|
||||||
for arg in string.gmatch(args, "([^&]+)") do
|
for arg in string.gmatch(args, "([^&]+)") do
|
||||||
local name, value = string.match(arg, "(.*)=(.*)")
|
local name, value = string.match(arg, "(.*)=(.*)")
|
||||||
@@ -46,6 +47,10 @@ local function getRequestData(payload)
|
|||||||
local requestData
|
local requestData
|
||||||
return function ()
|
return function ()
|
||||||
--print("Getting Request Data")
|
--print("Getting Request Data")
|
||||||
|
-- for backward compatibility before v2.1
|
||||||
|
if (sjson == nil) then
|
||||||
|
sjson = cjson
|
||||||
|
end
|
||||||
if requestData then
|
if requestData then
|
||||||
return requestData
|
return requestData
|
||||||
else
|
else
|
||||||
@@ -60,7 +65,7 @@ local function getRequestData(payload)
|
|||||||
--print("body = [" .. body .. "]")
|
--print("body = [" .. body .. "]")
|
||||||
if mimeType == "application/json" then
|
if mimeType == "application/json" then
|
||||||
--print("JSON: " .. body)
|
--print("JSON: " .. body)
|
||||||
requestData = cjson.decode(body)
|
requestData = sjson.decode(body)
|
||||||
elseif mimeType == "application/x-www-form-urlencoded" then
|
elseif mimeType == "application/x-www-form-urlencoded" then
|
||||||
requestData = parseFormData(body)
|
requestData = parseFormData(body)
|
||||||
else
|
else
|
||||||
@@ -79,7 +84,7 @@ local function parseUri(uri)
|
|||||||
|
|
||||||
if uri == nil then return r end
|
if uri == nil then return r end
|
||||||
if uri == "/" then uri = "/index.html" end
|
if uri == "/" then uri = "/index.html" end
|
||||||
questionMarkPos, b, c, d, e, f = uri:find("?")
|
local questionMarkPos, b, c, d, e, f = uri:find("?")
|
||||||
if questionMarkPos == nil then
|
if questionMarkPos == nil then
|
||||||
r.file = uri:sub(1, questionMarkPos)
|
r.file = uri:sub(1, questionMarkPos)
|
||||||
r.args = {}
|
r.args = {}
|
||||||
@@ -111,6 +116,7 @@ return function (request)
|
|||||||
if not e then return nil end
|
if not e then return nil end
|
||||||
local line = request:sub(1, e - 1)
|
local line = request:sub(1, e - 1)
|
||||||
local r = {}
|
local r = {}
|
||||||
|
local _, i
|
||||||
_, i, r.method, r.request = line:find("^([A-Z]+) (.-) HTTP/[1-9]+.[0-9]+$")
|
_, i, r.method, r.request = line:find("^([A-Z]+) (.-) HTTP/[1-9]+.[0-9]+$")
|
||||||
if not (r.method and r.request) then
|
if not (r.method and r.request) then
|
||||||
--print("invalid request: ")
|
--print("invalid request: ")
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ wifi.setmode(conf.wifi.mode)
|
|||||||
if (conf.wifi.mode == wifi.SOFTAP) or (conf.wifi.mode == wifi.STATIONAP) then
|
if (conf.wifi.mode == wifi.SOFTAP) or (conf.wifi.mode == wifi.STATIONAP) then
|
||||||
print('AP MAC: ',wifi.ap.getmac())
|
print('AP MAC: ',wifi.ap.getmac())
|
||||||
wifi.ap.config(conf.wifi.accessPoint.config)
|
wifi.ap.config(conf.wifi.accessPoint.config)
|
||||||
wifi.ap.setip(conf.wifi.accessPoint.ip)
|
wifi.ap.setip(conf.wifi.accessPoint.net)
|
||||||
end
|
end
|
||||||
|
|
||||||
if (conf.wifi.mode == wifi.STATION) or (conf.wifi.mode == wifi.STATIONAP) then
|
if (conf.wifi.mode == wifi.STATION) or (conf.wifi.mode == wifi.STATIONAP) then
|
||||||
print('Client MAC: ',wifi.sta.getmac())
|
print('Client MAC: ',wifi.sta.getmac())
|
||||||
wifi.sta.config(conf.wifi.station.ssid, conf.wifi.station.pwd, 1)
|
wifi.sta.config(conf.wifi.station)
|
||||||
end
|
end
|
||||||
|
|
||||||
print('chip: ',node.chipid())
|
print('chip: ',node.chipid())
|
||||||
|
|||||||
@@ -61,19 +61,19 @@ return function (port)
|
|||||||
uri.args = {code = 400, errorString = "Bad Request", logFunction = log}
|
uri.args = {code = 400, errorString = "Bad Request", logFunction = log}
|
||||||
fileServeFunction = dofile("httpserver-error.lc")
|
fileServeFunction = dofile("httpserver-error.lc")
|
||||||
else
|
else
|
||||||
local fileExists = file.open(uri.file, "r")
|
local fileExists = false
|
||||||
file.close()
|
|
||||||
|
|
||||||
if not fileExists then
|
if not file.exists(uri.file) then
|
||||||
|
-- print(uri.file .. " not found, checking gz version...")
|
||||||
-- gzip check
|
-- gzip check
|
||||||
fileExists = file.open(uri.file .. ".gz", "r")
|
if file.exists(uri.file .. ".gz") then
|
||||||
file.close()
|
|
||||||
|
|
||||||
if fileExists then
|
|
||||||
-- print("gzip variant exists, serving that one")
|
-- print("gzip variant exists, serving that one")
|
||||||
uri.file = uri.file .. ".gz"
|
uri.file = uri.file .. ".gz"
|
||||||
uri.isGzipped = true
|
uri.isGzipped = true
|
||||||
|
fileExists = true
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
fileExists = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if not fileExists then
|
if not fileExists then
|
||||||
|
|||||||
Reference in New Issue
Block a user