test_gzip.lua 11 KB

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