http_content.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include "http_content.h"
  2. #include "hurl.h"
  3. #include <string.h>
  4. std::string dump_query_params(QueryParams& query_params) {
  5. std::string query_string;
  6. for (auto& pair : query_params) {
  7. if (query_string.size() != 0) {
  8. query_string += '&';
  9. }
  10. query_string += url_escape(pair.first.c_str());
  11. query_string += '=';
  12. query_string += url_escape(pair.second.c_str());
  13. }
  14. return query_string;
  15. }
  16. int parse_query_params(const char* query_string, QueryParams& query_params) {
  17. const char* p = strchr(query_string, '?');
  18. p = p ? p+1 : query_string;
  19. enum {
  20. s_key,
  21. s_value,
  22. } state = s_key;
  23. const char* key = p;
  24. const char* value = NULL;
  25. int key_len = 0;
  26. int value_len = 0;
  27. while (*p != '\0') {
  28. if (*p == '&') {
  29. if (key_len && value_len) {
  30. std::string strkey = std::string(key, key_len);
  31. std::string strvalue = std::string(value, value_len);
  32. query_params[url_unescape(strkey.c_str())] = url_unescape(strvalue.c_str());
  33. key_len = value_len = 0;
  34. }
  35. state = s_key;
  36. key = p+1;
  37. }
  38. else if (*p == '=') {
  39. state = s_value;
  40. value = p+1;
  41. }
  42. else {
  43. state == s_key ? ++key_len : ++value_len;
  44. }
  45. ++p;
  46. }
  47. if (key_len && value_len) {
  48. std::string strkey = std::string(key, key_len);
  49. std::string strvalue = std::string(value, value_len);
  50. query_params[url_unescape(strkey.c_str())] = url_unescape(strvalue.c_str());
  51. key_len = value_len = 0;
  52. }
  53. return query_params.size() == 0 ? -1 : 0;
  54. }
  55. #ifndef WITHOUT_HTTP_CONTENT
  56. #include <sys/types.h>
  57. #include <sys/stat.h>
  58. #include "hstring.h" // for split
  59. #include "httpdef.h" // for http_content_type_str_by_suffix
  60. std::string dump_multipart(MultiPart& mp, const char* boundary) {
  61. char c_str[256] = {0};
  62. std::string str;
  63. for (auto& pair : mp) {
  64. str += "--";
  65. str += boundary;
  66. str += "\r\n";
  67. str += "Content-Disposition: form-data";
  68. snprintf(c_str, sizeof(c_str), "; name=\"%s\"", pair.first.c_str());
  69. str += c_str;
  70. auto& form = pair.second;
  71. if (form.filename.size() != 0) {
  72. if (form.content.size() == 0) {
  73. FILE* fp = fopen(form.filename.c_str(), "r");
  74. if (fp) {
  75. struct stat st;
  76. if (stat(form.filename.c_str(), &st) == 0 && st.st_size != 0) {
  77. form.content.resize(st.st_size);
  78. fread((void*)form.content.data(), 1, st.st_size, fp);
  79. }
  80. fclose(fp);
  81. }
  82. }
  83. snprintf(c_str, sizeof(c_str), "; filename=\"%s\"", basename(form.filename).c_str());
  84. str += c_str;
  85. const char* suffix = strrchr(form.filename.c_str(), '.');
  86. if (suffix) {
  87. const char* stype = http_content_type_str_by_suffix(++suffix);
  88. if (stype && *stype != '\0') {
  89. str += "\r\n";
  90. str += "Content-Type: ";
  91. str += stype;
  92. }
  93. }
  94. }
  95. str += "\r\n\r\n";
  96. str += form.content;
  97. str += "\r\n";
  98. }
  99. str += "--";
  100. str += boundary;
  101. str += "--";
  102. return str;
  103. }
  104. #include "multipart_parser.h"
  105. enum multipart_parser_state_e {
  106. MP_START,
  107. MP_PART_DATA_BEGIN,
  108. MP_HEADER_FIELD,
  109. MP_HEADER_VALUE,
  110. MP_HEADERS_COMPLETE,
  111. MP_PART_DATA,
  112. MP_PART_DATA_END,
  113. MP_BODY_END
  114. };
  115. struct multipart_parser_userdata {
  116. MultiPart* mp;
  117. // tmp
  118. multipart_parser_state_e state;
  119. std::string header_field;
  120. std::string header_value;
  121. std::string part_data;
  122. std::string name;
  123. std::string filename;
  124. void handle_header() {
  125. if (header_field.size() == 0 || header_value.size() == 0) return;
  126. if (stricmp(header_field.c_str(), "Content-Disposition") == 0) {
  127. StringList strlist = split(header_value, ';');
  128. for (auto& str : strlist) {
  129. StringList kv = split(trim(str, " "), '=');
  130. if (kv.size() == 2) {
  131. const char* key = kv.begin()->c_str();
  132. string value = *(kv.begin() + 1);
  133. value = trim_pairs(value, "\"\"\'\'");
  134. if (strcmp(key, "name") == 0) {
  135. name = value;
  136. }
  137. else if (strcmp(key, "filename") == 0) {
  138. filename = value;
  139. }
  140. }
  141. }
  142. }
  143. header_field.clear();
  144. header_value.clear();
  145. }
  146. void handle_data() {
  147. if (name.size() != 0) {
  148. FormData formdata;
  149. formdata.content = part_data;
  150. formdata.filename = filename;
  151. (*mp)[name] = formdata;
  152. }
  153. name.clear();
  154. filename.clear();
  155. part_data.clear();
  156. }
  157. };
  158. static int on_header_field(multipart_parser* parser, const char *at, size_t length) {
  159. //printf("on_header_field:%.*s\n", (int)length, at);
  160. multipart_parser_userdata* userdata = (multipart_parser_userdata*)multipart_parser_get_data(parser);
  161. userdata->handle_header();
  162. userdata->state = MP_HEADER_FIELD;
  163. userdata->header_field.append(at, length);
  164. return 0;
  165. }
  166. static int on_header_value(multipart_parser* parser, const char *at, size_t length) {
  167. //printf("on_header_value:%.*s\n", (int)length, at);
  168. multipart_parser_userdata* userdata = (multipart_parser_userdata*)multipart_parser_get_data(parser);
  169. userdata->state = MP_HEADER_VALUE;
  170. userdata->header_value.append(at, length);
  171. return 0;
  172. }
  173. static int on_part_data(multipart_parser* parser, const char *at, size_t length) {
  174. //printf("on_part_data:%.*s\n", (int)length, at);
  175. multipart_parser_userdata* userdata = (multipart_parser_userdata*)multipart_parser_get_data(parser);
  176. userdata->state = MP_PART_DATA;
  177. userdata->part_data.append(at, length);
  178. return 0;
  179. }
  180. static int on_part_data_begin(multipart_parser* parser) {
  181. //printf("on_part_data_begin\n");
  182. multipart_parser_userdata* userdata = (multipart_parser_userdata*)multipart_parser_get_data(parser);
  183. userdata->state = MP_PART_DATA_BEGIN;
  184. return 0;
  185. }
  186. static int on_headers_complete(multipart_parser* parser) {
  187. //printf("on_headers_complete\n");
  188. multipart_parser_userdata* userdata = (multipart_parser_userdata*)multipart_parser_get_data(parser);
  189. userdata->handle_header();
  190. userdata->state = MP_HEADERS_COMPLETE;
  191. return 0;
  192. }
  193. static int on_part_data_end(multipart_parser* parser) {
  194. //printf("on_part_data_end\n");
  195. multipart_parser_userdata* userdata = (multipart_parser_userdata*)multipart_parser_get_data(parser);
  196. userdata->state = MP_PART_DATA_END;
  197. userdata->handle_data();
  198. return 0;
  199. }
  200. static int on_body_end(multipart_parser* parser) {
  201. //printf("on_body_end\n");
  202. multipart_parser_userdata* userdata = (multipart_parser_userdata*)multipart_parser_get_data(parser);
  203. userdata->state = MP_BODY_END;
  204. return 0;
  205. }
  206. int parse_multipart(std::string& str, MultiPart& mp, const char* boundary) {
  207. //printf("boundary=%s\n", boundary);
  208. std::string __boundary("--");
  209. __boundary += boundary;
  210. multipart_parser_settings settings;
  211. settings.on_header_field = on_header_field;
  212. settings.on_header_value = on_header_value;
  213. settings.on_part_data = on_part_data;
  214. settings.on_part_data_begin = on_part_data_begin;
  215. settings.on_headers_complete = on_headers_complete;
  216. settings.on_part_data_end = on_part_data_end;
  217. settings.on_body_end = on_body_end;
  218. multipart_parser* parser = multipart_parser_init(__boundary.c_str(), &settings);
  219. multipart_parser_userdata userdata;
  220. userdata.state = MP_START;
  221. userdata.mp = &mp;
  222. multipart_parser_set_data(parser, &userdata);
  223. size_t nparse = multipart_parser_execute(parser, str.c_str(), str.size());
  224. multipart_parser_free(parser);
  225. return nparse == str.size() ? 0 : -1;
  226. }
  227. std::string dump_json(hv::Json& json) {
  228. return json.dump();
  229. }
  230. int parse_json(const char* str, hv::Json& json, std::string& errmsg) {
  231. try {
  232. json = nlohmann::json::parse(str);
  233. }
  234. catch(nlohmann::detail::exception e) {
  235. errmsg = e.what();
  236. return -1;
  237. }
  238. return (json.is_discarded() || json.is_null()) ? -1 : 0;
  239. }
  240. #endif