http.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /******************************************************************************
  2. * HTTP module for NodeMCU
  3. * vowstar@gmail.com
  4. * 2015-12-29
  5. *******************************************************************************/
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include "module.h"
  9. #include "lauxlib.h"
  10. #include "platform.h"
  11. #include "cpu_esp8266.h"
  12. #include "http/httpclient.h"
  13. #include <ctype.h>
  14. static int http_callback_registry = LUA_NOREF;
  15. static void http_callback( char * response, int http_status, char ** full_response_p, int body_size )
  16. {
  17. const char *full_response = full_response_p ? *full_response_p : NULL;
  18. #if defined(HTTPCLIENT_DEBUG_ON)
  19. dbg_printf( "http_status=%d\n", http_status );
  20. if ( http_status != HTTP_STATUS_GENERIC_ERROR )
  21. {
  22. if (full_response != NULL) {
  23. dbg_printf( "strlen(full_response)=%d\n", strlen( full_response ) );
  24. }
  25. dbg_printf( "response=%s<EOF>\n", response );
  26. }
  27. #endif
  28. if (http_callback_registry != LUA_NOREF)
  29. {
  30. lua_State *L = lua_getstate();
  31. lua_rawgeti(L, LUA_REGISTRYINDEX, http_callback_registry);
  32. lua_pushnumber(L, http_status);
  33. if ( http_status != HTTP_STATUS_GENERIC_ERROR && response)
  34. {
  35. lua_pushlstring(L, response, (size_t)body_size);
  36. lua_newtable(L);
  37. const char *p = full_response;
  38. // Need to skip the HTTP/1.1 header line
  39. while (*p && *p != '\n') {
  40. p++;
  41. }
  42. if (*p == '\n') {
  43. p++;
  44. }
  45. while (*p && *p != '\r' && *p != '\n') {
  46. const char *eol = p;
  47. while (*eol && *eol != '\r') {
  48. eol++;
  49. }
  50. const char *colon = p;
  51. while (*colon != ':' && colon < eol) {
  52. colon++;
  53. }
  54. if (*colon != ':') {
  55. break;
  56. }
  57. const char *value = colon + 1;
  58. while (*value == ' ') {
  59. value++;
  60. }
  61. luaL_Buffer b;
  62. luaL_buffinit(L, &b);
  63. while (p < colon) {
  64. luaL_addchar(&b, tolower((unsigned char) *p));
  65. p++;
  66. }
  67. luaL_pushresult(&b);
  68. lua_pushlstring(L, value, eol - value);
  69. lua_settable(L, -3);
  70. p = eol + 1;
  71. if (*p == '\n') {
  72. p++;
  73. }
  74. }
  75. }
  76. else
  77. {
  78. lua_pushnil(L);
  79. lua_pushnil(L);
  80. }
  81. if (full_response_p && *full_response_p) {
  82. free(*full_response_p);
  83. *full_response_p = NULL;
  84. }
  85. luaL_unref(L, LUA_REGISTRYINDEX, http_callback_registry);
  86. http_callback_registry = LUA_NOREF;
  87. luaL_pcallx(L, 3, 0); // With 3 arguments and 0 result
  88. }
  89. }
  90. // Lua: http.request( url, method, header, body, function(status, reponse) end )
  91. static int http_lapi_request( lua_State *L )
  92. {
  93. int length;
  94. const char * url = luaL_checklstring(L, 1, &length);
  95. const char * method = luaL_checklstring(L, 2, &length);
  96. const char * headers = NULL;
  97. const char * body = NULL;
  98. // Check parameter
  99. if ((url == NULL) || (method == NULL))
  100. {
  101. return luaL_error( L, "wrong arg type" );
  102. }
  103. if (lua_isstring(L, 3))
  104. {
  105. headers = luaL_checklstring(L, 3, &length);
  106. }
  107. if (lua_isstring(L, 4))
  108. {
  109. body = luaL_checklstring(L, 4, &length);
  110. }
  111. if (lua_isfunction(L, 5)) {
  112. lua_pushvalue(L, 5); // copy argument (func) to the top of stack
  113. luaL_unref(L, LUA_REGISTRYINDEX, http_callback_registry);
  114. http_callback_registry = luaL_ref(L, LUA_REGISTRYINDEX);
  115. }
  116. http_request(url, method, headers, body, http_callback, 0);
  117. return 0;
  118. }
  119. // Lua: http.post( url, header, body, function(status, reponse) end )
  120. static int http_lapi_post( lua_State *L )
  121. {
  122. int length;
  123. const char * url = luaL_checklstring(L, 1, &length);
  124. const char * headers = NULL;
  125. const char * body = NULL;
  126. // Check parameter
  127. if ((url == NULL))
  128. {
  129. return luaL_error( L, "wrong arg type" );
  130. }
  131. if (lua_isstring(L, 2))
  132. {
  133. headers = luaL_checklstring(L, 2, &length);
  134. }
  135. if (lua_isstring(L, 3))
  136. {
  137. body = luaL_checklstring(L, 3, &length);
  138. }
  139. if (lua_isfunction(L, 4)) {
  140. lua_pushvalue(L, 4); // copy argument (func) to the top of stack
  141. if (http_callback_registry != LUA_NOREF)
  142. luaL_unref(L, LUA_REGISTRYINDEX, http_callback_registry);
  143. http_callback_registry = luaL_ref(L, LUA_REGISTRYINDEX);
  144. }
  145. http_post(url, headers, body, http_callback);
  146. return 0;
  147. }
  148. // Lua: http.put( url, header, body, function(status, reponse) end )
  149. static int http_lapi_put( lua_State *L )
  150. {
  151. int length;
  152. const char * url = luaL_checklstring(L, 1, &length);
  153. const char * headers = NULL;
  154. const char * body = NULL;
  155. // Check parameter
  156. if ((url == NULL))
  157. {
  158. return luaL_error( L, "wrong arg type" );
  159. }
  160. if (lua_isstring(L, 2))
  161. {
  162. headers = luaL_checklstring(L, 2, &length);
  163. }
  164. if (lua_isstring(L, 3))
  165. {
  166. body = luaL_checklstring(L, 3, &length);
  167. }
  168. if (lua_isfunction(L, 4)) {
  169. lua_pushvalue(L, 4); // copy argument (func) to the top of stack
  170. if (http_callback_registry != LUA_NOREF)
  171. luaL_unref(L, LUA_REGISTRYINDEX, http_callback_registry);
  172. http_callback_registry = luaL_ref(L, LUA_REGISTRYINDEX);
  173. }
  174. http_put(url, headers, body, http_callback);
  175. return 0;
  176. }
  177. // Lua: http.delete( url, header, body, function(status, reponse) end )
  178. static int http_lapi_delete( lua_State *L )
  179. {
  180. int length;
  181. const char * url = luaL_checklstring(L, 1, &length);
  182. const char * headers = NULL;
  183. const char * body = NULL;
  184. // Check parameter
  185. if ((url == NULL))
  186. {
  187. return luaL_error( L, "wrong arg type" );
  188. }
  189. if (lua_isstring(L, 2))
  190. {
  191. headers = luaL_checklstring(L, 2, &length);
  192. }
  193. if (lua_isstring(L, 3))
  194. {
  195. body = luaL_checklstring(L, 3, &length);
  196. }
  197. if (lua_isfunction(L, 4)) {
  198. lua_pushvalue(L, 4); // copy argument (func) to the top of stack
  199. if (http_callback_registry != LUA_NOREF)
  200. luaL_unref(L, LUA_REGISTRYINDEX, http_callback_registry);
  201. http_callback_registry = luaL_ref(L, LUA_REGISTRYINDEX);
  202. }
  203. http_delete(url, headers, body, http_callback);
  204. return 0;
  205. }
  206. // Lua: http.get( url, header, function(status, reponse) end )
  207. static int http_lapi_get( lua_State *L )
  208. {
  209. int length;
  210. const char * url = luaL_checklstring(L, 1, &length);
  211. const char * headers = NULL;
  212. // Check parameter
  213. if ((url == NULL))
  214. {
  215. return luaL_error( L, "wrong arg type" );
  216. }
  217. if (lua_isstring(L, 2))
  218. {
  219. headers = luaL_checklstring(L, 2, &length);
  220. }
  221. if (lua_isfunction(L, 3)) {
  222. lua_pushvalue(L, 3); // copy argument (func) to the top of stack
  223. if (http_callback_registry != LUA_NOREF)
  224. luaL_unref(L, LUA_REGISTRYINDEX, http_callback_registry);
  225. http_callback_registry = luaL_ref(L, LUA_REGISTRYINDEX);
  226. }
  227. http_get(url, headers, http_callback);
  228. return 0;
  229. }
  230. // Module function map
  231. LROT_BEGIN(http, NULL, 0)
  232. LROT_FUNCENTRY( request, http_lapi_request )
  233. LROT_FUNCENTRY( post, http_lapi_post )
  234. LROT_FUNCENTRY( put, http_lapi_put )
  235. LROT_FUNCENTRY( delete, http_lapi_delete )
  236. LROT_FUNCENTRY( get, http_lapi_get )
  237. LROT_NUMENTRY( OK, 0 )
  238. LROT_NUMENTRY( ERROR, HTTP_STATUS_GENERIC_ERROR )
  239. LROT_END(http, NULL, 0)
  240. NODEMCU_MODULE(HTTP, "http", http, NULL);