_requests.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #include "_requests.h"
  2. #include <ctype.h>
  3. #include "PikaObj.h"
  4. #include "_requests_Response.h"
  5. #include "webclient.h"
  6. #if !PIKASCRIPT_VERSION_REQUIRE_MINIMUN(1, 11, 9)
  7. #error "This library requires PikaScript version 1.11.9 or higher"
  8. #endif
  9. /* 标准输出函数 */
  10. #define RQ_print(fmt, ...) __platform_printf(fmt, ##__VA_ARGS__)
  11. #define RQ_cli(fmt, ...) __platform_printf(fmt, ##__VA_ARGS__)
  12. #define RQ_debug(fmt, ...) \
  13. {}
  14. /* #define RQ_debug(fmt, ...) __platform_printf("[RQ]:**|"fmt"|**\n",
  15. * ##__VA_ARGS__) */
  16. #define RQ_error_pointer(...) \
  17. RQ_print("[%s]: Checking NULL pointer of {" #__VA_ARGS__ "}.\n", __fun__)
  18. #define RQ_error_value(str, ...) \
  19. RQ_print("[%s]: Checking error value of {" #__VA_ARGS__ ":" str "}.\n", \
  20. __fun__, ##__VA_ARGS__)
  21. #define RQ_err(fmt, ...) RQ_print("[%s]:" fmt "\n", __VA_ARGS__)
  22. /* 补充常见宏定义 */
  23. #ifndef unlikely
  24. #define unlikely(x) __builtin_expect(!!(x), 0)
  25. #endif
  26. #ifndef likely
  27. #define likely(x) __builtin_expect(!!(x), 1)
  28. #endif
  29. /**
  30. * 现在支持可选的额外参数
  31. * params: 用于填充url参数,即get方法通过url传递数据
  32. * headers: 用于响应头信息填充
  33. * data: 负载内容
  34. * json: 负载内容
  35. * files: 负载内容
  36. * timeout: 超时设置
  37. * 实际上支持有限
  38. */
  39. int _requests_Response_request(PikaObj* self,
  40. char* method,
  41. char* url,
  42. pika_float timeout,
  43. char* data) {
  44. size_t data_len, resp_len; /* 长度信息 */
  45. void* resp_data; /* 返回的负载内容 */
  46. int32_t ret; /* 返回值 */
  47. struct webclient_session* session;
  48. session = (struct webclient_session*)obj_getPtr(self, "session_address");
  49. if (unlikely(session == NULL)) {
  50. RQ_cli("Sorry, can not operate NULL session object.\n");
  51. return -1;
  52. }
  53. if (unlikely(url == NULL)) {
  54. RQ_cli("Sorry, please give a specified url.\n");
  55. return -1;
  56. }
  57. RQ_debug("header length:%d", session->header->length);
  58. RQ_debug("header buffer:%.4096s", session->header->buffer);
  59. RQ_debug("header url:%.1024s", url);
  60. /* 进行post或者get操作 */
  61. if (strEqu(method, "GET")) {
  62. /* Get之后,header->buffer缓冲区内容会被清空 */
  63. /* FIXME: 保存一下header->buffer内容 */
  64. if (webclient_get2(session, url) != 200) {
  65. return -1;
  66. }
  67. ret = webclient_response(session, &resp_data, &resp_len);
  68. if (ret < 0) {
  69. return -1;
  70. }
  71. /* 正常得到了数据 */
  72. obj_setInt(self, "status_code", session->resp_status);
  73. obj_setInt(self, "content_length", resp_len);
  74. obj_setStr(self, "headers", session->header->buffer);
  75. /* 释放申请的缓冲区内存 */
  76. if (resp_data != NULL) {
  77. obj_setStr(self, "text", (char*)resp_data);
  78. web_free(resp_data);
  79. } else {
  80. obj_setStr(self, "text", "");
  81. }
  82. } else if (strEqu(method, "POST")) {
  83. if (data == NULL) {
  84. data_len = 0;
  85. } else {
  86. data_len = strlen(data);
  87. }
  88. /* FIXME: 默认二进制数据 */
  89. if (strstr(session->header->buffer, "Content-Length") == RT_NULL) {
  90. ret = webclient_header_fields_add(session, "Content-Length: %d\r\n",
  91. data_len);
  92. if (ret < 0) {
  93. return -1;
  94. }
  95. }
  96. if (strstr(session->header->buffer, "Content-Type") == RT_NULL) {
  97. /* 二进制数据流 */
  98. ret = webclient_header_fields_add(
  99. session, "Content-Type: application/octet-stream\r\n");
  100. if (ret < 0) {
  101. return -1;
  102. }
  103. }
  104. RQ_debug("header buffer:%.4096s", session->header->buffer);
  105. if (webclient_post(session, url, data, data_len) != 200) {
  106. return -1;
  107. }
  108. ret = webclient_response(session, &resp_data, &resp_len);
  109. if (ret < 0) {
  110. return -1;
  111. }
  112. /* 正常得到了数据 */
  113. obj_setInt(self, "status_code", session->resp_status);
  114. obj_setInt(self, "content_length", resp_len);
  115. obj_setStr(self, "headers", session->header->buffer);
  116. /* 释放申请的缓冲区内存 */
  117. if (resp_data != NULL) {
  118. obj_setStr(self, "text", (char*)resp_data);
  119. web_free(resp_data);
  120. } else {
  121. obj_setStr(self, "text", "");
  122. }
  123. } else {
  124. return -1;
  125. }
  126. return 1;
  127. }
  128. int _requests_Response_header_write(PikaObj* self, char* header, char* value) {
  129. struct webclient_session* session;
  130. session = (struct webclient_session*)obj_getPtr(self, "session_address");
  131. if (unlikely(session == NULL)) {
  132. RQ_cli("Sorry, can not operate NULL session object.\n");
  133. return -1;
  134. }
  135. RQ_debug("Add HTTP fileds:");
  136. /* 写入请求初始内容 */
  137. if (webclient_header_fields_add(session, "%s:%s\r\n", header, value) < 0) {
  138. RQ_cli("Sorry, request header too long.\n");
  139. return -1;
  140. }
  141. RQ_debug("buffer:%p.", session->header->buffer);
  142. return 1;
  143. }
  144. int _requests_Response_proto_write(PikaObj* self, char* proto) {
  145. struct webclient_session* session;
  146. session = (struct webclient_session*)obj_getPtr(self, "session_address");
  147. if (unlikely(session == NULL)) {
  148. RQ_cli("Sorry, can not operate NULL session object.\n");
  149. return -1;
  150. }
  151. /* TODO: 写入协议头之前可以保存 */
  152. RQ_debug("Add proto content:");
  153. /* 写入请求初始内容 */
  154. if (proto != NULL && *proto != 0) {
  155. if (webclient_header_fields_add(session, " %s\r\n", proto) < 0) {
  156. RQ_cli("Sorry, request header too long.\n");
  157. return -1;
  158. }
  159. } else {
  160. if (webclient_header_fields_add(session, " HTTP/1.1\r\n") < 0) {
  161. RQ_cli("Sorry, request header too long.\n");
  162. return -1;
  163. }
  164. }
  165. RQ_debug("buffer:%p.", session->header->buffer);
  166. return 1;
  167. }
  168. char to_hex(char code) {
  169. static char hex[] = "0123456789abcdef";
  170. return hex[code & 15];
  171. }
  172. int _requests_Response_urlencode_write(PikaObj* self,
  173. char* s1,
  174. char* s2,
  175. char* start,
  176. char* connect) {
  177. struct webclient_session* session;
  178. char *url_address, *p, *s;
  179. int32_t length, header_length;
  180. session = (struct webclient_session*)obj_getPtr(self, "session_address");
  181. if (unlikely(session == NULL)) {
  182. RQ_cli("Sorry, can not operate NULL session object.\n");
  183. return -1;
  184. }
  185. header_length = session->header->length;
  186. url_address = session->header->buffer + header_length;
  187. p = url_address;
  188. RQ_debug("Add url content:");
  189. RQ_debug("buffer:%p,len:%d.", session->header->buffer, header_length);
  190. RQ_debug("%s%s%s%s", start, s1, connect, s2);
  191. if (*start == 0) {
  192. while (*s1) {
  193. *p++ = *s1++;
  194. }
  195. goto end;
  196. }
  197. if (start != NULL) {
  198. /* 写入前置符号 */
  199. s = (char*)start;
  200. while (*s) {
  201. *p++ = *s++;
  202. }
  203. }
  204. s = s1;
  205. while (*s) {
  206. if (isalnum(*s) || *s == '-' || *s == '_' || *s == '.' || *s == '~') {
  207. *p++ = *s;
  208. } else if (*s == ' ') {
  209. *p++ = '+';
  210. } else {
  211. *p++ = '%';
  212. *p++ = to_hex(*s >> 4);
  213. *p++ = to_hex(*s & 0xf);
  214. }
  215. s++;
  216. }
  217. if (connect != NULL) {
  218. /* 写入连接符号 */
  219. s = (char*)connect;
  220. while (*s) {
  221. *p++ = *s++;
  222. }
  223. }
  224. s = (char*)s2;
  225. if (s != NULL) {
  226. while (*s) {
  227. if (isalnum(*s) || *s == '-' || *s == '_' || *s == '.' ||
  228. *s == '~') {
  229. *p++ = *s;
  230. } else if (*s == ' ') {
  231. *p++ = '+';
  232. } else {
  233. *p++ = '%';
  234. *p++ = to_hex(*s >> 4);
  235. *p++ = to_hex(*s & 0xf);
  236. }
  237. s++;
  238. }
  239. }
  240. end:
  241. *p = '\0';
  242. length = p - url_address;
  243. length += header_length;
  244. if (length > session->header->size) {
  245. RQ_cli("Error, header buffer has overflowed: {%d}.\n", length);
  246. return -1;
  247. }
  248. /* 更新长度信息 */
  249. session->header->length = length;
  250. RQ_debug("context:%.1024s.", session->header->buffer);
  251. RQ_debug("url length add:%d.", length);
  252. return 1;
  253. }
  254. int _requests_Response_request_init(PikaObj* self, char* method) {
  255. /* 创建会话对象,header长度固定 */
  256. struct webclient_session* session;
  257. char* temp;
  258. if (unlikely((strEqu(method, "GET") || strEqu(method, "POST")) == 0)) {
  259. /* 目前仅支持两种方法 */
  260. RQ_cli("Sorry, now only support method: GET and POST.\n");
  261. return -1;
  262. }
  263. session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
  264. if (session == RT_NULL) {
  265. RQ_cli("Sorry, memeory is not enough.\n");
  266. obj_setPtr(self, "session_address", NULL);
  267. return -1;
  268. } else {
  269. /* 写入请求初始内容 */
  270. if (webclient_header_fields_add(session, "%s ", method) < 0) {
  271. _requests_Response_request_del(self);
  272. RQ_cli("Sorry, request header too long.\n");
  273. return -1;
  274. }
  275. temp = session->header->buffer + session->header->length;
  276. RQ_debug("buffer address:%p.", session->header->buffer);
  277. RQ_debug("url address:%p.", temp);
  278. RQ_debug("headers start:%.10s.", session->header->buffer);
  279. obj_setPtr(self, "url_address", temp);
  280. obj_setPtr(self, "session_address", session);
  281. }
  282. RQ_debug("Response deal session memory.");
  283. return 1;
  284. }
  285. void _requests_Response_request_del(PikaObj* self) {
  286. struct webclient_session* session;
  287. session = (struct webclient_session*)obj_getPtr(self, "session_address");
  288. if (session) {
  289. webclient_close(session);
  290. RQ_debug("Response free session memory.");
  291. }
  292. RQ_debug("Response set variables None.");
  293. }
  294. void _requests_Response___del__(PikaObj* self) {
  295. _requests_Response_request_del(self);
  296. RQ_debug("Response class deleted.");
  297. }
  298. void _requests_Response___init__(PikaObj* self) {
  299. /* 初始化 */
  300. obj_setNone(self, "url");
  301. obj_setNone(self, "text");
  302. obj_setNone(self, "headers");
  303. obj_setPtr(self, "session_address", NULL);
  304. RQ_debug("Response class initialized.");
  305. }