httpplus_app.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. --[[
  2. @module httpplus
  3. @summary httpplus应用功能模块
  4. @version 1.0
  5. @date 2025.08.06
  6. @author 马梦阳
  7. @usage
  8. 本文件为httpplus应用功能模块,核心业务逻辑为:基于不同的应用场景,演示httpplus扩展库的使用方式;
  9. http核心库和httpplus扩展库的区别如下:
  10. | 区别项 | http核心库 | httpplus扩展库 |
  11. | --------------------------------- | ------------------------------------------------------------------------- | ---------------------------- |
  12. | 文件上传 | 文件最大64KB | 只要内存够用,文件大小不限 |
  13. | 文件下载 | 支持,只要文件系统空间够用,文件大小不限 | 不支持 |
  14. | http header的key: value的限制 | 所有header的value总长度不能超过4KB,单个header的value长度不能超过1KB | 只要内存够用,header长度不限 |
  15. | 鉴权URL自动识别 | 不支持 | 支持 |
  16. | 接收到的body数据存储支持zbuff | 不支持 | 支持,可以直接传输给uart等库 |
  17. | 接收到的body数据存储到内存中 | 最大支持32KB | 只要内存够用,大小不限 |
  18. | chunk编码 | 支持 | 不支持 |
  19. 本文件没有对外接口,直接在main.lua中require "httpplus_app"就可以加载运行;
  20. ]]
  21. local httpplus = require "httpplus"
  22. -- 普通的http get请求功能演示
  23. -- 请求的body数据保存到内存变量中,在内存够用的情况下,长度不限
  24. -- timeout可以设置超时时间
  25. local function httpplus_app_get()
  26. local body
  27. -- https get请求https://httpbin.air32.cn/get网页内容
  28. -- 如果请求成功,请求的数据保存到response.body中
  29. local code, response = httpplus.request({url="https://httpbin.air32.cn/get"})
  30. log.info("httpplus_app_get1", code==200 and "success" or "error", code)
  31. if code==200 then
  32. log.info("httpplus_app_get1 headers", json.encode(response.headers or {}))
  33. body = response.body:query()
  34. log.info("httpplus_app_get1 body", body and (body:len()>512 and body:len() or body) or "nil")
  35. end
  36. -- http get请求http://httpbin.air32.cn/get网页内容,超时时间为3秒
  37. -- 请求超时时间为3秒,用户自己写代码时,不要照抄3秒,根据自己业务逻辑的需要设置合适的超时时间
  38. -- 如果请求成功,请求的数据保存到body中
  39. code, response = httpplus.request({url="http://httpbin.air32.cn/get", timeout=3})
  40. log.info("httpplus_app_get2", code==200 and "success" or "error", code)
  41. if code==200 then
  42. log.info("httpplus_app_get2 headers", json.encode(response.headers or {}))
  43. body = response.body:query()
  44. log.info("httpplus_app_get2 body", body and (body:len()>512 and body:len() or body) or "nil")
  45. end
  46. end
  47. -- http get下载压缩数据的功能演示
  48. local function httpplus_app_get_gzip()
  49. local body
  50. -- https get请求https://devapi.qweather.com/v7/weather/now?location=101010100&key=0e8c72015e2b4a1dbff1688ad54053de网页内容,超时时间为3秒
  51. -- 如果请求成功,请求的数据保存到response.body中
  52. local code, response = httpplus.request({url="https://devapi.qweather.com/v7/weather/now?location=101010100&key=0e8c72015e2b4a1dbff1688ad54053de"})
  53. log.info("httpplus_app_get_gzip", code==200 and "success" or "error", code)
  54. if code==200 then
  55. log.info("httpplus_app_get_gzip headers", json.encode(response.headers or {}))
  56. body = response.body:query()
  57. log.info("httpplus_app_get_gzip body", body and (body:len()>512 and body:len() or body) or "nil")
  58. end
  59. -- 如果请求成功
  60. if code == 200 then
  61. -- 从body的第11个字节开始解压缩
  62. local uncompress_data = miniz.uncompress(body:sub(11,-1), 0)
  63. if not uncompress_data then
  64. log.error("httpplus_app_get_gzip uncompress error")
  65. return
  66. end
  67. local json_data = json.decode(uncompress_data)
  68. if not json_data then
  69. log.error("httpplus_app_get_gzip json.decode error")
  70. return
  71. end
  72. log.info("httpplus_app_get_gzip json_data", json_data)
  73. log.info("httpplus_app_get_gzip", "和风天气", json_data.code)
  74. if json_data.now then
  75. log.info("httpplus_app_get_gzip", "和风天气", "天气", json_data.now.text)
  76. log.info("httpplus_app_get_gzip", "和风天气", "温度", json_data.now.temp)
  77. end
  78. end
  79. end
  80. -- http post提交表单数据功能演示
  81. local function httpplus_app_post_form()
  82. -- http post提交表单数据
  83. -- http://httpbin.air32.cn/post为回环测试服务器,服务器收到post提交的表单数据后,还会下发同样的表单数据给设备
  84. -- 如果请求成功,服务器应答的数据会保存到response.body中
  85. local code, response = httpplus.request(
  86. {
  87. url = "http://httpbin.air32.cn/post",
  88. forms = {username="LuatOS", password="123456"}
  89. })
  90. log.info("httpplus_app_post_form", code==200 and "success" or "error", code)
  91. if code==200 then
  92. log.info("httpplus_app_post_form headers", json.encode(response.headers or {}))
  93. local body = response.body:query()
  94. log.info("httpplus_app_post_form body", body and (body:len()>512 and body:len() or body) or "nil")
  95. end
  96. end
  97. -- http post提交json数据功能演示
  98. local function httpplus_app_post_json()
  99. local params = {
  100. username = "LuatOS",
  101. password = "123456"
  102. }
  103. -- http post提交json数据
  104. -- http://httpbin.air32.cn/post为回环测试服务器,服务器收到post提交的json数据后,还会下发同样的json数据给设备
  105. -- ["Content-Type"] = "application/json" 表示post提交的body数据格式为json格式的数据
  106. -- 如果请求成功,服务器应答的数据会保存到response.body中
  107. local code, response = httpplus.request(
  108. {
  109. method = "POST",
  110. url = "http://httpbin.air32.cn/post",
  111. headers = {["Content-Type"] = "application/json"},
  112. body = json.encode(params)
  113. })
  114. log.info("httpplus_app_post_json", code==200 and "success" or "error", code)
  115. if code==200 then
  116. log.info("httpplus_app_post_json headers", json.encode(response.headers or {}))
  117. local body = response.body:query()
  118. log.info("httpplus_app_post_json body", body and (body:len()>512 and body:len() or body) or "nil")
  119. end
  120. end
  121. -- http post提交纯文本数据功能演示
  122. local function httpplus_app_post_text()
  123. -- http post提交纯文本数据
  124. -- http://httpbin.air32.cn/post为回环测试服务器,服务器收到post提交的纯文本数据后,还会下发同样的纯文本数据给设备
  125. -- ["Content-Type"] = "text/plain" 表示post提交的body数据格式为纯文本格式的数据
  126. -- 如果请求成功,服务器应答的数据会保存到response.body中
  127. local code, response = httpplus.request(
  128. {
  129. method = "POST",
  130. url = "http://httpbin.air32.cn/post",
  131. headers = {["Content-Type"] = "text/plain"},
  132. body = "This is a raw text message from LuatOS device"
  133. })
  134. log.info("httpplus_app_post_text", code==200 and "success" or "error", code)
  135. if code==200 then
  136. log.info("httpplus_app_post_text headers", json.encode(response.headers or {}))
  137. local body = response.body:query()
  138. log.info("httpplus_app_post_text body", body and (body:len()>512 and body:len() or body) or "nil")
  139. end
  140. end
  141. -- http post提交xml数据功能演示
  142. local function httpplus_app_post_xml()
  143. -- [=[ 和 ]=] 之间是一个多行字符串
  144. local body = [=[
  145. <?xml version="1.0" encoding="UTF-8"?>
  146. <user>
  147. <name>LuatOS</name>
  148. <password>123456</password>
  149. </user>
  150. ]=]
  151. -- http post提交xml数据
  152. -- http://httpbin.air32.cn/post为回环测试服务器,服务器收到post提交的xml数据后,还会下发同样的xml数据给设备
  153. -- ["Content-Type"] = "text/xml" 表示post提交的body数据格式为xml格式的数据
  154. -- 如果请求成功,服务器应答的数据会保存到response.body中
  155. local code, response = httpplus.request(
  156. {
  157. method = "POST",
  158. url = "http://httpbin.air32.cn/post",
  159. headers = {["Content-Type"] = "text/xml"},
  160. body = body
  161. })
  162. log.info("httpplus_app_post_xml", code==200 and "success" or "error", code)
  163. if code==200 then
  164. log.info("httpplus_app_post_xml headers", json.encode(response.headers or {}))
  165. body = response.body:query()
  166. log.info("httpplus_app_post_xml body", body and (body:len()>512 and body:len() or body) or "nil")
  167. end
  168. end
  169. -- http post提交原始二进制数据功能演示
  170. local function httpplus_app_post_binary()
  171. local body = io.readFile("/luadb/logo.jpg")
  172. -- http post提交原始二进制数据
  173. -- http://upload.air32.cn/api/upload/jpg为jpg图片上传测试服务器
  174. -- 此处将logo.jpg的原始二进制数据做为body上传到服务器
  175. -- 上传成功后,电脑上浏览器打开https://www.air32.cn/upload/data/jpg/,打开对应的测试日期目录,点击具体的测试时间照片,可以查看上传的照片
  176. -- ["Content-Type"] = "application/octet-stream" 表示post提交的body数据格式为原始二进制格式的数据
  177. -- 如果请求成功,服务器应答的数据会保存到response.body中
  178. local code, response = httpplus.request(
  179. {
  180. method = "POST",
  181. url = "http://upload.air32.cn/api/upload/jpg",
  182. headers = {["Content-Type"] = "application/octet-stream"},
  183. body = body
  184. })
  185. log.info("httpplus_app_post_binary", code==200 and "success" or "error", code)
  186. if code==200 then
  187. log.info("httpplus_app_post_binary headers", json.encode(response.headers or {}))
  188. body = response.body:query()
  189. log.info("httpplus_app_post_binary body", body and (body:len()>512 and body:len() or body) or "nil")
  190. end
  191. end
  192. -- http post文件上传功能演示
  193. local function httpplus_app_post_file()
  194. -- hhtplus.request接口支持单文件上传、多文件上传、单文本上传、多文本上传、单/多文本+单/多文件上传
  195. -- http://airtest.openluat.com:2900/uploadFileToStatic 仅支持单文件上传,并且上传的文件name必须使用"uploadFile"
  196. -- 所以此处仅演示了单文件上传功能,并且"uploadFile"不能改成其他名字,否则会出现上传失败的应答
  197. -- 如果你自己的http服务支持更多类型的文本/文件混合上传,可以打开注释自行验证
  198. local code, response = httpplus.request(
  199. {
  200. url = "http://airtest.openluat.com:2900/uploadFileToStatic",
  201. files =
  202. {
  203. ["uploadFile"] = "/luadb/logo.jpg",
  204. -- ["logo1.jpg"] = "/luadb/logo.jpg",
  205. },
  206. -- forms =
  207. -- {
  208. -- ["username"] = "LuatOS",
  209. -- ["password"] = "123456",
  210. -- },
  211. })
  212. log.info("httpplus_app_post_file", code==200 and "success" or "error", code)
  213. if code==200 then
  214. log.info("httpplus_app_post_file headers", json.encode(response.headers or {}))
  215. local body = response.body:query()
  216. log.info("httpplus_app_post_file body", body and (body:len()>512 and body:len() or body) or "nil")
  217. end
  218. end
  219. -- http app task 的任务处理函数
  220. local function httpplus_app_task_func()
  221. while true do
  222. -- 如果当前时间点设置的默认网卡还没有连接成功,一直在这里循环等待
  223. while not socket.adapter(socket.dft()) do
  224. log.warn("httpplus_app_task_func", "wait IP_READY", socket.dft())
  225. -- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"
  226. -- 或者等待1秒超时退出阻塞等待状态;
  227. -- 注意:此处的1000毫秒超时不要修改的更长;
  228. -- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡
  229. -- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配
  230. -- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())
  231. sys.waitUntil("IP_READY", 1000)
  232. end
  233. -- 检测到了IP_READY消息
  234. log.info("httpplus_app_task_func", "recv IP_READY", socket.dft())
  235. -- 普通的http get请求功能演示
  236. httpplus_app_get()
  237. -- http get下载压缩数据的功能演示
  238. httpplus_app_get_gzip()
  239. -- http post提交表单数据功能演示
  240. httpplus_app_post_form()
  241. -- -- http post提交json数据功能演示
  242. httpplus_app_post_json()
  243. -- http post提交纯文本数据功能演示
  244. httpplus_app_post_text()
  245. -- http post提交xml数据功能演示
  246. httpplus_app_post_xml()
  247. -- http post提交原始二进制数据功能演示
  248. httpplus_app_post_binary()
  249. -- http post文件上传功能演示
  250. httpplus_app_post_file()
  251. -- 60秒之后,循环测试
  252. sys.wait(60000)
  253. end
  254. end
  255. --创建并且启动一个task
  256. --运行这个task的处理函数httpplus_app_task_func
  257. sys.taskInit(httpplus_app_task_func)