main.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. -- LuaTools需要PROJECT和VERSION这两个信息
  2. PROJECT = "httpdemo"
  3. VERSION = "1.0.0"
  4. --[[
  5. 本demo需要http库, 大部分能联网的设备都具有这个库
  6. http也是内置库, 无需require
  7. 1. 如需上传大文件,请使用 httpplus 库, 对应demo/httpplus
  8. 2.
  9. ]]
  10. -- sys库是标配
  11. _G.sys = require("sys")
  12. --[[特别注意, 使用http库需要下列语句]]
  13. _G.sysplus = require("sysplus")
  14. sys.taskInit(function()
  15. -----------------------------
  16. -- 统一联网函数, 可自行删减
  17. ----------------------------
  18. if wlan and wlan.connect then
  19. -- wifi 联网, ESP32系列均支持
  20. local ssid = "luatos1234"
  21. local password = "12341234"
  22. log.info("wifi", ssid, password)
  23. wlan.init()
  24. wlan.setMode(wlan.STATION)
  25. wlan.connect(ssid, password, 1)
  26. local result, data = sys.waitUntil("IP_READY", 30000)
  27. log.info("wlan", "IP_READY", result, data)
  28. device_id = wlan.getMac()
  29. elseif mobile then
  30. device_id = mobile.imei()
  31. log.info("ipv6", mobile.ipv6(true))
  32. sys.waitUntil("IP_READY", 30000)
  33. elseif http then
  34. sys.waitUntil("IP_READY")
  35. else
  36. while 1 do
  37. sys.wait(1000)
  38. log.info("http", "当前固件未包含http库")
  39. end
  40. end
  41. log.info("已联网")
  42. sys.publish("net_ready")
  43. end)
  44. function demo_http_get()
  45. -- 最普通的Http GET请求
  46. local code, headers, body = http.request("GET", "https://www.air32.cn/").wait()
  47. log.info("http.get", code, headers, body)
  48. local code, headers, body = http.request("GET", "https://mirrors6.tuna.tsinghua.edu.cn/", nil, nil, {ipv6=true}).wait()
  49. log.info("http.get", code, headers, body)
  50. sys.wait(100)
  51. local code, headers, body = http.request("GET", "https://www.luatos.com/").wait()
  52. log.info("http.get", code, headers, body)
  53. -- 按需打印
  54. -- code 响应值, 若大于等于 100 为服务器响应, 小于的均为错误代码
  55. -- headers是个table, 一般作为调试数据存在
  56. -- body是字符串. 注意lua的字符串是带长度的byte[]/char*, 是可以包含不可见字符的
  57. -- log.info("http", code, json.encode(headers or {}), #body > 512 and #body or body)
  58. end
  59. function demo_http_post_json()
  60. -- POST request 演示
  61. local req_headers = {}
  62. req_headers["Content-Type"] = "application/json"
  63. local body = json.encode({name="LuatOS"})
  64. local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date",
  65. req_headers,
  66. body -- POST请求所需要的body, string, zbuff, file均可
  67. ).wait()
  68. log.info("http.post", code, headers, body)
  69. end
  70. function demo_http_post_form()
  71. -- POST request 演示
  72. local req_headers = {}
  73. req_headers["Content-Type"] = "application/x-www-form-urlencoded"
  74. local params = {
  75. ABC = "123",
  76. DEF = 345
  77. }
  78. local body = ""
  79. for k, v in pairs(params) do
  80. body = body .. tostring(k) .. "=" .. tostring(v):urlEncode() .. "&"
  81. end
  82. local code, headers, body = http.request("POST","http://echohttp.wendal.cn/post",
  83. req_headers,
  84. body -- POST请求所需要的body, string, zbuff, file均可
  85. ).wait()
  86. log.info("http.post.form", code, headers, body)
  87. end
  88. -- local function http_download_callback(content_len,body_len,userdata)
  89. -- print("http_download_callback",content_len,body_len,userdata)
  90. -- end
  91. -- local http_userdata = "123456789"
  92. function demo_http_download()
  93. -- POST and download, task内的同步操作
  94. local opts = {} -- 额外的配置项
  95. opts["dst"] = "/data.bin" -- 下载路径,可选
  96. opts["timeout"] = 30000 -- 超时时长,单位ms,可选
  97. -- opts["adapter"] = socket.ETH0 -- 使用哪个网卡,可选
  98. -- opts["callback"] = http_download_callback
  99. -- opts["userdata"] = http_userdata
  100. for k, v in pairs(opts) do
  101. print("opts",k,v)
  102. end
  103. local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date",
  104. {}, -- 请求所添加的 headers, 可以是nil
  105. "",
  106. opts
  107. ).wait()
  108. log.info("http.post", code, headers, body) -- 只返回code和headers
  109. -- local f = io.open("/data.bin", "rb")
  110. -- if f then
  111. -- local data = f:read("*a")
  112. -- log.info("fs", "data", data, data:toHex())
  113. -- end
  114. -- GET request, 开个task让它自行执行去吧, 不管执行结果了
  115. sys.taskInit(http.request("GET","http://site0.cn/api/httptest/simple/time").wait)
  116. end
  117. function demo_http_post_file()
  118. -- -- POST multipart/form-data模式 上传文件---手动拼接
  119. local boundary = "----WebKitFormBoundary"..os.time()
  120. local req_headers = {
  121. ["Content-Type"] = "multipart/form-data; boundary="..boundary,
  122. }
  123. local body = "--"..boundary.."\r\n"..
  124. "Content-Disposition: form-data; name=\"uploadFile\"; filename=\"luatos_uploadFile_TEST01.txt\""..
  125. "\r\nContent-Type: text/plain\r\n\r\n"..
  126. "1111http_测试一二三四654zacc\r\n"..
  127. "--"..boundary
  128. log.info("headers: ", "\r\n"..json.encode(req_headers))
  129. log.info("body: ", "\r\n"..body)
  130. local code, headers, body = http.request("POST","http://airtest.openluat.com:2900/uploadFileToStatic",
  131. req_headers,
  132. body -- POST请求所需要的body, string, zbuff, file均可
  133. ).wait()
  134. log.info("http.post", code, headers, body)
  135. -- 也可用postMultipartFormData(url, params) 上传文件
  136. postMultipartFormData(
  137. "http://airtest.openluat.com:2900/uploadFileToStatic",
  138. {
  139. -- texts =
  140. -- {
  141. -- ["imei"] = "862991234567890",
  142. -- ["time"] = "20180802180345"
  143. -- },
  144. files =
  145. {
  146. ["uploadFile"] = "/luadb/luatos_uploadFile.txt",
  147. }
  148. }
  149. )
  150. end
  151. local function demo_http_get_gzip()
  152. -- 这里用 和风天气 的API做演示
  153. -- 这个API的响应, 总会gzip压缩过, 需要配合miniz库进行解压
  154. local code, headers, body = http.request("GET", "https://devapi.qweather.com/v7/weather/now?location=101010100&key=0e8c72015e2b4a1dbff1688ad54053de").wait()
  155. log.info("http.gzip", code)
  156. if code == 200 then
  157. local re = miniz.uncompress(body:sub(11), 0)
  158. log.info("和风天气", re)
  159. if re then
  160. local jdata = json.decode(re)
  161. log.info("jdata", jdata)
  162. if jdata then
  163. log.info("和风天气", jdata.code)
  164. if jdata.now then
  165. log.info("和风天气", "天气", jdata.now.text)
  166. log.info("和风天气", "温度", jdata.now.temp)
  167. end
  168. end
  169. end
  170. end
  171. end
  172. sys.taskInit(function()
  173. sys.wait(100)
  174. -- 打印一下支持的加密套件, 通常来说, 固件已包含常见的99%的加密套件
  175. -- if crypto.cipher_suites then
  176. -- log.info("cipher", "suites", json.encode(crypto.cipher_suites()))
  177. -- end
  178. -------------------------------------
  179. -------- HTTP 演示代码 --------------
  180. -------------------------------------
  181. sys.waitUntil("net_ready") -- 等联网
  182. while 1 do
  183. -- 演示GET请求
  184. demo_http_get()
  185. -- 表单提交
  186. -- demo_http_post_form()
  187. -- POST一个json字符串
  188. -- demo_http_post_json()
  189. -- 上传文件, mulitform形式
  190. -- demo_http_post_file()
  191. -- 文件下载
  192. -- demo_http_download()
  193. -- gzip压缩的响应, 以和风天气为例
  194. -- demo_http_get_gzip()
  195. sys.wait(1000)
  196. -- 打印一下内存状态
  197. log.info("sys", rtos.meminfo("sys"))
  198. log.info("lua", rtos.meminfo("lua"))
  199. sys.wait(600000)
  200. end
  201. end)
  202. ---- MultipartForm上传文件
  203. -- url string 请求URL地址
  204. -- req_headers table 请求头
  205. -- params table 需要传输的数据参数
  206. function postMultipartFormData(url, params)
  207. local boundary = "----WebKitFormBoundary"..os.time()
  208. local req_headers = {
  209. ["Content-Type"] = "multipart/form-data; boundary="..boundary,
  210. }
  211. local body = {}
  212. -- 解析拼接 body
  213. for k,v in pairs(params) do
  214. if k=="texts" then
  215. local bodyText = ""
  216. for kk,vv in pairs(v) do
  217. print(kk,vv)
  218. bodyText = bodyText.."--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"\r\n\r\n"..vv.."\r\n"
  219. end
  220. table.insert(body, bodyText)
  221. elseif k=="files" then
  222. local contentType =
  223. {
  224. txt = "text/plain", -- 文本
  225. jpg = "image/jpeg", -- JPG 格式图片
  226. jpeg = "image/jpeg", -- JPEG 格式图片
  227. png = "image/png", -- PNG 格式图片
  228. gif = "image/gif", -- GIF 格式图片
  229. html = "image/html", -- HTML
  230. json = "application/json" -- JSON
  231. }
  232. for kk,vv in pairs(v) do
  233. if type(vv) == "table" then
  234. for i=1, #vv do
  235. print(kk,vv[i])
  236. table.insert(body, "--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"; filename=\""..vv[i]:match("[^%/]+%w$").."\"\r\nContent-Type: "..contentType[vv[i]:match("%.(%w+)$")].."\r\n\r\n")
  237. table.insert(body, io.readFile(vv[i]))
  238. table.insert(body, "\r\n")
  239. end
  240. else
  241. print(kk,vv)
  242. table.insert(body, "--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"; filename=\""..vv:match("[^%/]+%w$").."\"\r\nContent-Type: "..contentType[vv:match("%.(%w+)$")].."\r\n\r\n")
  243. table.insert(body, io.readFile(vv))
  244. table.insert(body, "\r\n")
  245. end
  246. end
  247. end
  248. end
  249. table.insert(body, "--"..boundary.."--\r\n")
  250. body = table.concat(body)
  251. log.info("headers: ", "\r\n" .. json.encode(req_headers), type(body))
  252. log.info("body: " .. body:len() .. "\r\n" .. body)
  253. local code, headers, body = http.request("POST",url,
  254. req_headers,
  255. body
  256. ).wait()
  257. log.info("http.post", code, headers, body)
  258. end
  259. -- 用户代码已结束---------------------------------------------
  260. -- 结尾总是这一句
  261. sys.run()
  262. -- sys.run()之后后面不要加任何语句!!!!!