Преглед изворни кода

change: demo/http,分拆成多个文件

Wendal Chen пре 9 месеци
родитељ
комит
ac7518f3b5

+ 6 - 257
demo/http/main.lua

@@ -16,209 +16,17 @@ _G.sys = require("sys")
 --[[特别注意, 使用http库需要下列语句]]
 _G.sysplus = require("sysplus")
 
+require "netready"
+require "test_get"
+require "test_post"
+require "test_download"
+require "test_fileupload"
+require "test_gzip"
 
--- Air780E的AT固件默认会为开机键防抖, 导致部分用户刷机很麻烦
-if rtos.bsp() == "EC618" and pm and pm.PWK_MODE then
-    pm.power(pm.PWK_MODE, false)
-end
 
 
 sys.taskInit(function()
-    -----------------------------
-    -- 统一联网函数, 可自行删减
-    ----------------------------
-    if wlan and wlan.connect then
-        -- wifi 联网, ESP32系列均支持
-        local ssid = "luatos1234"
-        local password = "12341234"
-        log.info("wifi", ssid, password)
-        -- TODO 改成esptouch配网
-        -- LED = gpio.setup(12, 0, gpio.PULLUP)
-        wlan.init()
-        wlan.setMode(wlan.STATION)
-        wlan.connect(ssid, password, 1)
-        local result, data = sys.waitUntil("IP_READY", 30000)
-        log.info("wlan", "IP_READY", result, data)
-        device_id = wlan.getMac()
-    elseif rtos.bsp() == "AIR105" then
-        -- w5500 以太网, 当前仅Air105支持
-        w5500.init(spi.HSPI_0, 24000000, pin.PC14, pin.PC01, pin.PC00)
-        w5500.config() --默认是DHCP模式
-        w5500.bind(socket.ETH0)
-        -- LED = gpio.setup(62, 0, gpio.PULLUP)
-        sys.wait(1000)
-        -- TODO 获取mac地址作为device_id
-    elseif mobile then
-        -- Air780E/Air600E系列
-        --mobile.simid(2)
-        -- LED = gpio.setup(27, 0, gpio.PULLUP)
-        device_id = mobile.imei()
-        log.info("ipv6", mobile.ipv6(true))
-        sys.waitUntil("IP_READY", 30000)
-    elseif http then
-        sys.waitUntil("IP_READY")
-    else
-        while 1 do
-            sys.wait(1000)
-            log.info("http", "当前固件未包含http库")
-        end
-    end
-    log.info("已联网")
-    sys.publish("net_ready")
-end)
-
-function demo_http_get()
-    -- 最普通的Http GET请求
-    local code, headers, body = http.request("GET", "https://www.air32.cn/").wait()
-    log.info("http.get", code, headers, body)
-    local code, headers, body = http.request("GET", "https://mirrors6.tuna.tsinghua.edu.cn/", nil, nil, {ipv6=true}).wait()
-    log.info("http.get", code, headers, body)
     sys.wait(100)
-    local code, headers, body = http.request("GET", "https://www.luatos.com/").wait()
-    log.info("http.get", code, headers, body)
-
-    -- 按需打印
-    -- code 响应值, 若大于等于 100 为服务器响应, 小于的均为错误代码
-    -- headers是个table, 一般作为调试数据存在
-    -- body是字符串. 注意lua的字符串是带长度的byte[]/char*, 是可以包含不可见字符的
-    -- log.info("http", code, json.encode(headers or {}), #body > 512 and #body or body)
-end
-
-function demo_http_post_json()
-    -- POST request 演示
-    local req_headers = {}
-    req_headers["Content-Type"] = "application/json"
-    local body = json.encode({name="LuatOS"})
-    local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date", 
-            req_headers,
-            body -- POST请求所需要的body, string, zbuff, file均可
-    ).wait()
-    log.info("http.post", code, headers, body)
-end
-
-function demo_http_post_form()
-    -- POST request 演示
-    local req_headers = {}
-    req_headers["Content-Type"] = "application/x-www-form-urlencoded"
-    local params = {
-        ABC = "123",
-        DEF = 345
-    }
-    local body = ""
-    for k, v in pairs(params) do
-        body = body .. tostring(k) .. "=" .. tostring(v):urlEncode() .. "&"
-    end
-    local code, headers, body = http.request("POST","http://echohttp.wendal.cn/post", 
-            req_headers,
-            body -- POST请求所需要的body, string, zbuff, file均可
-    ).wait()
-    log.info("http.post.form", code, headers, body)
-end
-
--- local function http_download_callback(content_len,body_len,userdata)
---     print("http_download_callback",content_len,body_len,userdata)
--- end
-
--- local http_userdata = "123456789"
-
-function demo_http_download()
-
-    -- POST and download, task内的同步操作
-    local opts = {}                 -- 额外的配置项
-    opts["dst"] = "/data.bin"       -- 下载路径,可选
-    opts["timeout"] = 30000         -- 超时时长,单位ms,可选
-    -- opts["adapter"] = socket.ETH0  -- 使用哪个网卡,可选
-    -- opts["callback"] = http_download_callback
-    -- opts["userdata"] = http_userdata
-
-    for k, v in pairs(opts) do
-        print("opts",k,v)
-    end
-    
-    local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date",
-            {}, -- 请求所添加的 headers, 可以是nil
-            "", 
-            opts
-    ).wait()
-    log.info("http.post", code, headers, body) -- 只返回code和headers
-
-    -- local f = io.open("/data.bin", "rb")
-    -- if f then
-    --     local data = f:read("*a")
-    --     log.info("fs", "data", data, data:toHex())
-    -- end
-    
-    -- GET request, 开个task让它自行执行去吧, 不管执行结果了
-    sys.taskInit(http.request("GET","http://site0.cn/api/httptest/simple/time").wait)
-end
-
-function demo_http_post_file()
-        -- -- POST multipart/form-data模式 上传文件---手动拼接
-        local boundary = "----WebKitFormBoundary"..os.time()
-        local req_headers = {
-            ["Content-Type"] = "multipart/form-data; boundary="..boundary,
-        }
-        local body = "--"..boundary.."\r\n"..
-                     "Content-Disposition: form-data; name=\"uploadFile\"; filename=\"luatos_uploadFile_TEST01.txt\""..
-                     "\r\nContent-Type: text/plain\r\n\r\n"..
-                     "1111http_测试一二三四654zacc\r\n"..
-                     "--"..boundary
-
-        log.info("headers: ", "\r\n"..json.encode(req_headers))
-        log.info("body: ", "\r\n"..body)
-        local code, headers, body = http.request("POST","http://airtest.openluat.com:2900/uploadFileToStatic",
-                req_headers,
-                body -- POST请求所需要的body, string, zbuff, file均可
-        ).wait()
-        log.info("http.post", code, headers, body)
-
-        -- 也可用postMultipartFormData(url, params) 上传文件
-        postMultipartFormData(
-            "http://airtest.openluat.com:2900/uploadFileToStatic",
-            {
-                -- texts = 
-                -- {
-                --     ["imei"] = "862991234567890",
-                --     ["time"] = "20180802180345"
-                -- },
-                
-                files =
-                {
-                    ["uploadFile"] = "/luadb/luatos_uploadFile.txt",
-                }
-            }
-        )
-end
-
-
-local function demo_http_get_gzip()
-    -- 这里用 和风天气 的API做演示
-    -- 这个API的响应, 总会gzip压缩过, 需要配合miniz库进行解压
-    local code, headers, body = http.request("GET", "https://devapi.qweather.com/v7/weather/now?location=101010100&key=0e8c72015e2b4a1dbff1688ad54053de").wait()
-    log.info("http.gzip", code)
-    if code == 200 then
-        local re = miniz.uncompress(body:sub(11), 0)
-        log.info("和风天气", re)
-        if re then
-            local jdata = json.decode(re)
-            log.info("jdata", jdata)
-            if jdata then
-                log.info("和风天气", jdata.code)
-                if jdata.now then
-                    log.info("和风天气", "天气", jdata.now.text)
-                    log.info("和风天气", "温度", jdata.now.temp)
-                end
-            end
-        end
-    end
-end
-
-sys.taskInit(function()
-    sys.wait(100)
-    -- 打印一下支持的加密套件, 通常来说, 固件已包含常见的99%的加密套件
-    -- if crypto.cipher_suites then
-    --     log.info("cipher", "suites", json.encode(crypto.cipher_suites()))
-    -- end
 
     -------------------------------------
     -------- HTTP 演示代码 --------------
@@ -247,65 +55,6 @@ sys.taskInit(function()
     end
 end)
 
----- MultipartForm上传文件
--- url string 请求URL地址
--- req_headers table 请求头
--- params table 需要传输的数据参数
-function postMultipartFormData(url, params)
-    local boundary = "----WebKitFormBoundary"..os.time()
-    local req_headers = {
-        ["Content-Type"] = "multipart/form-data; boundary="..boundary,
-    }
-    local body = {}
-
-    -- 解析拼接 body
-    for k,v in pairs(params) do
-        if k=="texts" then
-            local bodyText = ""
-            for kk,vv in pairs(v) do
-                print(kk,vv)
-                bodyText = bodyText.."--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"\r\n\r\n"..vv.."\r\n"
-            end
-            table.insert(body, bodyText)
-        elseif k=="files" then
-            local contentType =
-            {
-                txt = "text/plain",             -- 文本
-                jpg = "image/jpeg",             -- JPG 格式图片
-                jpeg = "image/jpeg",            -- JPEG 格式图片
-                png = "image/png",              -- PNG 格式图片   
-                gif = "image/gif",              -- GIF 格式图片
-                html = "image/html",            -- HTML
-                json = "application/json"       -- JSON
-            }
-            
-            for kk,vv in pairs(v) do
-                if type(vv) == "table" then
-                    for i=1, #vv do
-                        print(kk,vv[i])
-                        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")
-                        table.insert(body, io.readFile(vv[i]))
-                        table.insert(body, "\r\n")
-                    end
-                else
-                    print(kk,vv)
-                    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")
-                    table.insert(body, io.readFile(vv))
-                    table.insert(body, "\r\n")
-                end
-            end
-        end
-    end 
-    table.insert(body, "--"..boundary.."--\r\n")
-    body = table.concat(body)
-    log.info("headers: ", "\r\n" .. json.encode(req_headers), type(body))
-    log.info("body: " .. body:len() .. "\r\n" .. body)
-    local code, headers, body = http.request("POST",url,
-            req_headers,
-            body
-    ).wait()   
-    log.info("http.post", code, headers, body)
-end
 
 
 -- 用户代码已结束---------------------------------------------

+ 44 - 0
demo/http/netready.lua

@@ -0,0 +1,44 @@
+
+sys.taskInit(function()
+    -----------------------------
+    -- 统一联网函数, 可自行删减
+    ----------------------------
+    if wlan and wlan.connect then
+        -- wifi 联网, ESP32系列均支持
+        local ssid = "luatos1234"
+        local password = "12341234"
+        log.info("wifi", ssid, password)
+        -- TODO 改成esptouch配网
+        -- LED = gpio.setup(12, 0, gpio.PULLUP)
+        wlan.init()
+        wlan.setMode(wlan.STATION)
+        wlan.connect(ssid, password, 1)
+        local result, data = sys.waitUntil("IP_READY", 30000)
+        log.info("wlan", "IP_READY", result, data)
+        device_id = wlan.getMac()
+    elseif rtos.bsp() == "AIR105" then
+        -- w5500 以太网, 当前仅Air105支持
+        w5500.init(spi.HSPI_0, 24000000, pin.PC14, pin.PC01, pin.PC00)
+        w5500.config() --默认是DHCP模式
+        w5500.bind(socket.ETH0)
+        -- LED = gpio.setup(62, 0, gpio.PULLUP)
+        sys.wait(1000)
+        -- TODO 获取mac地址作为device_id
+    elseif mobile then
+        -- Air780E/Air600E系列
+        --mobile.simid(2)
+        -- LED = gpio.setup(27, 0, gpio.PULLUP)
+        device_id = mobile.imei()
+        log.info("ipv6", mobile.ipv6(true))
+        sys.waitUntil("IP_READY", 30000)
+    elseif http then
+        sys.waitUntil("IP_READY")
+    else
+        while 1 do
+            sys.wait(1000)
+            log.info("http", "当前固件未包含http库")
+        end
+    end
+    log.info("已联网")
+    sys.publish("net_ready")
+end)

+ 31 - 0
demo/http/test_download.lua

@@ -0,0 +1,31 @@
+
+function demo_http_download()
+
+    -- POST and download, task内的同步操作
+    local opts = {}                 -- 额外的配置项
+    opts["dst"] = "/data.bin"       -- 下载路径,可选
+    opts["timeout"] = 30000         -- 超时时长,单位ms,可选
+    -- opts["adapter"] = socket.ETH0  -- 使用哪个网卡,可选
+    -- opts["callback"] = http_download_callback
+    -- opts["userdata"] = http_userdata
+
+    for k, v in pairs(opts) do
+        print("opts",k,v)
+    end
+    
+    local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date",
+            {}, -- 请求所添加的 headers, 可以是nil
+            "", 
+            opts
+    ).wait()
+    log.info("http.post", code, headers, body) -- 只返回code和headers
+
+    -- local f = io.open("/data.bin", "rb")
+    -- if f then
+    --     local data = f:read("*a")
+    --     log.info("fs", "data", data, data:toHex())
+    -- end
+    
+    -- GET request, 开个task让它自行执行去吧, 不管执行结果了
+    sys.taskInit(http.request("GET","http://site0.cn/api/httptest/simple/time").wait)
+end

+ 100 - 0
demo/http/test_fileupload.lua

@@ -0,0 +1,100 @@
+
+function demo_http_post_file()
+        -- -- POST multipart/form-data模式 上传文件---手动拼接
+        local boundary = "----WebKitFormBoundary"..os.time()
+        local req_headers = {
+            ["Content-Type"] = "multipart/form-data; boundary="..boundary,
+        }
+        local body = "--"..boundary.."\r\n"..
+                     "Content-Disposition: form-data; name=\"uploadFile\"; filename=\"luatos_uploadFile_TEST01.txt\""..
+                     "\r\nContent-Type: text/plain\r\n\r\n"..
+                     "1111http_测试一二三四654zacc\r\n"..
+                     "--"..boundary
+
+        log.info("headers: ", "\r\n"..json.encode(req_headers))
+        log.info("body: ", "\r\n"..body)
+        local code, headers, body = http.request("POST","http://airtest.openluat.com:2900/uploadFileToStatic",
+                req_headers,
+                body -- POST请求所需要的body, string, zbuff, file均可
+        ).wait()
+        log.info("http.post", code, headers, body)
+
+        -- 也可用postMultipartFormData(url, params) 上传文件
+        postMultipartFormData(
+            "http://airtest.openluat.com:2900/uploadFileToStatic",
+            {
+                -- texts = 
+                -- {
+                --     ["imei"] = "862991234567890",
+                --     ["time"] = "20180802180345"
+                -- },
+                
+                files =
+                {
+                    ["uploadFile"] = "/luadb/luatos_uploadFile.txt",
+                }
+            }
+        )
+end
+
+
+
+---- MultipartForm上传文件
+-- url string 请求URL地址
+-- req_headers table 请求头
+-- params table 需要传输的数据参数
+function postMultipartFormData(url, params)
+    local boundary = "----WebKitFormBoundary"..os.time()
+    local req_headers = {
+        ["Content-Type"] = "multipart/form-data; boundary="..boundary,
+    }
+    local body = {}
+
+    -- 解析拼接 body
+    for k,v in pairs(params) do
+        if k=="texts" then
+            local bodyText = ""
+            for kk,vv in pairs(v) do
+                print(kk,vv)
+                bodyText = bodyText.."--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"\r\n\r\n"..vv.."\r\n"
+            end
+            table.insert(body, bodyText)
+        elseif k=="files" then
+            local contentType =
+            {
+                txt = "text/plain",             -- 文本
+                jpg = "image/jpeg",             -- JPG 格式图片
+                jpeg = "image/jpeg",            -- JPEG 格式图片
+                png = "image/png",              -- PNG 格式图片   
+                gif = "image/gif",              -- GIF 格式图片
+                html = "image/html",            -- HTML
+                json = "application/json"       -- JSON
+            }
+            
+            for kk,vv in pairs(v) do
+                if type(vv) == "table" then
+                    for i=1, #vv do
+                        print(kk,vv[i])
+                        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")
+                        table.insert(body, io.readFile(vv[i]))
+                        table.insert(body, "\r\n")
+                    end
+                else
+                    print(kk,vv)
+                    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")
+                    table.insert(body, io.readFile(vv))
+                    table.insert(body, "\r\n")
+                end
+            end
+        end
+    end 
+    table.insert(body, "--"..boundary.."--\r\n")
+    body = table.concat(body)
+    log.info("headers: ", "\r\n" .. json.encode(req_headers), type(body))
+    log.info("body: " .. body:len() .. "\r\n" .. body)
+    local code, headers, body = http.request("POST",url,
+            req_headers,
+            body
+    ).wait()   
+    log.info("http.post", code, headers, body)
+end

+ 16 - 0
demo/http/test_get.lua

@@ -0,0 +1,16 @@
+function demo_http_get()
+    -- 最普通的Http GET请求
+    local code, headers, body = http.request("GET", "https://www.air32.cn/").wait()
+    log.info("http.get", code, headers, body)
+    local code, headers, body = http.request("GET", "https://mirrors6.tuna.tsinghua.edu.cn/", nil, nil, {ipv6=true}).wait()
+    log.info("http.get", code, headers, body)
+    sys.wait(100)
+    local code, headers, body = http.request("GET", "https://www.luatos.com/").wait()
+    log.info("http.get", code, headers, body)
+
+    -- 按需打印
+    -- code 响应值, 若大于等于 100 为服务器响应, 小于的均为错误代码
+    -- headers是个table, 一般作为调试数据存在
+    -- body是字符串. 注意lua的字符串是带长度的byte[]/char*, 是可以包含不可见字符的
+    -- log.info("http", code, json.encode(headers or {}), #body > 512 and #body or body)
+end

+ 314 - 0
demo/http/test_gzip.lua

@@ -0,0 +1,314 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "httpdemo"
+VERSION = "1.0.0"
+
+--[[
+本demo需要http库, 大部分能联网的设备都具有这个库
+http也是内置库, 无需require
+
+1. 如需上传大文件,请使用 httpplus 库, 对应demo/httpplus
+2. 
+]]
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用http库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+
+-- Air780E的AT固件默认会为开机键防抖, 导致部分用户刷机很麻烦
+if rtos.bsp() == "EC618" and pm and pm.PWK_MODE then
+    pm.power(pm.PWK_MODE, false)
+end
+
+
+sys.taskInit(function()
+    -----------------------------
+    -- 统一联网函数, 可自行删减
+    ----------------------------
+    if wlan and wlan.connect then
+        -- wifi 联网, ESP32系列均支持
+        local ssid = "luatos1234"
+        local password = "12341234"
+        log.info("wifi", ssid, password)
+        -- TODO 改成esptouch配网
+        -- LED = gpio.setup(12, 0, gpio.PULLUP)
+        wlan.init()
+        wlan.setMode(wlan.STATION)
+        wlan.connect(ssid, password, 1)
+        local result, data = sys.waitUntil("IP_READY", 30000)
+        log.info("wlan", "IP_READY", result, data)
+        device_id = wlan.getMac()
+    elseif rtos.bsp() == "AIR105" then
+        -- w5500 以太网, 当前仅Air105支持
+        w5500.init(spi.HSPI_0, 24000000, pin.PC14, pin.PC01, pin.PC00)
+        w5500.config() --默认是DHCP模式
+        w5500.bind(socket.ETH0)
+        -- LED = gpio.setup(62, 0, gpio.PULLUP)
+        sys.wait(1000)
+        -- TODO 获取mac地址作为device_id
+    elseif mobile then
+        -- Air780E/Air600E系列
+        --mobile.simid(2)
+        -- LED = gpio.setup(27, 0, gpio.PULLUP)
+        device_id = mobile.imei()
+        log.info("ipv6", mobile.ipv6(true))
+        sys.waitUntil("IP_READY", 30000)
+    elseif http then
+        sys.waitUntil("IP_READY")
+    else
+        while 1 do
+            sys.wait(1000)
+            log.info("http", "当前固件未包含http库")
+        end
+    end
+    log.info("已联网")
+    sys.publish("net_ready")
+end)
+
+function demo_http_get()
+    -- 最普通的Http GET请求
+    local code, headers, body = http.request("GET", "https://www.air32.cn/").wait()
+    log.info("http.get", code, headers, body)
+    local code, headers, body = http.request("GET", "https://mirrors6.tuna.tsinghua.edu.cn/", nil, nil, {ipv6=true}).wait()
+    log.info("http.get", code, headers, body)
+    sys.wait(100)
+    local code, headers, body = http.request("GET", "https://www.luatos.com/").wait()
+    log.info("http.get", code, headers, body)
+
+    -- 按需打印
+    -- code 响应值, 若大于等于 100 为服务器响应, 小于的均为错误代码
+    -- headers是个table, 一般作为调试数据存在
+    -- body是字符串. 注意lua的字符串是带长度的byte[]/char*, 是可以包含不可见字符的
+    -- log.info("http", code, json.encode(headers or {}), #body > 512 and #body or body)
+end
+
+function demo_http_post_json()
+    -- POST request 演示
+    local req_headers = {}
+    req_headers["Content-Type"] = "application/json"
+    local body = json.encode({name="LuatOS"})
+    local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date", 
+            req_headers,
+            body -- POST请求所需要的body, string, zbuff, file均可
+    ).wait()
+    log.info("http.post", code, headers, body)
+end
+
+function demo_http_post_form()
+    -- POST request 演示
+    local req_headers = {}
+    req_headers["Content-Type"] = "application/x-www-form-urlencoded"
+    local params = {
+        ABC = "123",
+        DEF = 345
+    }
+    local body = ""
+    for k, v in pairs(params) do
+        body = body .. tostring(k) .. "=" .. tostring(v):urlEncode() .. "&"
+    end
+    local code, headers, body = http.request("POST","http://echohttp.wendal.cn/post", 
+            req_headers,
+            body -- POST请求所需要的body, string, zbuff, file均可
+    ).wait()
+    log.info("http.post.form", code, headers, body)
+end
+
+-- local function http_download_callback(content_len,body_len,userdata)
+--     print("http_download_callback",content_len,body_len,userdata)
+-- end
+
+-- local http_userdata = "123456789"
+
+function demo_http_download()
+
+    -- POST and download, task内的同步操作
+    local opts = {}                 -- 额外的配置项
+    opts["dst"] = "/data.bin"       -- 下载路径,可选
+    opts["timeout"] = 30000         -- 超时时长,单位ms,可选
+    -- opts["adapter"] = socket.ETH0  -- 使用哪个网卡,可选
+    -- opts["callback"] = http_download_callback
+    -- opts["userdata"] = http_userdata
+
+    for k, v in pairs(opts) do
+        print("opts",k,v)
+    end
+    
+    local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date",
+            {}, -- 请求所添加的 headers, 可以是nil
+            "", 
+            opts
+    ).wait()
+    log.info("http.post", code, headers, body) -- 只返回code和headers
+
+    -- local f = io.open("/data.bin", "rb")
+    -- if f then
+    --     local data = f:read("*a")
+    --     log.info("fs", "data", data, data:toHex())
+    -- end
+    
+    -- GET request, 开个task让它自行执行去吧, 不管执行结果了
+    sys.taskInit(http.request("GET","http://site0.cn/api/httptest/simple/time").wait)
+end
+
+function demo_http_post_file()
+        -- -- POST multipart/form-data模式 上传文件---手动拼接
+        local boundary = "----WebKitFormBoundary"..os.time()
+        local req_headers = {
+            ["Content-Type"] = "multipart/form-data; boundary="..boundary,
+        }
+        local body = "--"..boundary.."\r\n"..
+                     "Content-Disposition: form-data; name=\"uploadFile\"; filename=\"luatos_uploadFile_TEST01.txt\""..
+                     "\r\nContent-Type: text/plain\r\n\r\n"..
+                     "1111http_测试一二三四654zacc\r\n"..
+                     "--"..boundary
+
+        log.info("headers: ", "\r\n"..json.encode(req_headers))
+        log.info("body: ", "\r\n"..body)
+        local code, headers, body = http.request("POST","http://airtest.openluat.com:2900/uploadFileToStatic",
+                req_headers,
+                body -- POST请求所需要的body, string, zbuff, file均可
+        ).wait()
+        log.info("http.post", code, headers, body)
+
+        -- 也可用postMultipartFormData(url, params) 上传文件
+        postMultipartFormData(
+            "http://airtest.openluat.com:2900/uploadFileToStatic",
+            {
+                -- texts = 
+                -- {
+                --     ["imei"] = "862991234567890",
+                --     ["time"] = "20180802180345"
+                -- },
+                
+                files =
+                {
+                    ["uploadFile"] = "/luadb/luatos_uploadFile.txt",
+                }
+            }
+        )
+end
+
+
+local function demo_http_get_gzip()
+    -- 这里用 和风天气 的API做演示
+    -- 这个API的响应, 总会gzip压缩过, 需要配合miniz库进行解压
+    local code, headers, body = http.request("GET", "https://devapi.qweather.com/v7/weather/now?location=101010100&key=0e8c72015e2b4a1dbff1688ad54053de").wait()
+    log.info("http.gzip", code)
+    if code == 200 then
+        local re = miniz.uncompress(body:sub(11), 0)
+        log.info("和风天气", re)
+        if re then
+            local jdata = json.decode(re)
+            log.info("jdata", jdata)
+            if jdata then
+                log.info("和风天气", jdata.code)
+                if jdata.now then
+                    log.info("和风天气", "天气", jdata.now.text)
+                    log.info("和风天气", "温度", jdata.now.temp)
+                end
+            end
+        end
+    end
+end
+
+sys.taskInit(function()
+    sys.wait(100)
+    -- 打印一下支持的加密套件, 通常来说, 固件已包含常见的99%的加密套件
+    -- if crypto.cipher_suites then
+    --     log.info("cipher", "suites", json.encode(crypto.cipher_suites()))
+    -- end
+
+    -------------------------------------
+    -------- HTTP 演示代码 --------------
+    -------------------------------------
+    sys.waitUntil("net_ready") -- 等联网
+
+    while 1 do
+        -- 演示GET请求
+        demo_http_get()
+        -- 表单提交
+        -- demo_http_post_form()
+        -- POST一个json字符串
+        -- demo_http_post_json()
+        -- 上传文件, mulitform形式
+        -- demo_http_post_file()
+        -- 文件下载
+        -- demo_http_download()
+        -- gzip压缩的响应, 以和风天气为例
+        -- demo_http_get_gzip()
+
+        sys.wait(1000)
+        -- 打印一下内存状态
+        log.info("sys", rtos.meminfo("sys"))
+        log.info("lua", rtos.meminfo("lua"))
+        sys.wait(600000)
+    end
+end)
+
+---- MultipartForm上传文件
+-- url string 请求URL地址
+-- req_headers table 请求头
+-- params table 需要传输的数据参数
+function postMultipartFormData(url, params)
+    local boundary = "----WebKitFormBoundary"..os.time()
+    local req_headers = {
+        ["Content-Type"] = "multipart/form-data; boundary="..boundary,
+    }
+    local body = {}
+
+    -- 解析拼接 body
+    for k,v in pairs(params) do
+        if k=="texts" then
+            local bodyText = ""
+            for kk,vv in pairs(v) do
+                print(kk,vv)
+                bodyText = bodyText.."--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"\r\n\r\n"..vv.."\r\n"
+            end
+            table.insert(body, bodyText)
+        elseif k=="files" then
+            local contentType =
+            {
+                txt = "text/plain",             -- 文本
+                jpg = "image/jpeg",             -- JPG 格式图片
+                jpeg = "image/jpeg",            -- JPEG 格式图片
+                png = "image/png",              -- PNG 格式图片   
+                gif = "image/gif",              -- GIF 格式图片
+                html = "image/html",            -- HTML
+                json = "application/json"       -- JSON
+            }
+            
+            for kk,vv in pairs(v) do
+                if type(vv) == "table" then
+                    for i=1, #vv do
+                        print(kk,vv[i])
+                        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")
+                        table.insert(body, io.readFile(vv[i]))
+                        table.insert(body, "\r\n")
+                    end
+                else
+                    print(kk,vv)
+                    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")
+                    table.insert(body, io.readFile(vv))
+                    table.insert(body, "\r\n")
+                end
+            end
+        end
+    end 
+    table.insert(body, "--"..boundary.."--\r\n")
+    body = table.concat(body)
+    log.info("headers: ", "\r\n" .. json.encode(req_headers), type(body))
+    log.info("body: " .. body:len() .. "\r\n" .. body)
+    local code, headers, body = http.request("POST",url,
+            req_headers,
+            body
+    ).wait()   
+    log.info("http.post", code, headers, body)
+end
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 31 - 0
demo/http/test_post.lua

@@ -0,0 +1,31 @@
+
+function demo_http_post_json()
+    -- POST request 演示
+    local req_headers = {}
+    req_headers["Content-Type"] = "application/json"
+    local body = json.encode({name="LuatOS"})
+    local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date", 
+            req_headers,
+            body -- POST请求所需要的body, string, zbuff, file均可
+    ).wait()
+    log.info("http.post", code, headers, body)
+end
+
+function demo_http_post_form()
+    -- POST request 演示
+    local req_headers = {}
+    req_headers["Content-Type"] = "application/x-www-form-urlencoded"
+    local params = {
+        ABC = "123",
+        DEF = 345
+    }
+    local body = ""
+    for k, v in pairs(params) do
+        body = body .. tostring(k) .. "=" .. tostring(v):urlEncode() .. "&"
+    end
+    local code, headers, body = http.request("POST","http://echohttp.wendal.cn/post", 
+            req_headers,
+            body -- POST请求所需要的body, string, zbuff, file均可
+    ).wait()
+    log.info("http.post.form", code, headers, body)
+end