如何在OpenWRT/uhttpd上从Lua中读取POST数据

我正在OpenWRT上使用Lua和uhttpd,尝试编写自己的门户以捕获自定义嵌入式作业的表单数据。

对于这项工作,我不需要路由器和LUCI等内容,尽管我已经浏览了现有的Lua脚本,但没有任何突破。

我对uhttpd如何将POST数据放入Lua脚本感到困惑。这是如何发生的?在Lua脚本中访问的是哪个/哪些POST和GET变量?

(在PHP中,这是$_POST、$_GET或php://input,在Ruby on Rails中是请求对象,在Python中是cgi.FieldStorage()或request.POST…那么在Lua/uhttpd上是什么?)

这是一个简单的示例脚本。

前端/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>

后端/cgi-bin/luascripts/processform.lua:

-- 有些神奇的东西将POST数据带入电子邮件变量中(这是如何发生的?)
-- email = 'joe@somecompany.com'

output = [[
Hello {email}
]]

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

浏览器输出:

Hello joe@somecompany.com

对于这个过程的任何见解都将是惊人的,谢谢!

点赞
用户204011
用户204011

你可能确实希望使用 Luci,或至少看一看 Luci 是如何做的。

POST 数据在请求体中。Luci 创建了一个ltn12 支持的源来读取它,并将其传递给 http.Request 构造函数CGI 也是一样)。

Request 类 调用 protocol.parse_message_body,它做了大部分工作。它将结果存储在 Request 的 params 字段中。然后您可以使用熟悉的 formvalue 方法来访问它们(源码 - 您可以看到第一个调用调用了我们之前看到的 _parse_input)。

2015-12-18 08:27:56
用户3115984
用户3115984

Lua 可以分别处理 HTTP header 和 POST content

在 Lua 中,HTTP header 和 POST content 被分别处理。HTTP header 会被加载为环境变量,而 POST content 会在 Lua 脚本执行后像交互式 shell 一样被发送进来。

因此,可以使用 os.getenv() 或者 OpenWRT 上的 nixio.getenv() 来获取 HTTP header,比如 HTTP_USER_AGENT

以下是一个读取 HTTP headers 并打印 POST content 的 Lua CGI 脚本:

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"))

执行后输出的结果类似于以下的格式:

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

需要注意的是,uhttpd 会代表 CGI 脚本向浏览器输出 HTTP headers,包括 Content-Type,该 header 会匹配 CGI 脚本的文件扩展名,所以 .json 文件会有 Content-Type: application/json header,而 .html 文件会有 Content-Type: text/html header。

2016-01-09 16:54:54