luat_http_client.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. /*
  2. @module http
  3. @summary http 客户端
  4. @version 1.0
  5. @date 2022.09.05
  6. @demo socket
  7. @tag LUAT_USE_HTTP
  8. @usage
  9. -- 使用http库,需要引入sysplus库, 且需要在task内使用
  10. require "sys"
  11. require "sysplus"
  12. sys.taskInit(function()
  13. sys.wait(1000)
  14. local code,headers,body = http.request("GET", "http://www.example.com/abc").wait()
  15. log.info("http", code, body)
  16. end)
  17. */
  18. #include "luat_base.h"
  19. #include "luat_network_adapter.h"
  20. #include "luat_rtos.h"
  21. #include "luat_msgbus.h"
  22. #include "luat_fs.h"
  23. #include "luat_malloc.h"
  24. #include "http_parser.h"
  25. #include "luat_http.h"
  26. #define LUAT_LOG_TAG "http"
  27. #include "luat_log.h"
  28. #define HTTP_DEBUG 0
  29. #if HTTP_DEBUG == 0
  30. #undef LLOGD
  31. #define LLOGD(...)
  32. #endif
  33. static void http_send_message(luat_http_ctrl_t *http_ctrl);
  34. static int http_close(luat_http_ctrl_t *http_ctrl){
  35. LLOGD("http close %p", http_ctrl);
  36. if (http_ctrl->netc){
  37. network_force_close_socket(http_ctrl->netc);
  38. network_release_ctrl(http_ctrl->netc);
  39. }
  40. if (http_ctrl->timeout_timer){
  41. luat_release_rtos_timer(http_ctrl->timeout_timer);
  42. http_ctrl->timeout_timer = NULL;
  43. }
  44. if (http_ctrl->host){
  45. luat_heap_free(http_ctrl->host);
  46. }
  47. if (http_ctrl->url){
  48. luat_heap_free(http_ctrl->url);
  49. }
  50. if (http_ctrl->uri){
  51. luat_heap_free(http_ctrl->uri);
  52. }
  53. if (http_ctrl->req_header){
  54. luat_heap_free(http_ctrl->req_header);
  55. }
  56. if (http_ctrl->req_body){
  57. luat_heap_free(http_ctrl->req_body);
  58. }
  59. if (http_ctrl->dst){
  60. luat_heap_free(http_ctrl->dst);
  61. }
  62. if (http_ctrl->headers){
  63. luat_heap_free(http_ctrl->headers);
  64. }
  65. if (http_ctrl->body){
  66. luat_heap_free(http_ctrl->body);
  67. }
  68. luat_heap_free(http_ctrl);
  69. return 0;
  70. }
  71. static int32_t l_http_callback(lua_State *L, void* ptr){
  72. char* temp;
  73. char* header;
  74. char* value;
  75. uint16_t header_len = 0,value_len = 0;
  76. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  77. luat_http_ctrl_t *http_ctrl =(luat_http_ctrl_t *)msg->ptr;
  78. uint64_t idp = http_ctrl->idp;
  79. if (http_ctrl->timeout_timer){
  80. luat_stop_rtos_timer(http_ctrl->timeout_timer);
  81. }
  82. LLOGD("l_http_callback arg1:%d is_download:%d idp:%d",msg->arg1,http_ctrl->is_download,idp);
  83. if (msg->arg1){
  84. lua_pushinteger(L, msg->arg1); // 把错误码返回去
  85. luat_cbcwait(L, idp, 1);
  86. goto exit;
  87. }
  88. lua_pushinteger(L, http_ctrl->parser.status_code);
  89. lua_newtable(L);
  90. // LLOGD("http_ctrl->headers:%.*s",http_ctrl->headers_len,http_ctrl->headers);
  91. header = http_ctrl->headers;
  92. while ( (http_ctrl->headers_len)>0 ){
  93. value = strstr(header,":")+1;
  94. if (value[1]==' '){
  95. value++;
  96. }
  97. temp = strstr(value,"\r\n")+2;
  98. header_len = value-header-1;
  99. value_len = temp-value-2;
  100. // LLOGD("header:%.*s",header_len,header);
  101. // LLOGD("value:%.*s",value_len,value);
  102. lua_pushlstring(L, header,header_len);
  103. lua_pushlstring(L, value,value_len);
  104. lua_settable(L, -3);
  105. http_ctrl->headers_len -= temp-header;
  106. header = temp;
  107. }
  108. LLOGD("http_ctrl->body:%.*s len:%d",http_ctrl->body_len,http_ctrl->body,http_ctrl->body_len);
  109. // 处理body, 需要区分下载模式和非下载模式
  110. if (http_ctrl->is_download) {
  111. // 下载模式
  112. if (http_ctrl->fd == NULL) {
  113. // 下载操作一切正常, 返回长度
  114. lua_pushinteger(L, http_ctrl->body_len);
  115. luat_cbcwait(L, idp, 3); // code, headers, body
  116. goto exit;
  117. }else if (http_ctrl->fd != NULL) {
  118. // 下载中断了!!
  119. luat_fs_fclose(http_ctrl->fd);
  120. luat_fs_remove(http_ctrl->dst); // 移除文件
  121. }
  122. // 下载失败, 返回错误码
  123. lua_pushinteger(L, -1);
  124. luat_cbcwait(L, idp, 3); // code, headers, body
  125. goto exit;
  126. } else {
  127. // 非下载模式
  128. lua_pushlstring(L, http_ctrl->body, http_ctrl->body_len);
  129. luat_cbcwait(L, idp, 3); // code, headers, body
  130. }
  131. exit:
  132. http_close(http_ctrl);
  133. return 0;
  134. }
  135. static void http_resp_error(luat_http_ctrl_t *http_ctrl, int error_code) {
  136. LLOGD("http_resp_error error_code:%d close_state:%d",error_code,http_ctrl->close_state);
  137. if (http_ctrl->close_state == 0 && http_ctrl->headers_complete && http_ctrl->re_request_count < HTTP_RE_REQUEST_MAX){
  138. http_ctrl->re_request_count++;
  139. #ifdef LUAT_USE_LWIP
  140. if(network_connect(http_ctrl->netc, http_ctrl->host, strlen(http_ctrl->host), (0xff == http_ctrl->ip_addr.type)?NULL:&(http_ctrl->ip_addr), http_ctrl->remote_port, 0) < 0){
  141. #else
  142. if(network_connect(http_ctrl->netc, http_ctrl->host, strlen(http_ctrl->host), (0xff == http_ctrl->ip_addr.is_ipv6)?NULL:&(http_ctrl->ip_addr), http_ctrl->remote_port, 0) < 0){
  143. #endif
  144. goto error;
  145. }
  146. }else if (http_ctrl->close_state==0){
  147. error:
  148. http_ctrl->close_state=1;
  149. network_close(http_ctrl->netc, 0);
  150. rtos_msg_t msg = {0};
  151. msg.handler = l_http_callback;
  152. msg.ptr = http_ctrl;
  153. msg.arg1 = error_code;
  154. luat_msgbus_put(&msg, 0);
  155. }
  156. }
  157. static int on_message_begin(http_parser* parser){
  158. LLOGD("on_message_begin");
  159. return 0;
  160. }
  161. static int on_url(http_parser* parser, const char *at, size_t length){
  162. LLOGD("on_url:%.*s",length,at);
  163. return 0;
  164. }
  165. static int on_status(http_parser* parser, const char *at, size_t length){
  166. LLOGD("on_status:%.*s",length,at);
  167. return 0;
  168. }
  169. static int on_header_field(http_parser* parser, const char *at, size_t length){
  170. LLOGD("on_header_field:%.*s",length,at);
  171. luat_http_ctrl_t *http_ctrl =(luat_http_ctrl_t *)parser->data;
  172. if (http_ctrl->headers_complete){
  173. return 0;
  174. }
  175. // if(!strncasecmp(at, "Content-Length: ", 16)){
  176. // http_ctrl->resp_content_len = -1;
  177. // }
  178. if (!http_ctrl->headers){
  179. http_ctrl->headers = luat_heap_malloc(length+2);
  180. }else{
  181. http_ctrl->headers = luat_heap_realloc(http_ctrl->headers,http_ctrl->headers_len+length+2);
  182. }
  183. memcpy(http_ctrl->headers+http_ctrl->headers_len,at,length);
  184. memcpy(http_ctrl->headers+http_ctrl->headers_len+length, ":", 1);
  185. http_ctrl->headers_len += length+1;
  186. return 0;
  187. }
  188. static int on_header_value(http_parser* parser, const char *at, size_t length){
  189. LLOGD("on_header_value:%.*s",length,at);
  190. char tmp[16] = {0};
  191. luat_http_ctrl_t *http_ctrl =(luat_http_ctrl_t *)parser->data;
  192. if (http_ctrl->headers_complete){
  193. return 0;
  194. }
  195. // if(http_ctrl->resp_content_len == -1){
  196. // memcpy(tmp, at, length);
  197. // http_ctrl->resp_content_len = atoi(tmp);
  198. // LLOGD("http_ctrl->resp_content_len:%d",http_ctrl->resp_content_len);
  199. // }
  200. http_ctrl->headers = luat_heap_realloc(http_ctrl->headers,http_ctrl->headers_len+length+3);
  201. memcpy(http_ctrl->headers+http_ctrl->headers_len,at,length);
  202. memcpy(http_ctrl->headers+http_ctrl->headers_len+length, "\r\n", 2);
  203. http_ctrl->headers_len += length+2;
  204. return 0;
  205. }
  206. static int on_headers_complete(http_parser* parser){
  207. LLOGD("on_headers_complete");
  208. luat_http_ctrl_t *http_ctrl =(luat_http_ctrl_t *)parser->data;
  209. if (http_ctrl->headers_complete){
  210. return 0;
  211. }
  212. http_ctrl->headers[http_ctrl->headers_len] = 0x00;
  213. if (http_ctrl->is_download){
  214. luat_fs_remove(http_ctrl->dst);
  215. http_ctrl->fd = luat_fs_fopen(http_ctrl->dst, "w+");
  216. if (http_ctrl->fd == NULL) {
  217. LLOGE("open download file fail %s", http_ctrl->dst);
  218. }
  219. }
  220. http_ctrl->headers_complete = 1;
  221. return 0;
  222. }
  223. static int on_body(http_parser* parser, const char *at, size_t length){
  224. LLOGD("on_body:%.*s",length,at);
  225. luat_http_ctrl_t *http_ctrl =(luat_http_ctrl_t *)parser->data;
  226. if (http_ctrl->is_download){
  227. if (http_ctrl->fd == NULL){
  228. luat_fs_remove(http_ctrl->dst);
  229. http_ctrl->fd = luat_fs_fopen(http_ctrl->dst, "w+");
  230. if (http_ctrl->fd == NULL) {
  231. LLOGE("open download file fail %s", http_ctrl->dst);
  232. http_resp_error(http_ctrl, HTTP_ERROR_DOWNLOAD);
  233. return -1;
  234. }
  235. }
  236. luat_fs_fwrite(at, length, 1, http_ctrl->fd);
  237. }else{
  238. if (!http_ctrl->body){
  239. http_ctrl->body = luat_heap_malloc(length+1);
  240. }else{
  241. http_ctrl->body = luat_heap_realloc(http_ctrl->body,http_ctrl->body_len+length+1);
  242. }
  243. memcpy(http_ctrl->body+http_ctrl->body_len,at,length);
  244. }
  245. http_ctrl->body_len += length;
  246. return 0;
  247. }
  248. static int on_message_complete(http_parser* parser){
  249. LLOGD("on_message_complete");
  250. luat_http_ctrl_t *http_ctrl =(luat_http_ctrl_t *)parser->data;
  251. // http_ctrl->body[http_ctrl->body_len] = 0x00;
  252. if (http_ctrl->fd != NULL) {
  253. luat_fs_fclose(http_ctrl->fd);
  254. http_ctrl->fd = NULL;
  255. }
  256. LLOGD("status_code:%d",parser->status_code);
  257. LLOGD("content_length:%lld",parser->content_length);
  258. http_ctrl->close_state = 1;
  259. network_close(http_ctrl->netc, 0);
  260. rtos_msg_t msg = {0};
  261. msg.handler = l_http_callback;
  262. msg.ptr = http_ctrl;
  263. msg.arg1 = HTTP_OK;
  264. luat_msgbus_put(&msg, 0);
  265. return 0;
  266. }
  267. static int on_chunk_header(http_parser* parser){
  268. LLOGD("on_chunk_header");
  269. LLOGD("content_length:%lld",parser->content_length);
  270. // luat_http_ctrl_t *http_ctrl =(luat_http_ctrl_t *)parser->data;
  271. // http_ctrl->is_chunk = 1;
  272. return 0;
  273. }
  274. // static int on_chunk_complete(http_parser* parser){
  275. // // LLOGD("on_chunk_complete CALL on_message_complete");
  276. // // on_message_complete(parser);
  277. // return 0;
  278. // }
  279. static uint32_t http_send(luat_http_ctrl_t *http_ctrl, uint8_t* data, size_t len) {
  280. if (len == 0)
  281. return 0;
  282. uint32_t tx_len = 0;
  283. // LLOGD("http_send data:%.*s",len,data);
  284. network_tx(http_ctrl->netc, data, len, 0, NULL, 0, &tx_len, 0);
  285. return tx_len;
  286. }
  287. static void http_send_message(luat_http_ctrl_t *http_ctrl){
  288. uint32_t tx_len = 0;
  289. // 发送请求行
  290. snprintf_(http_ctrl->request_message, HTTP_REQUEST_BUF_LEN_MAX, "%s %s HTTP/1.1\r\n", http_ctrl->method, http_ctrl->uri);
  291. http_send(http_ctrl, http_ctrl->request_message, strlen(http_ctrl->request_message));
  292. // 强制添加host. TODO 判断自定义headers是否有host
  293. snprintf_(http_ctrl->request_message, HTTP_REQUEST_BUF_LEN_MAX, "Host: %s\r\n", http_ctrl->host);
  294. http_send(http_ctrl, http_ctrl->request_message, strlen(http_ctrl->request_message));
  295. if (http_ctrl->headers_complete){
  296. snprintf_(http_ctrl->request_message, HTTP_REQUEST_BUF_LEN_MAX, "Range: bytes=%d-\r\n", http_ctrl->body_len+1);
  297. http_send(http_ctrl, http_ctrl->request_message, strlen(http_ctrl->request_message));
  298. }
  299. // 发送自定义头部
  300. if (http_ctrl->req_header){
  301. http_send(http_ctrl, http_ctrl->req_header, strlen(http_ctrl->req_header));
  302. }
  303. // 结束头部
  304. http_send(http_ctrl, "\r\n", 2);
  305. // 发送body
  306. if (http_ctrl->req_body){
  307. http_send(http_ctrl, http_ctrl->req_body, http_ctrl->req_body_len);
  308. }
  309. //--------------------------------------------
  310. // 清理资源
  311. if (http_ctrl->host){
  312. luat_heap_free(http_ctrl->host);
  313. http_ctrl->host = NULL;
  314. }
  315. if (http_ctrl->url){
  316. luat_heap_free(http_ctrl->url);
  317. http_ctrl->url = NULL;
  318. }
  319. if (http_ctrl->uri){
  320. luat_heap_free(http_ctrl->uri);
  321. http_ctrl->uri = NULL;
  322. }
  323. if (http_ctrl->req_header){
  324. luat_heap_free(http_ctrl->req_header);
  325. http_ctrl->req_header = NULL;
  326. }
  327. if (http_ctrl->req_body){
  328. luat_heap_free(http_ctrl->req_body);
  329. http_ctrl->req_body = NULL;
  330. http_ctrl->req_body_len = 0;
  331. }
  332. }
  333. LUAT_RT_RET_TYPE luat_http_timer_callback(LUAT_RT_CB_PARAM){
  334. luat_http_ctrl_t * http_ctrl = (luat_http_ctrl_t *)param;
  335. http_resp_error(http_ctrl, HTTP_ERROR_TIMEOUT);
  336. }
  337. static int32_t luat_lib_http_callback(void *data, void *param){
  338. OS_EVENT *event = (OS_EVENT *)data;
  339. luat_http_ctrl_t *http_ctrl =(luat_http_ctrl_t *)param;
  340. int ret = 0;
  341. // LLOGD("LINK %d ON_LINE %d EVENT %d TX_OK %d CLOSED %d",EV_NW_RESULT_LINK & 0x0fffffff,EV_NW_RESULT_CONNECT & 0x0fffffff,EV_NW_RESULT_EVENT & 0x0fffffff,EV_NW_RESULT_TX & 0x0fffffff,EV_NW_RESULT_CLOSE & 0x0fffffff);
  342. // LLOGD("luat_lib_http_callback %d %d",event->ID & 0x0fffffff,event->Param1);
  343. if (event->Param1){
  344. LLOGD("LINK %d ON_LINE %d EVENT %d TX_OK %d CLOSED %d",EV_NW_RESULT_LINK & 0x0fffffff,EV_NW_RESULT_CONNECT & 0x0fffffff,EV_NW_RESULT_EVENT & 0x0fffffff,EV_NW_RESULT_TX & 0x0fffffff,EV_NW_RESULT_CLOSE & 0x0fffffff);
  345. LLOGE("luat_lib_http_callback http_ctrl close %d %d",event->ID & 0x0fffffff,event->Param1);
  346. http_resp_error(http_ctrl, HTTP_ERROR_CLOSE);
  347. return -1;
  348. }
  349. if (event->ID == EV_NW_RESULT_LINK){
  350. return 0;
  351. }else if(event->ID == EV_NW_RESULT_CONNECT){
  352. http_send_message(http_ctrl);
  353. }else if(event->ID == EV_NW_RESULT_EVENT){
  354. uint32_t total_len = 0;
  355. uint32_t rx_len = 0;
  356. int result = network_rx(http_ctrl->netc, NULL, 0, 0, NULL, NULL, &total_len);
  357. // LLOGD("result:%d total_len:%d",result,total_len);
  358. if (0 == result){
  359. if (total_len>0){
  360. char* resp_buff = luat_heap_malloc(total_len + 1);
  361. resp_buff[total_len] = 0x00;
  362. next:
  363. result = network_rx(http_ctrl->netc, resp_buff, total_len, 0, NULL, NULL, &rx_len);
  364. LLOGD("result:%d rx_len:%d",result,rx_len);
  365. LLOGD("resp_buff:%.*s len:%d",total_len,resp_buff,total_len);
  366. if (result)
  367. goto next;
  368. if (rx_len == 0||result!=0) {
  369. luat_heap_free(resp_buff);
  370. http_resp_error(http_ctrl, HTTP_ERROR_RX);
  371. return -1;
  372. }
  373. int nParseBytes = http_parser_execute(&http_ctrl->parser, &http_ctrl->parser_settings, resp_buff, total_len);
  374. LLOGD("nParseBytes %d total_len %d", nParseBytes, total_len);
  375. luat_heap_free(resp_buff);
  376. if (nParseBytes != total_len){
  377. http_resp_error(http_ctrl, HTTP_ERROR_RX);
  378. return -1;
  379. }
  380. if (http_ctrl->close_state){
  381. return 0;
  382. }
  383. }
  384. }else{
  385. http_resp_error(http_ctrl, HTTP_ERROR_RX);
  386. return -1;
  387. }
  388. }else if(event->ID == EV_NW_RESULT_TX){
  389. }else if(event->ID == EV_NW_RESULT_CLOSE){
  390. // http_close(http_ctrl);
  391. return 0;
  392. }
  393. ret = network_wait_event(http_ctrl->netc, NULL, 0, NULL);
  394. LLOGD("network_wait_event %d", ret);
  395. if (ret < 0){
  396. http_resp_error(http_ctrl, HTTP_ERROR_CLOSE);
  397. return -1;
  398. }
  399. return 0;
  400. }
  401. static int http_add_header(luat_http_ctrl_t *http_ctrl, const char* name, const char* value){
  402. // LLOGD("http_add_header name:%s value:%s",name,value);
  403. // TODO 对value还需要进行urlencode
  404. strncat(http_ctrl->req_header, name, strlen(name));
  405. strncat(http_ctrl->req_header, ":", 1);
  406. strncat(http_ctrl->req_header, value, strlen(value));
  407. strncat(http_ctrl->req_header, "\r\n", 2);
  408. // LLOGD("http_ctrl->req_header:%s",http_ctrl->req_header);
  409. }
  410. static int http_set_url(luat_http_ctrl_t *http_ctrl) {
  411. char *tmp = http_ctrl->url;
  412. if (!strncmp("https://", http_ctrl->url, strlen("https://"))) {
  413. http_ctrl->is_tls = 1;
  414. tmp += strlen("https://");
  415. }
  416. else if (!strncmp("http://", http_ctrl->url, strlen("http://"))) {
  417. http_ctrl->is_tls = 0;
  418. tmp += strlen("http://");
  419. }
  420. else {
  421. LLOGI("only http/https supported %s", http_ctrl->url);
  422. return -1;
  423. }
  424. int tmplen = strlen(tmp);
  425. if (tmplen < 5) {
  426. LLOGI("url too short %s", http_ctrl->url);
  427. return -1;
  428. }
  429. char tmphost[256] = {0};
  430. char *tmpuri = NULL;
  431. for (size_t i = 0; i < tmplen; i++){
  432. if (tmp[i] == '/') {
  433. if (i > 255) {
  434. LLOGI("host too long %s", http_ctrl->url);
  435. return -1;
  436. }
  437. tmpuri = tmp + i;
  438. break;
  439. }else if(i == tmplen-1){
  440. tmphost[i+2] = '/';
  441. tmpuri = tmp + i+1;
  442. }
  443. tmphost[i] = tmp[i];
  444. }
  445. if (strlen(tmphost) < 1) {
  446. LLOGI("host not found %s", http_ctrl->url);
  447. return -1;
  448. }
  449. if (strlen(tmpuri) == 0) {
  450. tmpuri = "/";
  451. }
  452. // LLOGD("tmphost:%s",tmphost);
  453. // LLOGD("tmpuri:%s",tmpuri);
  454. for (size_t i = 1; i < strlen(tmphost); i++){
  455. if (tmphost[i] == ':') {
  456. tmphost[i] = '\0';
  457. http_ctrl->remote_port = atoi(tmphost + i + 1);
  458. break;
  459. }
  460. }
  461. if (http_ctrl->remote_port <= 0) {
  462. if (http_ctrl->is_tls)
  463. http_ctrl->remote_port = 443;
  464. else
  465. http_ctrl->remote_port = 80;
  466. }
  467. http_ctrl->host = luat_heap_malloc(strlen(tmphost) + 1);
  468. if (http_ctrl->host == NULL) {
  469. LLOGE("out of memory when malloc host");
  470. return -1;
  471. }
  472. memcpy(http_ctrl->host, tmphost, strlen(tmphost) + 1);
  473. http_ctrl->uri = luat_heap_malloc(strlen(tmpuri) + 1);
  474. if (http_ctrl->uri == NULL) {
  475. LLOGE("out of memory when malloc url");
  476. return -1;
  477. }
  478. memcpy(http_ctrl->uri, tmpuri, strlen(tmpuri) + 1);
  479. // LLOGD("http_ctrl->uri:%s",http_ctrl->uri);
  480. // LLOGD("http_ctrl->host:%s",http_ctrl->host);
  481. // LLOGD("http_ctrl->port:%d",http_ctrl->remote_port);
  482. return 0;
  483. }
  484. /*
  485. http客户端
  486. @api http.request(method,url,headers,body,opts,ca_file)
  487. @string 请求方法, 支持 GET/POST
  488. @string url地址
  489. @tabal 请求头 可选 例如{["Content-Type"] = "application/x-www-form-urlencoded"}
  490. @string body 可选
  491. @table 额外配置 可选 包含 timeout:超时时间单位ms 可选,默认10分钟,写0即永久等待 dst:下载路径,可选 adapter:选择使用网卡,可选 debug:是否打开debug信息,可选,ipv6:是否为ipv6 默认不是,可选
  492. @string 服务器ca证书数据
  493. @string 客户端ca证书数据
  494. @string 客户端私钥加密数据
  495. @string 客户端私钥口令数据
  496. @return int code
  497. @return tabal headers
  498. @return string body
  499. @usage
  500. -- GET请求
  501. local code, headers, body = http.request("GET","http://site0.cn/api/httptest/simple/time").wait()
  502. log.info("http.get", code, headers, body)
  503. -- POST请求
  504. local code, headers, body = http.request("POST","http://httpbin.com/post", {}, "abc=123").wait()
  505. log.info("http.post", code, headers, body)
  506. -- GET请求,但下载到文件
  507. local code, headers, body = http.request("GET","http://httpbin.com/", {}, "", {dst="/data.bin"}).wait()
  508. log.info("http.get", code, headers, body)
  509. */
  510. static int l_http_request(lua_State *L) {
  511. size_t server_cert_len,client_cert_len, client_key_len, client_password_len,len;
  512. const char *server_cert = NULL;
  513. const char *client_cert = NULL;
  514. const char *client_key = NULL;
  515. const char *client_password = NULL;
  516. int adapter_index = -1;
  517. char body_len[6] = {0};
  518. // mbedtls_debug_set_threshold(4);
  519. luat_http_ctrl_t *http_ctrl = (luat_http_ctrl_t *)luat_heap_malloc(sizeof(luat_http_ctrl_t));
  520. if (!http_ctrl){
  521. LLOGE("out of memory when malloc http_ctrl");
  522. lua_pushinteger(L,HTTP_ERROR_CONNECT);
  523. luat_pushcwait_error(L,1);
  524. return 1;
  525. }
  526. memset(http_ctrl, 0, sizeof(luat_http_ctrl_t));
  527. http_ctrl->timeout = HTTP_TIMEOUT;
  528. int use_ipv6 = 0;
  529. if (lua_istable(L, 5)){
  530. lua_pushstring(L, "adapter");
  531. if (LUA_TNUMBER == lua_gettable(L, 5)) {
  532. adapter_index = luaL_optinteger(L, -1, network_get_last_register_adapter());
  533. }else{
  534. adapter_index = network_get_last_register_adapter();
  535. }
  536. lua_pop(L, 1);
  537. lua_pushstring(L, "timeout");
  538. if (LUA_TNUMBER == lua_gettable(L, 5)) {
  539. http_ctrl->timeout = luaL_optinteger(L, -1, HTTP_TIMEOUT);
  540. }
  541. lua_pop(L, 1);
  542. lua_pushstring(L, "dst");
  543. if (LUA_TSTRING == lua_gettable(L, 5)) {
  544. const char *dst = luaL_checklstring(L, -1, &len);
  545. http_ctrl->dst = luat_heap_malloc(len + 1);
  546. memset(http_ctrl->dst, 0, len + 1);
  547. memcpy(http_ctrl->dst, dst, len);
  548. http_ctrl->is_download = 1;
  549. }
  550. lua_pop(L, 1);
  551. lua_pushstring(L, "debug");
  552. if (LUA_TBOOLEAN == lua_gettable(L, 5)) {
  553. http_ctrl->netc->is_debug = lua_toboolean(L, -1);
  554. }
  555. lua_pop(L, 1);
  556. lua_pushstring(L, "ipv6");
  557. if (LUA_TBOOLEAN == lua_gettable(L, 5) && lua_toboolean(L, -1)) {
  558. use_ipv6 = 1;
  559. }
  560. lua_pop(L, 1);
  561. }else{
  562. adapter_index = network_get_last_register_adapter();
  563. }
  564. if (adapter_index < 0 || adapter_index >= NW_ADAPTER_QTY){
  565. LLOGD("bad network adapter index %d", adapter_index);
  566. goto error;
  567. }
  568. http_ctrl->netc = network_alloc_ctrl(adapter_index);
  569. if (!http_ctrl->netc){
  570. LLOGE("netc create fail");
  571. goto error;
  572. }
  573. network_init_ctrl(http_ctrl->netc, NULL, luat_lib_http_callback, http_ctrl);
  574. network_set_base_mode(http_ctrl->netc, 1, 10000, 0, 0, 0, 0);
  575. network_set_local_port(http_ctrl->netc, 0);
  576. if (use_ipv6) {
  577. LLOGI("enable ipv6 support for http request");
  578. network_connect_ipv6_domain(http_ctrl->netc, 1);
  579. }
  580. http_parser_init(&http_ctrl->parser, HTTP_RESPONSE);
  581. http_ctrl->parser.data = http_ctrl;
  582. http_parser_settings_init(&http_ctrl->parser_settings);
  583. // http_ctrl->parser_settings.on_message_begin = on_message_begin;
  584. // http_ctrl->parser_settings.on_url = on_url;
  585. // http_ctrl->parser_settings.on_status = on_status;
  586. http_ctrl->parser_settings.on_header_field = on_header_field;
  587. http_ctrl->parser_settings.on_header_value = on_header_value;
  588. http_ctrl->parser_settings.on_headers_complete = on_headers_complete;
  589. http_ctrl->parser_settings.on_body = on_body;
  590. http_ctrl->parser_settings.on_message_complete = on_message_complete;
  591. http_ctrl->parser_settings.on_chunk_header = on_chunk_header;
  592. // http_ctrl->parser_settings.on_chunk_complete = on_chunk_complete;
  593. const char *method = luaL_optlstring(L, 1, "GET", &len);
  594. if (len > 11) {
  595. LLOGE("method is too long %s", method);
  596. goto error;
  597. }
  598. memcpy(http_ctrl->method, method, len + 1);
  599. // LLOGD("method:%s",http_ctrl->method);
  600. const char *url = luaL_checklstring(L, 2, &len);
  601. http_ctrl->url = luat_heap_malloc(len + 1);
  602. memset(http_ctrl->url, 0, len + 1);
  603. memcpy(http_ctrl->url, url, len);
  604. // LLOGD("http_ctrl->url:%s",http_ctrl->url);
  605. http_ctrl->req_header = luat_heap_malloc(HTTP_RESP_HEADER_MAX_SIZE);
  606. memset(http_ctrl->req_header, 0, HTTP_RESP_HEADER_MAX_SIZE);
  607. if (lua_istable(L, 3)) {
  608. lua_pushnil(L);
  609. while (lua_next(L, 3) != 0) {
  610. const char *name = lua_tostring(L, -2);
  611. const char *value = lua_tostring(L, -1);
  612. http_add_header(http_ctrl,name,value);
  613. lua_pop(L, 1);
  614. }
  615. }
  616. if (lua_isstring(L, 4)) {
  617. const char *body = luaL_checklstring(L, 4, &(http_ctrl->req_body_len));
  618. http_ctrl->req_body = luat_heap_malloc((http_ctrl->req_body_len) + 1);
  619. memset(http_ctrl->req_body, 0, (http_ctrl->req_body_len) + 1);
  620. memcpy(http_ctrl->req_body, body, (http_ctrl->req_body_len));
  621. snprintf_(body_len, 6,"%d",(http_ctrl->req_body_len));
  622. http_add_header(http_ctrl,"Content-Length",body_len);
  623. }
  624. // else{
  625. // http_add_header(http_ctrl,"Content-Length","0");
  626. // }
  627. int ret = http_set_url(http_ctrl);
  628. if (ret){
  629. goto error;
  630. }
  631. if (http_ctrl->is_tls){
  632. if (lua_isstring(L, 6)){
  633. server_cert = luaL_checklstring(L, 6, &server_cert_len);
  634. }
  635. if (lua_isstring(L, 7)){
  636. client_cert = luaL_checklstring(L, 7, &client_cert_len);
  637. }
  638. if (lua_isstring(L, 8)){
  639. client_key = luaL_checklstring(L, 8, &client_key_len);
  640. }
  641. if (lua_isstring(L, 9)){
  642. client_password = luaL_checklstring(L, 9, &client_password_len);
  643. }
  644. network_init_tls(http_ctrl->netc, (server_cert || client_cert)?2:0);
  645. if (server_cert){
  646. network_set_server_cert(http_ctrl->netc, (const unsigned char *)server_cert, server_cert_len+1);
  647. }
  648. if (client_cert){
  649. network_set_client_cert(http_ctrl->netc, client_cert, client_cert_len+1,
  650. client_key, client_key_len+1,
  651. client_password, client_password_len+1);
  652. }
  653. }else{
  654. network_deinit_tls(http_ctrl->netc);
  655. }
  656. #ifdef LUAT_USE_LWIP
  657. http_ctrl->ip_addr.type = 0xff;
  658. #else
  659. http_ctrl->ip_addr.is_ipv6 = 0xff;
  660. #endif
  661. http_ctrl->idp = luat_pushcwait(L);
  662. if(http_ctrl->timeout){
  663. http_ctrl->timeout_timer = luat_create_rtos_timer(luat_http_timer_callback, http_ctrl, NULL);
  664. luat_start_rtos_timer(http_ctrl->timeout_timer, http_ctrl->timeout, 0);
  665. }
  666. #ifdef LUAT_USE_LWIP
  667. if(network_connect(http_ctrl->netc, http_ctrl->host, strlen(http_ctrl->host), (0xff == http_ctrl->ip_addr.type)?NULL:&(http_ctrl->ip_addr), http_ctrl->remote_port, 0) < 0){
  668. #else
  669. if(network_connect(http_ctrl->netc, http_ctrl->host, strlen(http_ctrl->host), (0xff == http_ctrl->ip_addr.is_ipv6)?NULL:&(http_ctrl->ip_addr), http_ctrl->remote_port, 0) < 0){
  670. #endif
  671. network_close(http_ctrl->netc, 0);
  672. goto error;
  673. }
  674. return 1;
  675. error:
  676. http_close(http_ctrl);
  677. lua_pushinteger(L,HTTP_ERROR_CONNECT);
  678. luat_pushcwait_error(L,1);
  679. return 1;
  680. }
  681. #include "rotable2.h"
  682. static const rotable_Reg_t reg_http[] =
  683. {
  684. {"request", ROREG_FUNC(l_http_request)},
  685. { NULL, ROREG_INT(0)}
  686. };
  687. static const rotable_Reg_t reg_http_emtry[] =
  688. {
  689. { NULL, ROREG_INT(0)}
  690. };
  691. LUAMOD_API int luaopen_http( lua_State *L ) {
  692. #ifdef LUAT_USE_NETWORK
  693. luat_newlib2(L, reg_http);
  694. #else
  695. luat_newlib2(L, reg_http_emtry);
  696. LLOGE("reg_http require network enable!!");
  697. #endif
  698. lua_pushvalue(L, -1);
  699. lua_setglobal(L, "http2");
  700. return 1;
  701. }