| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /*
- @module http
- @summary 执行http请求
- @version 1.0
- @date 2020.07.07
- @demo http
- */
- #include "luat_base.h"
- #include "luat_http.h"
- #include "luat_msgbus.h"
- #include "luat_malloc.h"
- #define LUAT_LOG_TAG "http"
- #include "luat_log.h"
- static int l_http_reqcommon(lua_State *L, uint8_t method);
- static int luat_http_msghandler(lua_State *L, void* ptr) {
- luat_lib_http_resp_t *resp = ptr;
- int recount = 0;
- if (resp) {
- LLOGD("http resp code=%ld", resp->code);
- if (resp->luacb) {
- lua_geti(L, LUA_REGISTRYINDEX, resp->luacb);
- lua_pushinteger(L, resp->code);
- lua_newtable(L); // headers 暂时不处理
- if (resp->body.size > 0) {
- recount = 3;
- lua_pushlstring(L, resp->body.ptr, resp->body.size);
- }
- else {
- recount = 2;
- }
- lua_call(L, recount, 0);
- luaL_unref(L, LUA_REGISTRYINDEX, resp->luacb);
- }
- luat_http_resp_gc(resp);
- }
- return 0;
- }
- static int luat_http_cb_impl(luat_lib_http_resp_t *resp) {
- if (resp->luacb == 0) {
- LLOGD("http resp without lua callback code=%ld", resp->code);
- luat_http_resp_gc(resp);
- return 0; //
- }
- rtos_msg_t msg;
- msg.handler = luat_http_msghandler;
- msg.ptr = resp;
- msg.arg1 = resp->code;
- msg.arg2 = 0;
- luat_msgbus_put(&msg, 0);
- return 0;
- }
- /*
- 发起一个http get请求(推荐用http.get/post/put/delete方法)
- @api http.req(url, params, cb)
- @string 目标URL,需要是https://或者http://开头,否则将当成http://开头
- @table 可选参数. method方法,headers请求头,body数据,ca证书路径,timeout超时时长,
- @function 回调方法
- @return boolean 成功启动返回true,否则返回false.启动成功后,cb回调必然会调用一次
- @usage
- -- GET请求
- http.req("http://www.baidu.com/", nil, function(ret, code, headers, body)
- log.info("http", ret, code, header, body)
- end)
- */
- static int l_http_req(lua_State *L) {
- return l_http_reqcommon(L, LUAT_HTTP_GET);
- }
- /*
- 发起一个http get请求
- @api http.get(url, params, cb)
- @string 目标URL,需要是https://或者http://开头,否则将当成http://开头
- @table 可选参数. headers请求头,body数据,ca证书路径,timeout超时时长,
- @function 回调方法
- @return boolean 成功启动返回true,否则返回false.启动成功后,cb回调必然会调用一次
- @usage
- -- GET请求
- http.get("http://www.baidu.com/", nil, function(ret, code, headers, body)
- log.info("http", ret, code, header, body)
- end)
- */
- static int l_http_get(lua_State *L) {
- return l_http_reqcommon(L, LUAT_HTTP_GET);
- }
- /*
- 发起一个http post请求
- @api http.post(url, params, cb)
- @string 目标URL,需要是https://或者http://开头,否则将当成http://开头
- @table 可选参数. headers请求头,body数据,ca证书路径,timeout超时时长,
- @function 回调方法
- @return boolean 成功启动返回true,否则返回false.启动成功后,cb回调必然会调用一次
- @usage
- -- POST请求
- http.post("http://www.baidu.com/", {body=json.encode(data)}, function(ret, code, headers, body)
- log.info("http", ret, code, header, body)
- end)
- */
- static int l_http_post(lua_State *L) {
- return l_http_reqcommon(L, LUAT_HTTP_POST);
- }
- /*
- 发起一个http put请求
- @api http.put(url, params, cb)
- @string 目标URL,需要是https://或者http://开头,否则将当成http://开头
- @table 可选参数. headers请求头,body数据,ca证书路径,timeout超时时长,
- @function 回调方法
- @return boolean 成功启动返回true,否则返回false.启动成功后,cb回调必然会调用一次
- @usage
- -- PUT请求
- http.put("http://www.baidu.com/", {body=json.encode(data)}, function(ret, code, headers, body)
- log.info("http", ret, code, header, body)
- end)
- */
- static int l_http_put(lua_State *L) {
- return l_http_reqcommon(L, LUAT_HTTP_PUT);
- }
- /*
- 发起一个http delete请求
- @api http.delete(url, params, cb)
- @string 目标URL,需要是https://或者http://开头,否则将当成http://开头
- @table 可选参数. headers请求头,body数据,ca证书路径,timeout超时时长,
- @function 回调方法
- @return boolean 成功启动返回true,否则返回false.启动成功后,cb回调必然会调用一次
- @usage
- -- DELETE请求
- http.delete("http://www.baidu.com/", nil, function(ret, code, headers, body)
- log.info("http", ret, code, header, body)
- end)
- */
- static int l_http_delete(lua_State *L) {
- return l_http_reqcommon(L, LUAT_HTTP_DELETE);
- }
- static int l_http_reqcommon(lua_State *L, uint8_t method) {
- if (!lua_isstring(L, 1)) {
- lua_pushliteral(L, "first arg must string");
- lua_error(L);
- return 0;
- }
- luat_lib_http_req_t *req = luat_heap_malloc(sizeof(luat_lib_http_req_t));
- if (req == NULL) {
- lua_pushstring(L, "sys out of memory");
- lua_error(L);
- return 0;
- }
- memset(req, 0, sizeof(luat_lib_http_req_t));
- req->method = method;
- char* tmp = (char*)luaL_checklstring(L, 1, &(req->url_len));
- req->url = luat_heap_malloc(req->url_len+1);
- if (req->url == NULL) {
- luat_heap_free(req);
- lua_pushstring(L, "sys out of memory");
- lua_error(L);
- return 0;
- }
- memset(req->url, 0, req->url_len + 1);
- memcpy(req->url, tmp, req->url_len + 1);
- LLOGD("http url=%s", req->url);
- // 先取一下回调
- if (lua_isfunction(L, 3)) {
- lua_settop(L, 3);
- req->luacb = luaL_ref(L, LUA_REGISTRYINDEX);
- }
- if (lua_istable(L, 2)) {
- //lua_settop(L, 2); // 移除掉其他参数
- // 取method
- lua_pushliteral(L, "method");
- if (lua_gettable(L, 2)) {
- if (lua_isinteger(L, -1)) {
- req->method = luaL_checkinteger(L, -1);
- }
- }
- lua_pop(L, 1);
- // 取下载路径
- lua_pushliteral(L, "dw");
- if (lua_gettable(L, 2) == LUA_TSTRING){
- size_t dw_path_sz = 0;
- const char* dw = luaL_checklstring(L, -1, &dw_path_sz);
- if (dw_path_sz > 31) {
- LLOGD("download path is too long!!!");
- lua_pushliteral(L, "download path is too long!!!");
- lua_error(L);
- return 0;
- }
- strcpy(req->dwpath, dw);
- }
- lua_pop(L, 1);
- // 取headers
- // 取body,当前仅支持string
- lua_pushliteral(L, "body");
- lua_gettable(L, 2);
- if (!lua_isnil(L, -1) && !lua_isstring(L, -1)) {
- lua_pop(L, 1);
- lua_pushliteral(L, "body must be string");
- lua_error(L);
- luat_http_req_gc(req);
- return 0;
- }
- else if (lua_isstring(L, -1)) {
- tmp = (char*)luaL_checklstring(L, -1, &(req->body.size));
- if (req->body.size > 0) {
- req->body.ptr = luat_heap_malloc(req->body.size);
- memcpy(req->body.ptr, tmp, req->body.size);
- }
- }
- lua_pop(L, 1);
- // 去ca证书路径
- lua_pushliteral(L, "ca");
- lua_gettable(L, 2);
- if (!lua_isnil(L, -1) && !lua_isstring(L, -1)) {
- lua_pop(L, 1);
- lua_pushliteral(L, "ca must be string");
- lua_error(L);
- luat_http_req_gc(req);
- return 0;
- }
- else if (lua_isstring(L, -1)) {
- tmp = (char*)luaL_checklstring(L, -1, &(req->ca_len));
- if (req->ca_len > 0) {
- req->ca = luat_heap_malloc(req->ca_len);
- memcpy(req->ca, tmp, req->ca_len);
- }
- }
- lua_pop(L, 1);
- // timeout设置
- lua_pushliteral(L, "timeout");
- lua_gettable(L, 2);
- if (!lua_isnil(L, -1) && !lua_isinteger(L, -1)) {
- lua_pop(L, 1);
- lua_pushliteral(L, "timeout must be int");
- lua_error(L);
- luat_http_req_gc(req);
- return 0;
- }
- else if (lua_isinteger(L, -1)) {
- req->timeout_s = luaL_checkinteger(L, -1);
- }
- lua_pop(L, 1);
- }
- req->httpcb = luat_http_cb_impl;
- if (req->timeout_s <= 5) {
- req->timeout_s = 5;
- }
- // 执行
- int re = luat_http_req(req);
- if (re == 0) {
- lua_pushboolean(L, 1);
- return 1;
- }
- else {
- luat_http_req_gc(req);
- LLOGW("http request return re=%ld", re);
- lua_pushboolean(L, 0);
- lua_pushinteger(L, re);
- return 2;
- }
- }
- #include "rotable2.h"
- static const rotable_Reg_t reg_http[] =
- {
- { "req", ROREG_FUNC(l_http_req)},
- { "get", ROREG_FUNC(l_http_get)},
- { "post", ROREG_FUNC(l_http_post)},
- { "put", ROREG_FUNC(l_http_put)},
- { "delete", ROREG_FUNC(l_http_delete)},
- { NULL, ROREG_INT(0) }
- };
- LUAMOD_API int luaopen_http( lua_State *L ) {
- luat_newlib2(L, reg_http);
- return 1;
- }
- void luat_http_req_gc(luat_lib_http_req_t *req) {
- if (req == NULL) {
- return;
- }
- if (req->url) {
- luat_heap_free(req->url);
- }
- if (req->headers.size > 0) {
- for (size_t i = 0; i < req->headers.size; i++)
- {
- luat_heap_free(*(req->headers.ptr + i));
- }
- }
- if (req->body.size > 0) {
- luat_heap_free(req->body.ptr);
- }
- luat_heap_free(req);
- }
- void luat_http_resp_gc(luat_lib_http_resp_t *resp) {
- if (resp == NULL) {
- return;
- }
- if (resp->headers.size > 0) {
- for (size_t i = 0; i < resp->headers.size; i++)
- {
- luat_heap_free(*(resp->headers.ptr + i));
- }
- }
- if (resp->body.size > 0) {
- luat_heap_free(resp->body.ptr);
- }
- luat_heap_free(resp);
- }
|