1
0

HttpMessage.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  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_boolean()) {
  185. bool b = value;
  186. return b ? "true" : "false";
  187. }
  188. else {
  189. return defvalue;
  190. }
  191. }
  192. break;
  193. case MULTIPART_FORM_DATA:
  194. {
  195. if (form.empty()) {
  196. ParseBody();
  197. }
  198. auto iter = form.find(key);
  199. if (iter != form.end()) {
  200. return iter->second.content;
  201. }
  202. }
  203. break;
  204. case APPLICATION_URLENCODED:
  205. {
  206. if (kv.empty()) {
  207. ParseBody();
  208. }
  209. auto iter = kv.find(key);
  210. if (iter != kv.end()) {
  211. return iter->second;
  212. }
  213. }
  214. break;
  215. default:
  216. break;
  217. }
  218. return defvalue;
  219. }
  220. template<>
  221. HV_EXPORT int64_t HttpMessage::Get(const char* key, int64_t defvalue) {
  222. if (ContentType() == APPLICATION_JSON) {
  223. if (json.empty()) {
  224. ParseBody();
  225. }
  226. if (!json.is_object()) {
  227. return defvalue;
  228. }
  229. const auto& value = json[key];
  230. if (value.is_number()) {
  231. return value;
  232. }
  233. else if (value.is_string()) {
  234. std::string str = value;
  235. return atoll(str.c_str());
  236. }
  237. else if (value.is_boolean()) {
  238. bool b = value;
  239. return b ? 1 : 0;
  240. }
  241. else {
  242. return defvalue;
  243. }
  244. }
  245. else {
  246. std::string str = GetString(key);
  247. return str.empty() ? defvalue : atoll(str.c_str());
  248. }
  249. }
  250. template<>
  251. HV_EXPORT int HttpMessage::Get(const char* key, int defvalue) {
  252. return (int)Get<int64_t>(key, defvalue);
  253. }
  254. template<>
  255. HV_EXPORT double HttpMessage::Get(const char* key, double defvalue) {
  256. if (ContentType() == APPLICATION_JSON) {
  257. if (json.empty()) {
  258. ParseBody();
  259. }
  260. if (!json.is_object()) {
  261. return defvalue;
  262. }
  263. const auto& value = json[key];
  264. if (value.is_number()) {
  265. return value;
  266. }
  267. else if (value.is_string()) {
  268. std::string str = value;
  269. return atof(str.c_str());
  270. }
  271. else {
  272. return defvalue;
  273. }
  274. }
  275. else {
  276. std::string str = GetString(key);
  277. return str.empty() ? defvalue : atof(str.c_str());
  278. }
  279. }
  280. template<>
  281. HV_EXPORT float HttpMessage::Get(const char* key, float defvalue) {
  282. return (float)Get<double>(key, defvalue);
  283. }
  284. template<>
  285. HV_EXPORT bool HttpMessage::Get(const char* key, bool defvalue) {
  286. if (ContentType() == APPLICATION_JSON) {
  287. if (json.empty()) {
  288. ParseBody();
  289. }
  290. if (!json.is_object()) {
  291. return defvalue;
  292. }
  293. const auto& value = json[key];
  294. if (value.is_boolean()) {
  295. return value;
  296. }
  297. else if (value.is_string()) {
  298. std::string str = value;
  299. return hv_getboolean(str.c_str());
  300. }
  301. else if (value.is_number()) {
  302. return value != 0;
  303. }
  304. else {
  305. return defvalue;
  306. }
  307. }
  308. else {
  309. std::string str = GetString(key);
  310. return str.empty() ? defvalue : hv_getboolean(str.c_str());
  311. }
  312. }
  313. bool HttpMessage::GetBool(const char* key, bool defvalue) {
  314. return Get<bool>(key, defvalue);
  315. }
  316. int64_t HttpMessage::GetInt(const char* key, int64_t defvalue) {
  317. return Get<int64_t>(key, defvalue);
  318. }
  319. double HttpMessage::GetFloat(const char* key, double defvalue) {
  320. return Get<double>(key, defvalue);
  321. }
  322. #endif
  323. void HttpMessage::FillContentType() {
  324. auto iter = headers.find("Content-Type");
  325. if (iter != headers.end()) {
  326. content_type = http_content_type_enum(iter->second.c_str());
  327. goto append;
  328. }
  329. #ifndef WITHOUT_HTTP_CONTENT
  330. if (content_type == CONTENT_TYPE_NONE) {
  331. if (json.size() != 0) {
  332. content_type = APPLICATION_JSON;
  333. }
  334. else if (form.size() != 0) {
  335. content_type = MULTIPART_FORM_DATA;
  336. }
  337. else if (kv.size() != 0) {
  338. content_type = X_WWW_FORM_URLENCODED;
  339. }
  340. else if (body.size() != 0) {
  341. content_type = TEXT_PLAIN;
  342. }
  343. }
  344. #endif
  345. if (content_type != CONTENT_TYPE_NONE) {
  346. headers["Content-Type"] = http_content_type_str(content_type);
  347. }
  348. append:
  349. #ifndef WITHOUT_HTTP_CONTENT
  350. if (content_type == MULTIPART_FORM_DATA) {
  351. auto iter = headers.find("Content-Type");
  352. if (iter != headers.end()) {
  353. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  354. if (boundary == NULL) {
  355. boundary = DEFAULT_MULTIPART_BOUNDARY;
  356. iter->second += "; boundary=";
  357. iter->second += boundary;
  358. }
  359. }
  360. }
  361. #endif
  362. return;
  363. }
  364. void HttpMessage::FillContentLength() {
  365. auto iter = headers.find("Content-Length");
  366. if (iter != headers.end()) {
  367. content_length = atoll(iter->second.c_str());
  368. }
  369. if (content_length == 0) {
  370. DumpBody();
  371. content_length = body.size();
  372. }
  373. if (iter == headers.end() && !IsChunked() && content_type != TEXT_EVENT_STREAM) {
  374. if (content_length != 0 || type == HTTP_RESPONSE) {
  375. headers["Content-Length"] = hv::to_string(content_length);
  376. }
  377. }
  378. }
  379. bool HttpMessage::IsChunked() {
  380. auto iter = headers.find("Transfer-Encoding");
  381. return iter != headers.end() && stricmp(iter->second.c_str(), "chunked") == 0;
  382. }
  383. bool HttpMessage::IsKeepAlive() {
  384. bool keepalive = true;
  385. auto iter = headers.find("connection");
  386. if (iter != headers.end()) {
  387. const char* keepalive_value = iter->second.c_str();
  388. if (stricmp(keepalive_value, "keep-alive") == 0) {
  389. keepalive = true;
  390. }
  391. else if (stricmp(keepalive_value, "close") == 0) {
  392. keepalive = false;
  393. }
  394. else if (stricmp(keepalive_value, "upgrade") == 0) {
  395. keepalive = true;
  396. }
  397. }
  398. else if (http_major == 1 && http_minor == 0) {
  399. keepalive = false;
  400. }
  401. return keepalive;
  402. }
  403. // headers
  404. void HttpMessage::SetHeader(const char* key, const std::string& value) {
  405. headers[key] = value;
  406. }
  407. std::string HttpMessage::GetHeader(const char* key, const std::string& defvalue) {
  408. auto iter = headers.find(key);
  409. return iter == headers.end() ? defvalue : iter->second;
  410. }
  411. // cookies
  412. void HttpMessage::AddCookie(const HttpCookie& cookie) {
  413. cookies.push_back(cookie);
  414. }
  415. const HttpCookie& HttpMessage::GetCookie(const std::string& name) {
  416. for (auto iter = cookies.begin(); iter != cookies.end(); ++iter) {
  417. if (iter->name == name) {
  418. return *iter;
  419. }
  420. }
  421. return NoCookie;
  422. }
  423. // body
  424. void HttpMessage::SetBody(const std::string& body) {
  425. this->body = body;
  426. }
  427. const std::string& HttpMessage::Body() {
  428. return this->body;
  429. }
  430. void HttpMessage::DumpHeaders(std::string& str) {
  431. FillContentType();
  432. FillContentLength();
  433. // headers
  434. for (auto& header: headers) {
  435. // http2 :method :path :scheme :authority :status
  436. if (*str.c_str() != ':') {
  437. // %s: %s\r\n
  438. str += header.first;
  439. str += ": ";
  440. str += header.second;
  441. str += "\r\n";
  442. }
  443. }
  444. // cookies
  445. const char* cookie_field = "Cookie";
  446. if (type == HTTP_RESPONSE) {
  447. cookie_field = "Set-Cookie";
  448. }
  449. for (auto& cookie : cookies) {
  450. str += cookie_field;
  451. str += ": ";
  452. str += cookie.dump();
  453. str += "\r\n";
  454. }
  455. }
  456. void HttpMessage::DumpBody() {
  457. if (body.size() != 0) {
  458. return;
  459. }
  460. FillContentType();
  461. #ifndef WITHOUT_HTTP_CONTENT
  462. switch(content_type) {
  463. case APPLICATION_JSON:
  464. body = dump_json(json, 2);
  465. break;
  466. case MULTIPART_FORM_DATA:
  467. {
  468. auto iter = headers.find("Content-Type");
  469. if (iter == headers.end()) {
  470. return;
  471. }
  472. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  473. if (boundary == NULL) {
  474. return;
  475. }
  476. boundary += strlen("boundary=");
  477. body = dump_multipart(form, boundary);
  478. }
  479. break;
  480. case X_WWW_FORM_URLENCODED:
  481. body = dump_query_params(kv);
  482. break;
  483. default:
  484. // nothing to do
  485. break;
  486. }
  487. #endif
  488. }
  489. void HttpMessage::DumpBody(std::string& str) {
  490. DumpBody();
  491. const char* content = (const char*)Content();
  492. size_t content_length = ContentLength();
  493. if (content && content_length) {
  494. str.append(content, content_length);
  495. }
  496. }
  497. int HttpMessage::ParseBody() {
  498. if (body.size() == 0) {
  499. return -1;
  500. }
  501. FillContentType();
  502. #ifndef WITHOUT_HTTP_CONTENT
  503. switch(content_type) {
  504. case APPLICATION_JSON:
  505. {
  506. std::string errmsg;
  507. int ret = parse_json(body.c_str(), json, errmsg);
  508. if (ret != 0 && errmsg.size() != 0) {
  509. hloge("%s", errmsg.c_str());
  510. }
  511. return ret;
  512. }
  513. case MULTIPART_FORM_DATA:
  514. {
  515. auto iter = headers.find("Content-Type");
  516. if (iter == headers.end()) {
  517. return -1;
  518. }
  519. const char* boundary = strstr(iter->second.c_str(), "boundary=");
  520. if (boundary == NULL) {
  521. return -1;
  522. }
  523. boundary += strlen("boundary=");
  524. std::string strBoundary(boundary);
  525. strBoundary = trim_pairs(strBoundary, "\"\"\'\'");
  526. return parse_multipart(body, form, strBoundary.c_str());
  527. }
  528. case X_WWW_FORM_URLENCODED:
  529. return parse_query_params(body.c_str(), kv);
  530. default:
  531. // nothing to do
  532. return 0;
  533. }
  534. #endif
  535. return 0;
  536. }
  537. std::string HttpMessage::Dump(bool is_dump_headers, bool is_dump_body) {
  538. std::string str;
  539. if (is_dump_headers) {
  540. DumpHeaders(str);
  541. }
  542. str += "\r\n";
  543. if (is_dump_body) {
  544. DumpBody(str);
  545. }
  546. return str;
  547. }
  548. HttpRequest::HttpRequest() : HttpMessage() {
  549. type = HTTP_REQUEST;
  550. Init();
  551. }
  552. void HttpRequest::Init() {
  553. headers["User-Agent"] = DEFAULT_HTTP_USER_AGENT;
  554. headers["Accept"] = "*/*";
  555. method = HTTP_GET;
  556. scheme = "http";
  557. host = "127.0.0.1";
  558. port = DEFAULT_HTTP_PORT;
  559. path = "/";
  560. timeout = DEFAULT_HTTP_TIMEOUT;
  561. connect_timeout = DEFAULT_HTTP_CONNECT_TIMEOUT;
  562. retry_count = DEFAULT_HTTP_FAIL_RETRY_COUNT;
  563. retry_delay = DEFAULT_HTTP_FAIL_RETRY_DELAY;
  564. redirect = 1;
  565. proxy = 0;
  566. }
  567. void HttpRequest::Reset() {
  568. HttpMessage::Reset();
  569. Init();
  570. url.clear();
  571. query_params.clear();
  572. }
  573. void HttpRequest::DumpUrl() {
  574. std::string str;
  575. if (url.size() != 0 &&
  576. *url.c_str() != '/' &&
  577. strstr(url.c_str(), "://") != NULL) {
  578. // have been complete url
  579. goto query;
  580. }
  581. // scheme://
  582. str = scheme;
  583. str += "://";
  584. // host:port
  585. if (url.size() != 0 && *url.c_str() != '/') {
  586. // url begin with host
  587. str += url;
  588. }
  589. else {
  590. if (port == 0 ||
  591. port == DEFAULT_HTTP_PORT ||
  592. port == DEFAULT_HTTPS_PORT) {
  593. str += Host();
  594. }
  595. else {
  596. str += hv::asprintf("%s:%d", host.c_str(), port);
  597. }
  598. }
  599. // /path
  600. if (url.size() != 0 && *url.c_str() == '/') {
  601. // url begin with path
  602. str += url;
  603. }
  604. else if (path.size() > 1 && *path.c_str() == '/') {
  605. str += path;
  606. }
  607. else if (url.size() == 0) {
  608. str += '/';
  609. }
  610. url = str;
  611. query:
  612. // ?query
  613. if (strchr(url.c_str(), '?') == NULL &&
  614. query_params.size() != 0) {
  615. url += '?';
  616. url += dump_query_params(query_params);
  617. }
  618. }
  619. void HttpRequest::ParseUrl() {
  620. DumpUrl();
  621. hurl_t parser;
  622. hv_parse_url(&parser, url.c_str());
  623. // scheme
  624. std::string scheme_ = url.substr(parser.fields[HV_URL_SCHEME].off, parser.fields[HV_URL_SCHEME].len);
  625. // host
  626. std::string host_(host);
  627. if (parser.fields[HV_URL_HOST].len > 0) {
  628. host_ = url.substr(parser.fields[HV_URL_HOST].off, parser.fields[HV_URL_HOST].len);
  629. }
  630. // port
  631. int port_ = parser.port ? parser.port : strcmp(scheme_.c_str(), "https") ? DEFAULT_HTTP_PORT : DEFAULT_HTTPS_PORT;
  632. if (!proxy) {
  633. scheme = scheme_;
  634. host = host_;
  635. port = port_;
  636. }
  637. FillHost(host_.c_str(), port_);
  638. // path
  639. if (parser.fields[HV_URL_PATH].len > 0) {
  640. path = url.substr(parser.fields[HV_URL_PATH].off);
  641. }
  642. // query
  643. if (parser.fields[HV_URL_QUERY].len > 0) {
  644. parse_query_params(url.c_str()+parser.fields[HV_URL_QUERY].off, query_params);
  645. }
  646. }
  647. std::string HttpRequest::Path() {
  648. const char* s = path.c_str();
  649. const char* e = s;
  650. while (*e && *e != '?' && *e != '#') ++e;
  651. return HUrl::unescape(std::string(s, e));
  652. }
  653. void HttpRequest::FillHost(const char* host, int port) {
  654. if (headers.find("Host") == headers.end()) {
  655. if (port == 0 ||
  656. port == DEFAULT_HTTP_PORT ||
  657. port == DEFAULT_HTTPS_PORT) {
  658. headers["Host"] = host;
  659. } else {
  660. headers["Host"] = asprintf("%s:%d", host, port);
  661. }
  662. }
  663. }
  664. void HttpRequest::SetHost(const char* host, int port) {
  665. this->host = host;
  666. this->port = port;
  667. FillHost(host, port);
  668. }
  669. void HttpRequest::SetProxy(const char* host, int port) {
  670. this->scheme = "http";
  671. this->host = host;
  672. this->port = port;
  673. proxy = 1;
  674. }
  675. std::string HttpRequest::Dump(bool is_dump_headers, bool is_dump_body) {
  676. ParseUrl();
  677. std::string str;
  678. str.reserve(MAX(512, path.size() + 128));
  679. // GET / HTTP/1.1\r\n
  680. str = asprintf("%s %s HTTP/%d.%d\r\n",
  681. http_method_str(method),
  682. proxy ? url.c_str() : path.c_str(),
  683. (int)http_major, (int)http_minor);
  684. if (is_dump_headers) {
  685. DumpHeaders(str);
  686. }
  687. str += "\r\n";
  688. if (is_dump_body) {
  689. DumpBody(str);
  690. }
  691. return str;
  692. }
  693. void HttpRequest::SetRange(long from, long to) {
  694. SetHeader("Range", hv::asprintf("bytes=%ld-%ld", from, to));
  695. }
  696. bool HttpRequest::GetRange(long& from, long& to) {
  697. auto iter = headers.find("Range");
  698. if (iter != headers.end()) {
  699. sscanf(iter->second.c_str(), "bytes=%ld-%ld", &from, &to);
  700. return true;
  701. }
  702. from = to = 0;
  703. return false;
  704. }
  705. HttpResponse::HttpResponse() : HttpMessage() {
  706. type = HTTP_RESPONSE;
  707. Init();
  708. }
  709. void HttpResponse::Init() {
  710. status_code = HTTP_STATUS_OK;
  711. }
  712. void HttpResponse::Reset() {
  713. HttpMessage::Reset();
  714. Init();
  715. }
  716. std::string HttpResponse::Dump(bool is_dump_headers, bool is_dump_body) {
  717. char c_str[256] = {0};
  718. std::string str;
  719. str.reserve(512);
  720. // HTTP/1.1 200 OK\r\n
  721. snprintf(c_str, sizeof(c_str), "HTTP/%d.%d %d %s\r\n",
  722. (int)http_major, (int)http_minor,
  723. (int)status_code, http_status_str(status_code));
  724. str = c_str;
  725. if (is_dump_headers) {
  726. if (*s_date) {
  727. headers["Date"] = s_date;
  728. } else {
  729. headers["Date"] = gmtime_fmt(time(NULL), c_str);
  730. }
  731. DumpHeaders(str);
  732. }
  733. str += "\r\n";
  734. if (is_dump_body) {
  735. DumpBody(str);
  736. }
  737. return str;
  738. }
  739. void HttpResponse::SetRange(long from, long to, long total) {
  740. SetHeader("Content-Range", hv::asprintf("bytes %ld-%ld/%ld", from, to, total));
  741. }
  742. bool HttpResponse::GetRange(long& from, long& to, long& total) {
  743. auto iter = headers.find("Content-Range");
  744. if (iter != headers.end()) {
  745. sscanf(iter->second.c_str(), "bytes %ld-%ld/%ld", &from, &to, &total);
  746. return true;
  747. }
  748. from = to = total = 0;
  749. return false;
  750. }