HttpMessage.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #include "HttpMessage.h"
  2. #include <string.h>
  3. #include "http_parser.h" // for http_parser_url
  4. void HttpMessage::FillContentType() {
  5. auto iter = headers.find("Content-Type");
  6. if (iter != headers.end()) {
  7. content_type = http_content_type_enum(iter->second.c_str());
  8. goto append;
  9. }
  10. #ifndef WITHOUT_HTTP_CONTENT
  11. if (content_type == CONTENT_TYPE_NONE) {
  12. if (json.size() != 0) {
  13. content_type = APPLICATION_JSON;
  14. }
  15. else if (mp.size() != 0) {
  16. content_type = MULTIPART_FORM_DATA;
  17. }
  18. else if (kv.size() != 0) {
  19. content_type = X_WWW_FORM_URLENCODED;
  20. }
  21. else if (body.size() != 0) {
  22. content_type = TEXT_PLAIN;
  23. }
  24. }
  25. #endif
  26. if (content_type != CONTENT_TYPE_NONE) {
  27. headers["Content-Type"] = http_content_type_str(content_type);
  28. }
  29. append:
  30. #ifndef WITHOUT_HTTP_CONTENT
  31. if (content_type == MULTIPART_FORM_DATA) {
  32. auto iter = headers.find("Content-Type");
  33. if (iter != headers.end()) {
  34. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  35. if (boundary == NULL) {
  36. boundary = DEFAULT_MULTIPART_BOUNDARY;
  37. iter->second += "; boundary=";
  38. iter->second += boundary;
  39. }
  40. }
  41. }
  42. #endif
  43. return;
  44. }
  45. void HttpMessage::FillContentLength() {
  46. auto iter = headers.find("Content-Length");
  47. if (iter == headers.end()) {
  48. if (content_length == 0) {
  49. content_length = body.size();
  50. }
  51. headers["Content-Length"] = asprintf("%d", content_length);
  52. }
  53. else {
  54. content_length = atoi(iter->second.c_str());
  55. }
  56. }
  57. void HttpMessage::DumpHeaders(std::string& str) {
  58. FillContentType();
  59. FillContentLength();
  60. for (auto& header: headers) {
  61. // http2 :method :path :scheme :authority :status
  62. if (*str.c_str() != ':') {
  63. // %s: %s\r\n
  64. str += header.first;
  65. str += ": ";
  66. str += header.second;
  67. str += "\r\n";
  68. }
  69. }
  70. }
  71. void HttpMessage::DumpBody() {
  72. if (body.size() != 0) {
  73. return;
  74. }
  75. FillContentType();
  76. #ifndef WITHOUT_HTTP_CONTENT
  77. switch(content_type) {
  78. case APPLICATION_JSON:
  79. body = dump_json(json);
  80. break;
  81. case MULTIPART_FORM_DATA:
  82. {
  83. auto iter = headers.find("Content-Type");
  84. if (iter == headers.end()) {
  85. return;
  86. }
  87. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  88. if (boundary == NULL) {
  89. return;
  90. }
  91. boundary += strlen("boundary=");
  92. body = dump_multipart(mp, boundary);
  93. }
  94. break;
  95. case X_WWW_FORM_URLENCODED:
  96. body = dump_query_params(kv);
  97. break;
  98. default:
  99. // nothing to do
  100. break;
  101. }
  102. #endif
  103. }
  104. int HttpMessage::ParseBody() {
  105. if (body.size() == 0) {
  106. return -1;
  107. }
  108. FillContentType();
  109. #ifndef WITHOUT_HTTP_CONTENT
  110. switch(content_type) {
  111. case APPLICATION_JSON:
  112. return parse_json(body.c_str(), json);
  113. case MULTIPART_FORM_DATA:
  114. {
  115. auto iter = headers.find("Content-Type");
  116. if (iter == headers.end()) {
  117. return false;
  118. }
  119. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  120. if (boundary == NULL) {
  121. return false;
  122. }
  123. boundary += strlen("boundary=");
  124. return parse_multipart(body, mp, boundary);
  125. }
  126. case X_WWW_FORM_URLENCODED:
  127. return parse_query_params(body.c_str(), kv);
  128. default:
  129. // nothing to do
  130. return 0;
  131. }
  132. #endif
  133. return 0;
  134. }
  135. std::string HttpMessage::Dump(bool is_dump_headers, bool is_dump_body) {
  136. std::string str;
  137. if (is_dump_headers) {
  138. DumpHeaders(str);
  139. }
  140. str += "\r\n";
  141. if (is_dump_body) {
  142. DumpBody();
  143. if (ContentLength() != 0) {
  144. str.insert(str.size(), (const char*)Content(), ContentLength());
  145. }
  146. }
  147. return str;
  148. }
  149. void HttpRequest::DumpUrl() {
  150. if (url.size() != 0 && strncmp(url.c_str(), "http", 4) == 0) {
  151. // have been complete url
  152. return;
  153. }
  154. std::string str;
  155. // scheme://
  156. str += "http";
  157. if (https) str += 's';
  158. str += "://";
  159. // host:port
  160. char c_str[256] = {0};
  161. if (url.size() != 0 && *url.c_str() != '/') {
  162. // url begin with host
  163. str += url;
  164. }
  165. else {
  166. if (port == 0 ||
  167. port == DEFAULT_HTTP_PORT ||
  168. port == DEFAULT_HTTPS_PORT) {
  169. str += host;
  170. }
  171. else {
  172. snprintf(c_str, sizeof(c_str), "%s:%d", host.c_str(), port);
  173. str += c_str;
  174. }
  175. }
  176. // /path
  177. if (url.size() != 0 && *url.c_str() == '/') {
  178. // url begin with path
  179. str += url;
  180. }
  181. else if (path.size() > 1 && *path.c_str() == '/') {
  182. str += path;
  183. }
  184. else if (url.size() == 0) {
  185. str += '/';
  186. }
  187. // ?query
  188. if (strchr(str.c_str(), '?') == NULL &&
  189. query_params.size() != 0) {
  190. str += '?';
  191. str += dump_query_params(query_params);
  192. }
  193. url = str;
  194. }
  195. void HttpRequest::ParseUrl() {
  196. DumpUrl();
  197. http_parser_url parser;
  198. http_parser_url_init(&parser);
  199. http_parser_parse_url(url.c_str(), url.size(), 0, &parser);
  200. // scheme
  201. https = !strncmp(url.c_str(), "https", 5);
  202. // host
  203. if (parser.field_set & (1<<UF_HOST)) {
  204. host = url.substr(parser.field_data[UF_HOST].off, parser.field_data[UF_HOST].len);
  205. }
  206. // port
  207. port = parser.port ? parser.port : https ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT;
  208. // path
  209. if (parser.field_set & (1<<UF_PATH)) {
  210. path = url.c_str() + parser.field_data[UF_PATH].off;
  211. }
  212. // query
  213. if (parser.field_set & (1<<UF_QUERY)) {
  214. parse_query_params(url.c_str()+parser.field_data[UF_QUERY].off, query_params);
  215. }
  216. }
  217. std::string HttpRequest::Dump(bool is_dump_headers, bool is_dump_body) {
  218. ParseUrl();
  219. char c_str[256] = {0};
  220. std::string str;
  221. // GET / HTTP/1.1\r\n
  222. snprintf(c_str, sizeof(c_str), "%s %s HTTP/%d.%d\r\n", http_method_str(method), path.c_str(), http_major, http_minor);
  223. str += c_str;
  224. if (is_dump_headers) {
  225. // Host:
  226. if (headers.find("Host") == headers.end()) {
  227. if (port == 0 ||
  228. port == DEFAULT_HTTP_PORT ||
  229. port == DEFAULT_HTTPS_PORT) {
  230. headers["Host"] = host;
  231. }
  232. else {
  233. snprintf(c_str, sizeof(c_str), "%s:%d", host.c_str(), port);
  234. headers["Host"] = c_str;
  235. }
  236. }
  237. DumpHeaders(str);
  238. }
  239. str += "\r\n";
  240. if (is_dump_body) {
  241. DumpBody();
  242. if (ContentLength() != 0) {
  243. str.insert(str.size(), (const char*)Content(), ContentLength());
  244. }
  245. }
  246. return str;
  247. }
  248. #include <time.h>
  249. std::string HttpResponse::Dump(bool is_dump_headers, bool is_dump_body) {
  250. char c_str[256] = {0};
  251. std::string str;
  252. // HTTP/1.1 200 OK\r\n
  253. snprintf(c_str, sizeof(c_str), "HTTP/%d.%d %d %s\r\n", http_major, http_minor, status_code, http_status_str(status_code));
  254. str += c_str;
  255. if (is_dump_headers) {
  256. // Date:
  257. time_t tt;
  258. time(&tt);
  259. strftime(c_str, sizeof(c_str), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&tt));
  260. headers["Date"] = c_str;
  261. DumpHeaders(str);
  262. }
  263. str += "\r\n";
  264. if (is_dump_body) {
  265. DumpBody();
  266. if (ContentLength() != 0) {
  267. str.insert(str.size(), (const char*)Content(), ContentLength());
  268. }
  269. }
  270. return str;
  271. }