1
0

http_content.cpp 8.2 KB

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