1
0

HttpMessage.cpp 22 KB

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