1
0

HttpMessage.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. #include "HttpMessage.h"
  2. #include <string.h>
  3. #include "htime.h"
  4. #include "hlog.h"
  5. #include "hurl.h"
  6. using namespace hv;
  7. http_headers DefaultHeaders;
  8. http_body NoBody;
  9. HttpCookie NoCookie;
  10. char HttpMessage::s_date[32] = {0};
  11. HttpCookie::HttpCookie() {
  12. init();
  13. }
  14. void HttpCookie::init() {
  15. max_age = 0;
  16. secure = false;
  17. httponly = false;
  18. samesite = Default;
  19. priority = NotSet;
  20. }
  21. void HttpCookie::reset() {
  22. init();
  23. name.clear();
  24. value.clear();
  25. domain.clear();
  26. path.clear();
  27. expires.clear();
  28. kv.clear();
  29. }
  30. bool HttpCookie::parse(const std::string& str) {
  31. std::stringstream ss;
  32. ss << str;
  33. std::string line;
  34. std::string::size_type pos;
  35. std::string key;
  36. std::string val;
  37. reset();
  38. while (std::getline(ss, line, ';')) {
  39. pos = line.find_first_of('=');
  40. if (pos != std::string::npos) {
  41. key = trim(line.substr(0, pos));
  42. val = trim(line.substr(pos+1));
  43. const char* pkey = key.c_str();
  44. if (stricmp(pkey, "Domain") == 0) {
  45. domain = val;
  46. }
  47. else if (stricmp(pkey, "Path") == 0) {
  48. path = val;
  49. }
  50. else if (stricmp(pkey, "Expires") == 0) {
  51. expires = val;
  52. }
  53. else if (stricmp(pkey, "Max-Age") == 0) {
  54. max_age = atoi(val.c_str());
  55. }
  56. else if (stricmp(pkey, "SameSite") == 0) {
  57. samesite = stricmp(val.c_str(), "Strict") == 0 ? HttpCookie::SameSite::Strict :
  58. stricmp(val.c_str(), "Lax") == 0 ? HttpCookie::SameSite::Lax :
  59. stricmp(val.c_str(), "None") == 0 ? HttpCookie::SameSite::None :
  60. HttpCookie::SameSite::Default;
  61. }
  62. else if (stricmp(pkey, "Priority") == 0) {
  63. priority = stricmp(val.c_str(), "Low") == 0 ? HttpCookie::Priority::Low :
  64. stricmp(val.c_str(), "Medium") == 0 ? HttpCookie::Priority::Medium :
  65. stricmp(val.c_str(), "High") == 0 ? HttpCookie::Priority::High :
  66. HttpCookie::Priority::NotSet ;
  67. }
  68. else {
  69. if (name.empty()) {
  70. name = key;
  71. value = val;
  72. }
  73. kv[key] = val;
  74. }
  75. } else {
  76. key = trim(line);
  77. const char* pkey = key.c_str();
  78. if (stricmp(pkey, "Secure") == 0) {
  79. secure = true;
  80. }
  81. else if (stricmp(pkey, "HttpOnly") == 0) {
  82. httponly = true;
  83. }
  84. else {
  85. hlogw("Unrecognized key '%s'", key.c_str());
  86. }
  87. }
  88. }
  89. return !name.empty();
  90. }
  91. std::string HttpCookie::dump() const {
  92. assert(!name.empty() || !kv.empty());
  93. std::string res;
  94. if (!name.empty()) {
  95. res = name;
  96. res += "=";
  97. res += value;
  98. }
  99. for (auto& pair : kv) {
  100. if (pair.first == name) continue;
  101. if (!res.empty()) res += "; ";
  102. res += pair.first;
  103. res += "=";
  104. res += pair.second;
  105. }
  106. if (!domain.empty()) {
  107. res += "; Domain=";
  108. res += domain;
  109. }
  110. if (!path.empty()) {
  111. res += "; Path=";
  112. res += path;
  113. }
  114. if (max_age > 0) {
  115. res += "; Max-Age=";
  116. res += hv::to_string(max_age);
  117. } else if (!expires.empty()) {
  118. res += "; Expires=";
  119. res += expires;
  120. }
  121. if (samesite != HttpCookie::SameSite::Default) {
  122. res += "; SameSite=";
  123. res += samesite == HttpCookie::SameSite::Strict ? "Strict" :
  124. samesite == HttpCookie::SameSite::Lax ? "Lax" :
  125. "None" ;
  126. }
  127. if (priority != HttpCookie::Priority::NotSet) {
  128. res += "; Priority=";
  129. res += priority == HttpCookie::Priority::Low ? "Low" :
  130. priority == HttpCookie::Priority::Medium ? "Medium" :
  131. "High" ;
  132. }
  133. if (secure) {
  134. res += "; Secure";
  135. }
  136. if (httponly) {
  137. res += "; HttpOnly";
  138. }
  139. return res;
  140. }
  141. HttpMessage::HttpMessage() {
  142. type = HTTP_BOTH;
  143. Init();
  144. }
  145. HttpMessage::~HttpMessage() {
  146. }
  147. void HttpMessage::Init() {
  148. http_major = 1;
  149. http_minor = 1;
  150. content = NULL;
  151. content_length = 0;
  152. content_type = CONTENT_TYPE_NONE;
  153. }
  154. void HttpMessage::Reset() {
  155. Init();
  156. headers.clear();
  157. cookies.clear();
  158. body.clear();
  159. #ifndef WITHOUT_HTTP_CONTENT
  160. json.clear();
  161. form.clear();
  162. kv.clear();
  163. #endif
  164. }
  165. #ifndef WITHOUT_HTTP_CONTENT
  166. // NOTE: json ignore number/string, 123/"123"
  167. std::string HttpMessage::GetString(const char* key, const std::string& defvalue) {
  168. switch (ContentType()) {
  169. case APPLICATION_JSON:
  170. {
  171. if (json.empty()) {
  172. ParseBody();
  173. }
  174. if (!json.is_object()) {
  175. return defvalue;
  176. }
  177. const auto& value = json[key];
  178. if (value.is_string()) {
  179. return value;
  180. }
  181. else if (value.is_number()) {
  182. return hv::to_string(value);
  183. }
  184. else if (value.is_null()) {
  185. return "null";
  186. }
  187. else if (value.is_boolean()) {
  188. bool b = value;
  189. return b ? "true" : "false";
  190. }
  191. else {
  192. return defvalue;
  193. }
  194. }
  195. break;
  196. case MULTIPART_FORM_DATA:
  197. {
  198. if (form.empty()) {
  199. ParseBody();
  200. }
  201. auto iter = form.find(key);
  202. if (iter != form.end()) {
  203. return iter->second.content;
  204. }
  205. }
  206. break;
  207. case APPLICATION_URLENCODED:
  208. {
  209. if (kv.empty()) {
  210. ParseBody();
  211. }
  212. auto iter = kv.find(key);
  213. if (iter != kv.end()) {
  214. return iter->second;
  215. }
  216. }
  217. break;
  218. default:
  219. break;
  220. }
  221. return defvalue;
  222. }
  223. template<>
  224. HV_EXPORT int64_t HttpMessage::Get(const char* key, int64_t defvalue) {
  225. if (ContentType() == APPLICATION_JSON) {
  226. if (json.empty()) {
  227. ParseBody();
  228. }
  229. if (!json.is_object()) {
  230. return defvalue;
  231. }
  232. const auto& value = json[key];
  233. if (value.is_number()) {
  234. return value;
  235. }
  236. else if (value.is_string()) {
  237. std::string str = value;
  238. return atoll(str.c_str());
  239. }
  240. else if (value.is_null()) {
  241. return 0;
  242. }
  243. else if (value.is_boolean()) {
  244. bool b = value;
  245. return b ? 1 : 0;
  246. }
  247. else {
  248. return defvalue;
  249. }
  250. }
  251. else {
  252. std::string str = GetString(key);
  253. return str.empty() ? defvalue : atoll(str.c_str());
  254. }
  255. }
  256. template<>
  257. HV_EXPORT int HttpMessage::Get(const char* key, int defvalue) {
  258. return (int)Get<int64_t>(key, defvalue);
  259. }
  260. template<>
  261. HV_EXPORT double HttpMessage::Get(const char* key, double defvalue) {
  262. if (ContentType() == APPLICATION_JSON) {
  263. if (json.empty()) {
  264. ParseBody();
  265. }
  266. if (!json.is_object()) {
  267. return defvalue;
  268. }
  269. const auto& value = json[key];
  270. if (value.is_number()) {
  271. return value;
  272. }
  273. else if (value.is_string()) {
  274. std::string str = value;
  275. return atof(str.c_str());
  276. }
  277. else if (value.is_null()) {
  278. return 0.0f;
  279. }
  280. else {
  281. return defvalue;
  282. }
  283. }
  284. else {
  285. std::string str = GetString(key);
  286. return str.empty() ? defvalue : atof(str.c_str());
  287. }
  288. }
  289. template<>
  290. HV_EXPORT float HttpMessage::Get(const char* key, float defvalue) {
  291. return (float)Get<double>(key, defvalue);
  292. }
  293. template<>
  294. HV_EXPORT bool HttpMessage::Get(const char* key, bool defvalue) {
  295. if (ContentType() == APPLICATION_JSON) {
  296. if (json.empty()) {
  297. ParseBody();
  298. }
  299. if (!json.is_object()) {
  300. return defvalue;
  301. }
  302. const auto& value = json[key];
  303. if (value.is_boolean()) {
  304. return value;
  305. }
  306. else if (value.is_string()) {
  307. std::string str = value;
  308. return hv_getboolean(str.c_str());
  309. }
  310. else if (value.is_null()) {
  311. return false;
  312. }
  313. else if (value.is_number()) {
  314. return value != 0;
  315. }
  316. else {
  317. return defvalue;
  318. }
  319. }
  320. else {
  321. std::string str = GetString(key);
  322. return str.empty() ? defvalue : hv_getboolean(str.c_str());
  323. }
  324. }
  325. bool HttpMessage::GetBool(const char* key, bool defvalue) {
  326. return Get<bool>(key, defvalue);
  327. }
  328. int64_t HttpMessage::GetInt(const char* key, int64_t defvalue) {
  329. return Get<int64_t>(key, defvalue);
  330. }
  331. double HttpMessage::GetFloat(const char* key, double defvalue) {
  332. return Get<double>(key, defvalue);
  333. }
  334. #endif
  335. void HttpMessage::FillContentType() {
  336. auto iter = headers.find("Content-Type");
  337. if (iter != headers.end()) {
  338. content_type = http_content_type_enum(iter->second.c_str());
  339. goto append;
  340. }
  341. #ifndef WITHOUT_HTTP_CONTENT
  342. if (content_type == CONTENT_TYPE_NONE) {
  343. if (json.size() != 0) {
  344. content_type = APPLICATION_JSON;
  345. }
  346. else if (form.size() != 0) {
  347. content_type = MULTIPART_FORM_DATA;
  348. }
  349. else if (kv.size() != 0) {
  350. content_type = X_WWW_FORM_URLENCODED;
  351. }
  352. else if (body.size() != 0) {
  353. content_type = TEXT_PLAIN;
  354. }
  355. }
  356. #endif
  357. if (content_type != CONTENT_TYPE_NONE) {
  358. headers["Content-Type"] = http_content_type_str(content_type);
  359. }
  360. append:
  361. #ifndef WITHOUT_HTTP_CONTENT
  362. if (content_type == MULTIPART_FORM_DATA) {
  363. auto iter = headers.find("Content-Type");
  364. if (iter != headers.end()) {
  365. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  366. if (boundary == NULL) {
  367. boundary = DEFAULT_MULTIPART_BOUNDARY;
  368. iter->second += "; boundary=";
  369. iter->second += boundary;
  370. }
  371. }
  372. }
  373. #endif
  374. return;
  375. }
  376. void HttpMessage::FillContentLength() {
  377. auto iter = headers.find("Content-Length");
  378. if (iter != headers.end()) {
  379. content_length = atoll(iter->second.c_str());
  380. }
  381. if (content_length == 0) {
  382. DumpBody();
  383. content_length = body.size();
  384. }
  385. if (iter == headers.end() && !IsChunked() && content_type != TEXT_EVENT_STREAM) {
  386. if (content_length != 0 || type == HTTP_RESPONSE) {
  387. headers["Content-Length"] = hv::to_string(content_length);
  388. }
  389. }
  390. }
  391. bool HttpMessage::IsChunked() {
  392. auto iter = headers.find("Transfer-Encoding");
  393. return iter != headers.end() && stricmp(iter->second.c_str(), "chunked") == 0;
  394. }
  395. bool HttpMessage::IsKeepAlive() {
  396. bool keepalive = true;
  397. auto iter = headers.find("connection");
  398. if (iter != headers.end()) {
  399. const char* keepalive_value = iter->second.c_str();
  400. if (stricmp(keepalive_value, "keep-alive") == 0) {
  401. keepalive = true;
  402. }
  403. else if (stricmp(keepalive_value, "close") == 0) {
  404. keepalive = false;
  405. }
  406. else if (stricmp(keepalive_value, "upgrade") == 0) {
  407. keepalive = true;
  408. }
  409. }
  410. else if (http_major == 1 && http_minor == 0) {
  411. keepalive = false;
  412. }
  413. return keepalive;
  414. }
  415. // headers
  416. void HttpMessage::SetHeader(const char* key, const std::string& value) {
  417. headers[key] = value;
  418. }
  419. std::string HttpMessage::GetHeader(const char* key, const std::string& defvalue) {
  420. auto iter = headers.find(key);
  421. return iter == headers.end() ? defvalue : iter->second;
  422. }
  423. // cookies
  424. void HttpMessage::AddCookie(const HttpCookie& cookie) {
  425. cookies.push_back(cookie);
  426. }
  427. const HttpCookie& HttpMessage::GetCookie(const std::string& name) {
  428. for (auto iter = cookies.begin(); iter != cookies.end(); ++iter) {
  429. if (iter->name == name) {
  430. return *iter;
  431. }
  432. }
  433. return NoCookie;
  434. }
  435. // body
  436. void HttpMessage::SetBody(const std::string& body) {
  437. this->body = body;
  438. }
  439. const std::string& HttpMessage::Body() {
  440. return this->body;
  441. }
  442. void HttpMessage::DumpHeaders(std::string& str) {
  443. FillContentType();
  444. FillContentLength();
  445. // headers
  446. for (auto& header: headers) {
  447. // http2 :method :path :scheme :authority :status
  448. if (*str.c_str() != ':') {
  449. // %s: %s\r\n
  450. str += header.first;
  451. str += ": ";
  452. str += header.second;
  453. str += "\r\n";
  454. }
  455. }
  456. // cookies
  457. const char* cookie_field = "Cookie";
  458. if (type == HTTP_RESPONSE) {
  459. cookie_field = "Set-Cookie";
  460. }
  461. for (auto& cookie : cookies) {
  462. str += cookie_field;
  463. str += ": ";
  464. str += cookie.dump();
  465. str += "\r\n";
  466. }
  467. }
  468. void HttpMessage::DumpBody() {
  469. if (body.size() != 0) {
  470. return;
  471. }
  472. FillContentType();
  473. #ifndef WITHOUT_HTTP_CONTENT
  474. switch(content_type) {
  475. case APPLICATION_JSON:
  476. body = dump_json(json, 2);
  477. break;
  478. case MULTIPART_FORM_DATA:
  479. {
  480. auto iter = headers.find("Content-Type");
  481. if (iter == headers.end()) {
  482. return;
  483. }
  484. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  485. if (boundary == NULL) {
  486. return;
  487. }
  488. boundary += strlen("boundary=");
  489. body = dump_multipart(form, boundary);
  490. }
  491. break;
  492. case X_WWW_FORM_URLENCODED:
  493. body = dump_query_params(kv);
  494. break;
  495. default:
  496. // nothing to do
  497. break;
  498. }
  499. #endif
  500. }
  501. void HttpMessage::DumpBody(std::string& str) {
  502. DumpBody();
  503. const char* content = (const char*)Content();
  504. size_t content_length = ContentLength();
  505. if (content && content_length) {
  506. str.append(content, content_length);
  507. }
  508. }
  509. int HttpMessage::ParseBody() {
  510. if (body.size() == 0) {
  511. return -1;
  512. }
  513. FillContentType();
  514. #ifndef WITHOUT_HTTP_CONTENT
  515. switch(content_type) {
  516. case APPLICATION_JSON:
  517. {
  518. std::string errmsg;
  519. int ret = parse_json(body.c_str(), json, errmsg);
  520. if (ret != 0 && errmsg.size() != 0) {
  521. hloge("%s", errmsg.c_str());
  522. }
  523. return ret;
  524. }
  525. case MULTIPART_FORM_DATA:
  526. {
  527. auto iter = headers.find("Content-Type");
  528. if (iter == headers.end()) {
  529. return -1;
  530. }
  531. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  532. if (boundary == NULL) {
  533. return -1;
  534. }
  535. boundary += strlen("boundary=");
  536. std::string strBoundary(boundary);
  537. strBoundary = trim_pairs(strBoundary, "\"\"\'\'");
  538. return parse_multipart(body, form, strBoundary.c_str());
  539. }
  540. case X_WWW_FORM_URLENCODED:
  541. return parse_query_params(body.c_str(), kv);
  542. default:
  543. // nothing to do
  544. return 0;
  545. }
  546. #endif
  547. return 0;
  548. }
  549. std::string HttpMessage::Dump(bool is_dump_headers, bool is_dump_body) {
  550. std::string str;
  551. if (is_dump_headers) {
  552. DumpHeaders(str);
  553. }
  554. str += "\r\n";
  555. if (is_dump_body) {
  556. DumpBody(str);
  557. }
  558. return str;
  559. }
  560. HttpRequest::HttpRequest() : HttpMessage() {
  561. type = HTTP_REQUEST;
  562. Init();
  563. }
  564. void HttpRequest::Init() {
  565. headers["User-Agent"] = DEFAULT_HTTP_USER_AGENT;
  566. headers["Accept"] = "*/*";
  567. method = HTTP_GET;
  568. scheme = "http";
  569. host = "127.0.0.1";
  570. port = DEFAULT_HTTP_PORT;
  571. path = "/";
  572. timeout = DEFAULT_HTTP_TIMEOUT;
  573. connect_timeout = DEFAULT_HTTP_CONNECT_TIMEOUT;
  574. retry_count = DEFAULT_HTTP_FAIL_RETRY_COUNT;
  575. retry_delay = DEFAULT_HTTP_FAIL_RETRY_DELAY;
  576. redirect = 1;
  577. proxy = 0;
  578. }
  579. void HttpRequest::Reset() {
  580. HttpMessage::Reset();
  581. Init();
  582. url.clear();
  583. query_params.clear();
  584. }
  585. void HttpRequest::DumpUrl() {
  586. std::string str;
  587. if (url.size() != 0 &&
  588. *url.c_str() != '/' &&
  589. strstr(url.c_str(), "://") != NULL) {
  590. // have been complete url
  591. goto query;
  592. }
  593. // scheme://
  594. str = scheme;
  595. str += "://";
  596. // host:port
  597. if (url.size() != 0 && *url.c_str() != '/') {
  598. // url begin with host
  599. str += url;
  600. }
  601. else {
  602. if (port == 0 ||
  603. port == DEFAULT_HTTP_PORT ||
  604. port == DEFAULT_HTTPS_PORT) {
  605. str += Host();
  606. }
  607. else {
  608. str += hv::asprintf("%s:%d", host.c_str(), port);
  609. }
  610. }
  611. // /path
  612. if (url.size() != 0 && *url.c_str() == '/') {
  613. // url begin with path
  614. str += url;
  615. }
  616. else if (path.size() > 1 && *path.c_str() == '/') {
  617. str += path;
  618. }
  619. else if (url.size() == 0) {
  620. str += '/';
  621. }
  622. url = str;
  623. query:
  624. // ?query
  625. if (strchr(url.c_str(), '?') == NULL &&
  626. query_params.size() != 0) {
  627. url += '?';
  628. url += dump_query_params(query_params);
  629. }
  630. }
  631. void HttpRequest::ParseUrl() {
  632. DumpUrl();
  633. hurl_t parser;
  634. hv_parse_url(&parser, url.c_str());
  635. // scheme
  636. std::string scheme_ = url.substr(parser.fields[HV_URL_SCHEME].off, parser.fields[HV_URL_SCHEME].len);
  637. // host
  638. std::string host_(host);
  639. if (parser.fields[HV_URL_HOST].len > 0) {
  640. host_ = url.substr(parser.fields[HV_URL_HOST].off, parser.fields[HV_URL_HOST].len);
  641. }
  642. // port
  643. int port_ = parser.port ? parser.port : strcmp(scheme_.c_str(), "https") ? DEFAULT_HTTP_PORT : DEFAULT_HTTPS_PORT;
  644. if (!proxy) {
  645. scheme = scheme_;
  646. host = host_;
  647. port = port_;
  648. }
  649. FillHost(host_.c_str(), port_);
  650. // path
  651. if (parser.fields[HV_URL_PATH].len > 0) {
  652. path = url.substr(parser.fields[HV_URL_PATH].off);
  653. }
  654. // query
  655. if (parser.fields[HV_URL_QUERY].len > 0) {
  656. parse_query_params(url.c_str()+parser.fields[HV_URL_QUERY].off, query_params);
  657. }
  658. }
  659. std::string HttpRequest::Path() {
  660. const char* s = path.c_str();
  661. const char* e = s;
  662. while (*e && *e != '?' && *e != '#') ++e;
  663. return HUrl::unescape(std::string(s, e));
  664. }
  665. void HttpRequest::FillHost(const char* host, int port) {
  666. if (headers.find("Host") == headers.end()) {
  667. if (port == 0 ||
  668. port == DEFAULT_HTTP_PORT ||
  669. port == DEFAULT_HTTPS_PORT) {
  670. headers["Host"] = host;
  671. } else {
  672. headers["Host"] = asprintf("%s:%d", host, port);
  673. }
  674. }
  675. }
  676. void HttpRequest::SetHost(const char* host, int port) {
  677. this->host = host;
  678. this->port = port;
  679. FillHost(host, port);
  680. }
  681. void HttpRequest::SetProxy(const char* host, int port) {
  682. this->scheme = "http";
  683. this->host = host;
  684. this->port = port;
  685. proxy = 1;
  686. }
  687. std::string HttpRequest::Dump(bool is_dump_headers, bool is_dump_body) {
  688. ParseUrl();
  689. std::string str;
  690. str.reserve(MAX(512, path.size() + 128));
  691. // GET / HTTP/1.1\r\n
  692. str = asprintf("%s %s HTTP/%d.%d\r\n",
  693. http_method_str(method),
  694. proxy ? url.c_str() : path.c_str(),
  695. (int)http_major, (int)http_minor);
  696. if (is_dump_headers) {
  697. DumpHeaders(str);
  698. }
  699. str += "\r\n";
  700. if (is_dump_body) {
  701. DumpBody(str);
  702. }
  703. return str;
  704. }
  705. void HttpRequest::SetRange(long from, long to) {
  706. SetHeader("Range", hv::asprintf("bytes=%ld-%ld", from, to));
  707. }
  708. bool HttpRequest::GetRange(long& from, long& to) {
  709. auto iter = headers.find("Range");
  710. if (iter != headers.end()) {
  711. sscanf(iter->second.c_str(), "bytes=%ld-%ld", &from, &to);
  712. return true;
  713. }
  714. from = to = 0;
  715. return false;
  716. }
  717. HttpResponse::HttpResponse() : HttpMessage() {
  718. type = HTTP_RESPONSE;
  719. Init();
  720. }
  721. void HttpResponse::Init() {
  722. status_code = HTTP_STATUS_OK;
  723. }
  724. void HttpResponse::Reset() {
  725. HttpMessage::Reset();
  726. Init();
  727. }
  728. std::string HttpResponse::Dump(bool is_dump_headers, bool is_dump_body) {
  729. char c_str[256] = {0};
  730. std::string str;
  731. str.reserve(512);
  732. // HTTP/1.1 200 OK\r\n
  733. snprintf(c_str, sizeof(c_str), "HTTP/%d.%d %d %s\r\n",
  734. (int)http_major, (int)http_minor,
  735. (int)status_code, http_status_str(status_code));
  736. str = c_str;
  737. if (is_dump_headers) {
  738. if (*s_date) {
  739. headers["Date"] = s_date;
  740. } else {
  741. headers["Date"] = gmtime_fmt(time(NULL), c_str);
  742. }
  743. DumpHeaders(str);
  744. }
  745. str += "\r\n";
  746. if (is_dump_body) {
  747. DumpBody(str);
  748. }
  749. return str;
  750. }
  751. void HttpResponse::SetRange(long from, long to, long total) {
  752. SetHeader("Content-Range", hv::asprintf("bytes %ld-%ld/%ld", from, to, total));
  753. }
  754. bool HttpResponse::GetRange(long& from, long& to, long& total) {
  755. auto iter = headers.find("Content-Range");
  756. if (iter != headers.end()) {
  757. sscanf(iter->second.c_str(), "bytes %ld-%ld/%ld", &from, &to, &total);
  758. return true;
  759. }
  760. from = to = total = 0;
  761. return false;
  762. }