HttpMessage.cpp 13 KB

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