HttpMessage.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. #include "HttpMessage.h"
  2. #include <string.h>
  3. #include "htime.h"
  4. #include "http_parser.h" // for http_parser_url
  5. #ifndef WITHOUT_HTTP_CONTENT
  6. // NOTE: json ignore number/string, 123/"123"
  7. using nlohmann::detail::value_t;
  8. std::string HttpMessage::GetString(const char* key, const std::string& defvalue) {
  9. switch (content_type) {
  10. case APPLICATION_JSON:
  11. {
  12. auto iter = json.find(key);
  13. if (iter != json.end()) {
  14. switch (iter->type()) {
  15. case value_t::null:
  16. return "null";
  17. case value_t::string:
  18. return *iter;
  19. case value_t::boolean:
  20. {
  21. bool b = *iter;
  22. return b ? "true" : "false";
  23. }
  24. case value_t::number_integer:
  25. {
  26. std::int64_t n = *iter;
  27. return hv::to_string(n);
  28. }
  29. case value_t::number_unsigned:
  30. {
  31. std::uint64_t n = *iter;
  32. return hv::to_string(n);
  33. }
  34. case value_t::number_float:
  35. {
  36. double f = *iter;
  37. return hv::to_string(f);
  38. }
  39. default:
  40. return defvalue;
  41. }
  42. }
  43. }
  44. break;
  45. case MULTIPART_FORM_DATA:
  46. {
  47. auto iter = form.find(key);
  48. if (iter != form.end()) {
  49. return iter->second.content;
  50. }
  51. }
  52. break;
  53. case APPLICATION_URLENCODED:
  54. {
  55. auto iter = kv.find(key);
  56. if (iter != kv.end()) {
  57. return iter->second;
  58. }
  59. }
  60. break;
  61. default:
  62. break;
  63. }
  64. return defvalue;
  65. }
  66. template<>
  67. int64_t HttpMessage::Get(const char* key, int64_t defvalue) {
  68. if (content_type == APPLICATION_JSON) {
  69. auto iter = json.find(key);
  70. if (iter != json.end()) {
  71. switch (iter->type()) {
  72. case value_t::boolean:
  73. {
  74. bool b = *iter;
  75. return b;
  76. }
  77. case value_t::number_integer:
  78. {
  79. std::int64_t n = *iter;
  80. return n;
  81. }
  82. case value_t::number_unsigned:
  83. {
  84. std::uint64_t n = *iter;
  85. return n;
  86. }
  87. case value_t::number_float:
  88. {
  89. double f = *iter;
  90. return f;
  91. }
  92. case value_t::string:
  93. {
  94. std::string str = *iter;
  95. return atoll(str.c_str());
  96. }
  97. default:
  98. return defvalue;
  99. }
  100. }
  101. return defvalue;
  102. }
  103. else {
  104. std::string str = GetString(key);
  105. return str.empty() ? defvalue : atoll(str.c_str());
  106. }
  107. }
  108. template<>
  109. double HttpMessage::Get(const char* key, double defvalue) {
  110. if (content_type == APPLICATION_JSON) {
  111. auto iter = json.find(key);
  112. if (iter != json.end()) {
  113. switch (iter->type()) {
  114. case value_t::boolean:
  115. {
  116. bool b = *iter;
  117. return b;
  118. }
  119. case value_t::number_integer:
  120. {
  121. std::int64_t n = *iter;
  122. return n;
  123. }
  124. case value_t::number_unsigned:
  125. {
  126. std::uint64_t n = *iter;
  127. return n;
  128. }
  129. case value_t::number_float:
  130. {
  131. double f = *iter;
  132. return f;
  133. }
  134. case value_t::string:
  135. {
  136. std::string str = *iter;
  137. return atof(str.c_str());
  138. }
  139. default:
  140. return defvalue;
  141. }
  142. }
  143. return defvalue;
  144. }
  145. else {
  146. std::string str = GetString(key);
  147. return str.empty() ? defvalue : atof(str.c_str());
  148. }
  149. }
  150. template<>
  151. bool HttpMessage::Get(const char* key, bool defvalue) {
  152. if (content_type == APPLICATION_JSON) {
  153. auto iter = json.find(key);
  154. if (iter != json.end()) {
  155. switch (iter->type()) {
  156. case value_t::boolean:
  157. {
  158. bool b = *iter;
  159. return b;
  160. }
  161. case value_t::number_integer:
  162. {
  163. std::int64_t n = *iter;
  164. return n;
  165. }
  166. case value_t::number_unsigned:
  167. {
  168. std::uint64_t n = *iter;
  169. return n;
  170. }
  171. case value_t::number_float:
  172. {
  173. double f = *iter;
  174. return f;
  175. }
  176. case value_t::string:
  177. {
  178. std::string str = *iter;
  179. return getboolean(str.c_str());
  180. }
  181. default:
  182. return defvalue;
  183. }
  184. }
  185. return defvalue;
  186. }
  187. else {
  188. std::string str = GetString(key);
  189. return str.empty() ? defvalue : getboolean(str.c_str());
  190. }
  191. }
  192. bool HttpMessage::GetBool(const char* key, bool defvalue) {
  193. return Get<bool>(key, defvalue);
  194. }
  195. int64_t HttpMessage::GetInt(const char* key, int64_t defvalue) {
  196. return Get<int64_t>(key, defvalue);
  197. }
  198. double HttpMessage::GetFloat(const char* key, double defvalue) {
  199. return Get<double>(key, defvalue);
  200. }
  201. #endif
  202. void HttpMessage::FillContentType() {
  203. auto iter = headers.find("Content-Type");
  204. if (iter != headers.end()) {
  205. content_type = http_content_type_enum(iter->second.c_str());
  206. goto append;
  207. }
  208. #ifndef WITHOUT_HTTP_CONTENT
  209. if (content_type == CONTENT_TYPE_NONE) {
  210. if (json.size() != 0) {
  211. content_type = APPLICATION_JSON;
  212. }
  213. else if (form.size() != 0) {
  214. content_type = MULTIPART_FORM_DATA;
  215. }
  216. else if (kv.size() != 0) {
  217. content_type = X_WWW_FORM_URLENCODED;
  218. }
  219. else if (body.size() != 0) {
  220. content_type = TEXT_PLAIN;
  221. }
  222. }
  223. #endif
  224. if (content_type != CONTENT_TYPE_NONE) {
  225. headers["Content-Type"] = http_content_type_str(content_type);
  226. }
  227. append:
  228. #ifndef WITHOUT_HTTP_CONTENT
  229. if (content_type == MULTIPART_FORM_DATA) {
  230. auto iter = headers.find("Content-Type");
  231. if (iter != headers.end()) {
  232. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  233. if (boundary == NULL) {
  234. boundary = DEFAULT_MULTIPART_BOUNDARY;
  235. iter->second += "; boundary=";
  236. iter->second += boundary;
  237. }
  238. }
  239. }
  240. #endif
  241. return;
  242. }
  243. void HttpMessage::FillContentLength() {
  244. auto iter = headers.find("Content-Length");
  245. if (iter != headers.end()) {
  246. content_length = atoi(iter->second.c_str());
  247. }
  248. if (iter == headers.end() || content_length == 0) {
  249. if (content_length == 0) {
  250. content_length = body.size();
  251. }
  252. if (content_length == 0) {
  253. DumpBody();
  254. content_length = body.size();
  255. }
  256. char sz[64];
  257. snprintf(sz, sizeof(sz), "%d", content_length);
  258. headers["Content-Length"] = sz;
  259. }
  260. }
  261. void HttpMessage::DumpHeaders(std::string& str) {
  262. FillContentType();
  263. FillContentLength();
  264. for (auto& header: headers) {
  265. // http2 :method :path :scheme :authority :status
  266. if (*str.c_str() != ':') {
  267. // %s: %s\r\n
  268. str += header.first;
  269. str += ": ";
  270. str += header.second;
  271. str += "\r\n";
  272. }
  273. }
  274. }
  275. void HttpMessage::DumpBody() {
  276. if (body.size() != 0) {
  277. return;
  278. }
  279. FillContentType();
  280. #ifndef WITHOUT_HTTP_CONTENT
  281. switch(content_type) {
  282. case APPLICATION_JSON:
  283. body = dump_json(json);
  284. break;
  285. case MULTIPART_FORM_DATA:
  286. {
  287. auto iter = headers.find("Content-Type");
  288. if (iter == headers.end()) {
  289. return;
  290. }
  291. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  292. if (boundary == NULL) {
  293. return;
  294. }
  295. boundary += strlen("boundary=");
  296. body = dump_multipart(form, boundary);
  297. }
  298. break;
  299. case X_WWW_FORM_URLENCODED:
  300. body = dump_query_params(kv);
  301. break;
  302. default:
  303. // nothing to do
  304. break;
  305. }
  306. #endif
  307. }
  308. int HttpMessage::ParseBody() {
  309. if (body.size() == 0) {
  310. return -1;
  311. }
  312. FillContentType();
  313. #ifndef WITHOUT_HTTP_CONTENT
  314. switch(content_type) {
  315. case APPLICATION_JSON:
  316. return parse_json(body.c_str(), json);
  317. case MULTIPART_FORM_DATA:
  318. {
  319. auto iter = headers.find("Content-Type");
  320. if (iter == headers.end()) {
  321. return false;
  322. }
  323. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  324. if (boundary == NULL) {
  325. return false;
  326. }
  327. boundary += strlen("boundary=");
  328. return parse_multipart(body, form, boundary);
  329. }
  330. case X_WWW_FORM_URLENCODED:
  331. return parse_query_params(body.c_str(), kv);
  332. default:
  333. // nothing to do
  334. return 0;
  335. }
  336. #endif
  337. return 0;
  338. }
  339. std::string HttpMessage::Dump(bool is_dump_headers, bool is_dump_body) {
  340. std::string str;
  341. if (is_dump_headers) {
  342. DumpHeaders(str);
  343. }
  344. str += "\r\n";
  345. if (is_dump_body) {
  346. DumpBody();
  347. if (ContentLength() != 0) {
  348. str.insert(str.size(), (const char*)Content(), ContentLength());
  349. }
  350. }
  351. return str;
  352. }
  353. void HttpRequest::DumpUrl() {
  354. if (url.size() != 0 && strncmp(url.c_str(), "http", 4) == 0) {
  355. // have been complete url
  356. return;
  357. }
  358. std::string str;
  359. // scheme://
  360. str += "http";
  361. if (https) str += 's';
  362. str += "://";
  363. // host:port
  364. char c_str[256] = {0};
  365. if (url.size() != 0 && *url.c_str() != '/') {
  366. // url begin with host
  367. str += url;
  368. }
  369. else {
  370. if (port == 0 ||
  371. port == DEFAULT_HTTP_PORT ||
  372. port == DEFAULT_HTTPS_PORT) {
  373. str += host;
  374. }
  375. else {
  376. snprintf(c_str, sizeof(c_str), "%s:%d", host.c_str(), port);
  377. str += c_str;
  378. }
  379. }
  380. // /path
  381. if (url.size() != 0 && *url.c_str() == '/') {
  382. // url begin with path
  383. str += url;
  384. }
  385. else if (path.size() > 1 && *path.c_str() == '/') {
  386. str += path;
  387. }
  388. else if (url.size() == 0) {
  389. str += '/';
  390. }
  391. // ?query
  392. if (strchr(str.c_str(), '?') == NULL &&
  393. query_params.size() != 0) {
  394. str += '?';
  395. str += dump_query_params(query_params);
  396. }
  397. url = str;
  398. }
  399. void HttpRequest::ParseUrl() {
  400. DumpUrl();
  401. http_parser_url parser;
  402. http_parser_url_init(&parser);
  403. http_parser_parse_url(url.c_str(), url.size(), 0, &parser);
  404. // scheme
  405. https = !strncmp(url.c_str(), "https", 5);
  406. // host
  407. if (parser.field_set & (1<<UF_HOST)) {
  408. host = url.substr(parser.field_data[UF_HOST].off, parser.field_data[UF_HOST].len);
  409. }
  410. // port
  411. port = parser.port ? parser.port : https ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT;
  412. // path
  413. if (parser.field_set & (1<<UF_PATH)) {
  414. path = url.c_str() + parser.field_data[UF_PATH].off;
  415. }
  416. // query
  417. if (parser.field_set & (1<<UF_QUERY)) {
  418. parse_query_params(url.c_str()+parser.field_data[UF_QUERY].off, query_params);
  419. }
  420. }
  421. std::string HttpRequest::Dump(bool is_dump_headers, bool is_dump_body) {
  422. ParseUrl();
  423. char c_str[256] = {0};
  424. std::string str;
  425. // GET / HTTP/1.1\r\n
  426. snprintf(c_str, sizeof(c_str), "%s %s HTTP/%d.%d\r\n", http_method_str(method), path.c_str(), http_major, http_minor);
  427. str += c_str;
  428. if (is_dump_headers) {
  429. // Host:
  430. if (headers.find("Host") == headers.end()) {
  431. if (port == 0 ||
  432. port == DEFAULT_HTTP_PORT ||
  433. port == DEFAULT_HTTPS_PORT) {
  434. headers["Host"] = host;
  435. }
  436. else {
  437. snprintf(c_str, sizeof(c_str), "%s:%d", host.c_str(), port);
  438. headers["Host"] = c_str;
  439. }
  440. }
  441. DumpHeaders(str);
  442. }
  443. str += "\r\n";
  444. if (is_dump_body) {
  445. DumpBody();
  446. if (ContentLength() != 0) {
  447. str.insert(str.size(), (const char*)Content(), ContentLength());
  448. }
  449. }
  450. return str;
  451. }
  452. std::string HttpResponse::Dump(bool is_dump_headers, bool is_dump_body) {
  453. char c_str[256] = {0};
  454. std::string str;
  455. // HTTP/1.1 200 OK\r\n
  456. snprintf(c_str, sizeof(c_str), "HTTP/%d.%d %d %s\r\n", http_major, http_minor, status_code, http_status_str(status_code));
  457. str += c_str;
  458. if (is_dump_headers) {
  459. headers["Date"] = gmtime_fmt(time(NULL), c_str);
  460. DumpHeaders(str);
  461. }
  462. str += "\r\n";
  463. if (is_dump_body) {
  464. DumpBody();
  465. if (ContentLength() != 0) {
  466. str.insert(str.size(), (const char*)Content(), ContentLength());
  467. }
  468. }
  469. return str;
  470. }