简体   繁体   中英

How to read POST from Lua on OpenWRT/uhttpd

I'm using Lua on uhttpd on OpenWRT, trying to write my own portal to capture form data for a custom embedded job.

I don't need the router and LUCI stuff for this job, though I've trolled through the existing Lua scripts without any breakthroughs.

I'm confused about how uhttpd puts POST data into the Lua scripts. How does that happen? What is/are the POST and GET variable(s) that I access in the resulting Lua script?

(in PHP, this is $_POST, $_GET, or php://input, ruby on rails is the request object, python has cgi.FieldStorage() or request.POST... what is it on Lua/uhttpd?)

Here is a simple example script.

Front end /index.html:

<!DOCTYPE html>
<html>
<body>
<form action="/cgi/luascripts/processform.lua" method="post">
  <input type="email" name="email" placeholder="email@example.com" />
  <input type="submit" value="submit" />
</form>
</body>
</html>

Back end /cgi-bin/luascripts/processform.lua:

-- some magic happens to bring POST data into email variable (how does this happen?)
-- email = 'joe@somecompany.com'

output = [[
Hello {email}
]]

output = output:gsub("{email}", email)
print(output)

Browser Output:

Hello joe@somecompany.com

Any insight into this process would be amazing, thank you!

You probably do want Luci, or at least to take a look at how Luci does it.

POST data is in the body of the request. Luci creates a ltn12 compatible source to read it and passes it to the http.Request constructor ( same with CGI ).

The Request class calls protocol.parse_message_body which does most of the work. It stores the results in the params field of the Request. You can then access them with the familiar formvalue method ( source - you can see that the first call calls _parse_input that we saw earlier).

At its core, HTTP headers and POST content come in separately into Lua. The HTTP Headers are loaded as environment variables and the POST content is sent in as if by interactive shell into the Lua script after it has run.

Therefore, you can grab an HTTP header such as HTTP_USER_AGENT using os.getenv() or nixio.getenv() on OpenWRT.

A Lua CGI script that reads HTTP headers and prints POST content looks like this:

require "nixio"

-- prepare the browser for content:
print("\r")

-- print http headers
http_headers = nixio.getenv()
for k,v in pairs(http_headers) do
  print(k, v)
end

-- print POST output
print(io.read("*all"))

The resulting output will look something like this:

HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
SCRIPT_NAME /cgi-bin/test.htm
QUERY_STRING    parm1=val&parm2=val2
HTTP_ACCEPT_ENCODING    gzip, deflate
SERVER_ADDR 192.168.1.1
GATEWAY_INTERFACE   CGI/1.1
HTTP_AUTHORIZATION  
CONTENT_LENGTH  23
SERVER_PORT 80
SCRIPT_FILENAME /www/cgi-bin/test.htm
REQUEST_URI /cgi-bin/test.htm?parm1=val&parm2=val2
...
DOCUMENT_ROOT   /www
CONTENT_TYPE    application/x-www-form-urlencoded
HTTP_CONNECTION keep-alive
HTTP_USER_AGENT Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36
HTTP_ACCEPT_LANGUAGE    en-us
REQUEST_METHOD  POST

test=value&test1=value1

It is useful to note that uhttpd will output HTTP headers to the browser on behalf of the CGI script, including a Content-Type that matches the file extension of the CGI script. Therefore a .json will have a Content-Type: application/json header and a .html file will have a Content-Type: text/html header.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM