http.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. #pragma once
  2. #include <util/datetime/base.h>
  3. #include <util/string/builder.h>
  4. #include <util/system/thread.h>
  5. #include <util/system/hp_timer.h>
  6. #include <util/generic/hash_set.h>
  7. #include <util/generic/buffer.h>
  8. #include <util/generic/intrlist.h>
  9. #include "http_config.h"
  10. // TODO(xenoxeno): hide in implementation
  11. template <typename Type>
  12. struct THash<TIntrusivePtr<Type>> {
  13. size_t operator ()(const TIntrusivePtr<Type>& ptr) const { return reinterpret_cast<size_t>(ptr.Get()); }
  14. };
  15. template<>
  16. inline void Out<NHttp::THttpConfig::SocketAddressType>(IOutputStream& o, const NHttp::THttpConfig::SocketAddressType& x) {
  17. o << x->ToString();
  18. }
  19. namespace NHttp {
  20. bool IsIPv6(const TString& host);
  21. bool IsIPv4(const TString& host);
  22. bool CrackURL(TStringBuf url, TStringBuf& scheme, TStringBuf& host, TStringBuf& uri);
  23. void CrackAddress(const TString& address, TString& hostname, TIpPort& port);
  24. void TrimBegin(TStringBuf& target, char delim);
  25. void TrimEnd(TStringBuf& target, char delim);
  26. void Trim(TStringBuf& target, char delim);
  27. void TrimEnd(TString& target, char delim);
  28. TString CompressDeflate(TStringBuf source);
  29. TString DecompressDeflate(TStringBuf source);
  30. struct TLessNoCase {
  31. bool operator()(TStringBuf l, TStringBuf r) const {
  32. auto ll = l.length();
  33. auto rl = r.length();
  34. if (ll != rl) {
  35. return ll < rl;
  36. }
  37. return strnicmp(l.data(), r.data(), ll) < 0;
  38. }
  39. };
  40. struct TEqNoCase {
  41. bool operator()(TStringBuf l, TStringBuf r) const {
  42. auto ll = l.length();
  43. auto rl = r.length();
  44. if (ll != rl) {
  45. return false;
  46. }
  47. return strnicmp(l.data(), r.data(), ll) == 0;
  48. }
  49. };
  50. struct TSensors {
  51. TString Direction;
  52. TString Host;
  53. TString Url;
  54. TString Status;
  55. TDuration Time;
  56. TSensors(
  57. TStringBuf direction,
  58. TStringBuf host,
  59. TStringBuf url,
  60. TStringBuf status,
  61. TDuration time)
  62. : Direction(direction)
  63. , Host(host)
  64. , Url(url)
  65. , Status(status)
  66. , Time(time)
  67. {}
  68. };
  69. struct TUrlParameters {
  70. THashMap<TStringBuf, TStringBuf> Parameters;
  71. TUrlParameters(TStringBuf url);
  72. TString operator [](TStringBuf name) const;
  73. bool Has(TStringBuf name) const;
  74. TStringBuf Get(TStringBuf name) const; // raw
  75. TString Render() const;
  76. };
  77. struct TCookies {
  78. THashMap<TStringBuf, TStringBuf> Cookies;
  79. TCookies(TStringBuf cookie);
  80. TCookies(const TCookies&) = delete;
  81. TStringBuf operator [](TStringBuf name) const;
  82. bool Has(TStringBuf name) const;
  83. TStringBuf Get(TStringBuf name) const; // raw
  84. TString Render() const;
  85. };
  86. struct TCookiesBuilder : TCookies {
  87. TDeque<std::pair<TString, TString>> Data;
  88. TCookiesBuilder();
  89. void Set(TStringBuf name, TStringBuf data);
  90. };
  91. struct THeaders {
  92. TMap<TStringBuf, TStringBuf, TLessNoCase> Headers;
  93. THeaders() = default;
  94. THeaders(TStringBuf headers);
  95. THeaders(const THeaders&) = delete;
  96. const TStringBuf operator [](TStringBuf name) const;
  97. bool Has(TStringBuf name) const;
  98. TStringBuf Get(TStringBuf name) const; // raw
  99. size_t Parse(TStringBuf headers);
  100. TString Render() const;
  101. };
  102. struct THeadersBuilder : THeaders {
  103. TDeque<std::pair<TString, TString>> Data;
  104. THeadersBuilder();
  105. THeadersBuilder(TStringBuf headers);
  106. THeadersBuilder(const THeadersBuilder& builder);
  107. void Set(TStringBuf name, TStringBuf data);
  108. void Erase(TStringBuf name);
  109. };
  110. class TSocketBuffer : public TBuffer, public THttpConfig {
  111. public:
  112. TSocketBuffer()
  113. : TBuffer(BUFFER_SIZE)
  114. {}
  115. bool EnsureEnoughSpaceAvailable(size_t need) {
  116. size_t avail = Avail();
  117. if (avail < need) {
  118. Reserve(Capacity() + std::max(need, BUFFER_MIN_STEP));
  119. return false;
  120. }
  121. return true;
  122. }
  123. // non-destructive variant of AsString
  124. TString AsString() const {
  125. return TString(Data(), Size());
  126. }
  127. };
  128. class THttpRequest {
  129. public:
  130. TStringBuf Method;
  131. TStringBuf URL;
  132. TStringBuf Protocol;
  133. TStringBuf Version;
  134. TStringBuf Headers;
  135. TStringBuf Host;
  136. TStringBuf Accept;
  137. TStringBuf Connection;
  138. TStringBuf ContentType;
  139. TStringBuf ContentLength;
  140. TStringBuf AcceptEncoding;
  141. TStringBuf TransferEncoding;
  142. TStringBuf Body;
  143. static const TMap<TStringBuf, TStringBuf THttpRequest::*, TLessNoCase> HeadersLocation;
  144. template <TStringBuf THttpRequest::* Header>
  145. static TStringBuf GetName();
  146. void Clear();
  147. };
  148. class THttpResponse {
  149. public:
  150. TStringBuf Protocol;
  151. TStringBuf Version;
  152. TStringBuf Status;
  153. TStringBuf Message;
  154. TStringBuf Headers;
  155. TStringBuf Connection;
  156. TStringBuf ContentType;
  157. TStringBuf ContentLength;
  158. TStringBuf TransferEncoding;
  159. TStringBuf LastModified;
  160. TStringBuf ContentEncoding;
  161. TStringBuf Body;
  162. static const TMap<TStringBuf, TStringBuf THttpResponse::*, TLessNoCase> HeadersLocation;
  163. template <TStringBuf THttpResponse::* Header>
  164. static TStringBuf GetName();
  165. void Clear();
  166. };
  167. template <typename HeaderType, typename BufferType>
  168. class THttpParser : public HeaderType, public BufferType {
  169. public:
  170. enum class EParseStage : ui8 {
  171. Method,
  172. URL,
  173. Protocol,
  174. Version,
  175. Status,
  176. Message,
  177. Header,
  178. Body,
  179. ChunkLength,
  180. ChunkData,
  181. Done,
  182. Error,
  183. };
  184. static constexpr size_t MaxMethodSize = 8;
  185. static constexpr size_t MaxURLSize = 2048;
  186. static constexpr size_t MaxProtocolSize = 4;
  187. static constexpr size_t MaxVersionSize = 4;
  188. static constexpr size_t MaxStatusSize = 3;
  189. static constexpr size_t MaxMessageSize = 1024;
  190. static constexpr size_t MaxHeaderSize = 8192;
  191. static constexpr size_t MaxChunkLengthSize = 8;
  192. static constexpr size_t MaxChunkSize = 256 * 1024 * 1024;
  193. static constexpr size_t MaxChunkContentSize = 1 * 1024 * 1024 * 1024;
  194. EParseStage Stage;
  195. EParseStage LastSuccessStage;
  196. TStringBuf Line;
  197. TStringBuf& Header = Line;
  198. size_t ChunkLength = 0;
  199. size_t ContentSize = 0;
  200. TString Content; // body storage
  201. std::optional<size_t> TotalSize;
  202. THttpParser(const THttpParser& src)
  203. : HeaderType(src)
  204. , BufferType(src)
  205. , Stage(src.Stage)
  206. , LastSuccessStage(src.LastSuccessStage)
  207. , Line()
  208. , Header(Line)
  209. , ChunkLength(src.ChunkLength)
  210. , ContentSize(src.ContentSize)
  211. , Content(src.Content)
  212. {}
  213. template <typename StringType>
  214. bool ProcessData(StringType& target, TStringBuf& source, char delim, size_t maxLen) {
  215. TStringBuf maxSource(source.substr(0, maxLen + 1 - target.size()));
  216. size_t pos = maxSource.find(delim);
  217. target += maxSource.substr(0, pos);
  218. source.Skip(pos);
  219. if (target.size() > maxLen) {
  220. Stage = EParseStage::Error;
  221. return false;
  222. }
  223. if (!source.empty() && *source.begin() == delim) {
  224. source.Skip(1);
  225. }
  226. return pos != TStringBuf::npos;
  227. }
  228. template <typename StringType>
  229. bool ProcessData(StringType& target, TStringBuf& source, TStringBuf delim, size_t maxLen) {
  230. if (delim.empty()) {
  231. return false;
  232. }
  233. if (delim.size() == 1) {
  234. return ProcessData(target, source, delim[0], maxLen);
  235. }
  236. if (ProcessData(target, source, delim.back(), maxLen + 1)) {
  237. for (signed i = delim.size() - 2; i >= 0; --i) {
  238. TrimEnd(target, delim[i]);
  239. }
  240. return true;
  241. }
  242. return false;
  243. }
  244. template <typename StringType>
  245. bool ProcessData(StringType& target, TStringBuf& source, size_t size) {
  246. TStringBuf maxSource(source.substr(0, size - target.size()));
  247. target += maxSource;
  248. source.Skip(maxSource.size());
  249. if (target.size() > size && !source.empty()) {
  250. Stage = EParseStage::Error;
  251. return false;
  252. }
  253. return target.size() == size;
  254. }
  255. void ProcessHeader(TStringBuf& header) {
  256. TStringBuf name = header.NextTok(':');
  257. TrimBegin(name, ' ');
  258. TStringBuf value = header;
  259. Trim(value, ' ');
  260. auto cit = HeaderType::HeadersLocation.find(name);
  261. if (cit != HeaderType::HeadersLocation.end()) {
  262. this->*cit->second = value;
  263. }
  264. header.Clear();
  265. }
  266. size_t ParseHex(TStringBuf value) {
  267. size_t result = 0;
  268. for (char ch : value) {
  269. if (ch >= '0' && ch <= '9') {
  270. result *= 16;
  271. result += ch - '0';
  272. } else if (ch >= 'a' && ch <= 'f') {
  273. result *= 16;
  274. result += 10 + ch - 'a';
  275. } else if (ch >= 'A' && ch <= 'F') {
  276. result *= 16;
  277. result += 10 + ch - 'A';
  278. } else if (ch == ';') {
  279. break;
  280. } else if (isspace(ch)) {
  281. continue;
  282. } else {
  283. Stage = EParseStage::Error;
  284. return 0;
  285. }
  286. }
  287. return result;
  288. }
  289. void Advance(size_t len);
  290. void ConnectionClosed();
  291. size_t GetBodySizeFromTotalSize() const {
  292. return TotalSize.value() - (HeaderType::Headers.end() - BufferType::Data());
  293. }
  294. void Clear() {
  295. BufferType::Clear();
  296. HeaderType::Clear();
  297. Stage = GetInitialStage();
  298. Line.Clear();
  299. Content.clear();
  300. }
  301. bool IsReady() const {
  302. return Stage == EParseStage::Done;
  303. }
  304. bool IsError() const {
  305. return Stage == EParseStage::Error;
  306. }
  307. TStringBuf GetErrorText() const {
  308. switch (LastSuccessStage) {
  309. case EParseStage::Method:
  310. return "Invalid http method";
  311. case EParseStage::URL:
  312. return "Invalid url";
  313. case EParseStage::Protocol:
  314. return "Invalid http protocol";
  315. case EParseStage::Version:
  316. return "Invalid http version";
  317. case EParseStage::Status:
  318. return "Invalid http status";
  319. case EParseStage::Message:
  320. return "Invalid http message";
  321. case EParseStage::Header:
  322. return "Invalid http header";
  323. case EParseStage::Body:
  324. return "Invalid content body";
  325. case EParseStage::ChunkLength:
  326. case EParseStage::ChunkData:
  327. return "Broken chunked data";
  328. case EParseStage::Done:
  329. return "Everything is fine";
  330. case EParseStage::Error:
  331. return "Error on error"; // wat? ...because we don't want to include default label here
  332. }
  333. }
  334. bool IsDone() const {
  335. return IsReady() || IsError();
  336. }
  337. bool HaveBody() const;
  338. bool EnsureEnoughSpaceAvailable(size_t need = BufferType::BUFFER_MIN_STEP) {
  339. bool result = BufferType::EnsureEnoughSpaceAvailable(need);
  340. if (!result && !BufferType::Empty()) {
  341. Reparse();
  342. }
  343. return true;
  344. }
  345. void Reparse() {
  346. size_t size = BufferType::Size();
  347. Clear();
  348. Advance(size);
  349. }
  350. TStringBuf GetRawData() const {
  351. return TStringBuf(BufferType::Data(), BufferType::Size());
  352. }
  353. TString GetObfuscatedData() const {
  354. THeaders headers(HeaderType::Headers);
  355. TStringBuf authorization(headers["Authorization"]);
  356. TStringBuf cookie(headers["Cookie"]);
  357. TStringBuf x_ydb_auth_ticket(headers["x-ydb-auth-ticket"]);
  358. TStringBuf x_yacloud_subjecttoken(headers["x-yacloud-subjecttoken"]);
  359. TString data(GetRawData());
  360. if (!authorization.empty()) {
  361. auto pos = data.find(authorization);
  362. if (pos != TString::npos) {
  363. data.replace(pos, authorization.size(), TString("<obfuscated>"));
  364. }
  365. }
  366. if (!cookie.empty()) {
  367. auto pos = data.find(cookie);
  368. if (pos != TString::npos) {
  369. data.replace(pos, cookie.size(), TString("<obfuscated>"));
  370. }
  371. }
  372. if (!x_ydb_auth_ticket.empty()) {
  373. auto pos = data.find(x_ydb_auth_ticket);
  374. if (pos != TString::npos) {
  375. data.replace(pos, x_ydb_auth_ticket.size(), TString("<obfuscated>"));
  376. }
  377. }
  378. if (!x_yacloud_subjecttoken.empty()) {
  379. auto pos = data.find(x_yacloud_subjecttoken);
  380. if (pos != TString::npos) {
  381. data.replace(pos, x_yacloud_subjecttoken.size(), TString("<obfuscated>"));
  382. }
  383. }
  384. return data;
  385. }
  386. static EParseStage GetInitialStage();
  387. THttpParser()
  388. : Stage(GetInitialStage())
  389. , LastSuccessStage(Stage)
  390. {}
  391. THttpParser(TStringBuf data)
  392. : Stage(GetInitialStage())
  393. , LastSuccessStage(Stage)
  394. {
  395. BufferType::Assign(data.data(), data.size());
  396. BufferType::Clear(); // reset position to 0
  397. TotalSize = data.size();
  398. Advance(data.size());
  399. }
  400. };
  401. template <typename HeaderType, typename BufferType>
  402. class THttpRenderer : public HeaderType, public BufferType {
  403. public:
  404. enum class ERenderStage {
  405. Init,
  406. Header,
  407. Body,
  408. Done,
  409. Error,
  410. };
  411. ERenderStage Stage = ERenderStage::Init;
  412. TString Content; // body storage
  413. //THttpRenderer(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version); // request
  414. void InitRequest(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version) {
  415. Y_VERIFY_DEBUG(Stage == ERenderStage::Init);
  416. AppendParsedValue<&THttpRequest::Method>(method);
  417. Append(' ');
  418. AppendParsedValue<&THttpRequest::URL>(url);
  419. Append(' ');
  420. AppendParsedValue<&THttpRequest::Protocol>(protocol);
  421. Append('/');
  422. AppendParsedValue<&THttpRequest::Version>(version);
  423. Append("\r\n");
  424. Stage = ERenderStage::Header;
  425. HeaderType::Headers = TStringBuf(BufferType::Pos(), size_t(0));
  426. }
  427. //THttpRenderer(TStringBuf protocol, TStringBuf version, TStringBuf status, TStringBuf message); // response
  428. void InitResponse(TStringBuf protocol, TStringBuf version, TStringBuf status, TStringBuf message) {
  429. Y_VERIFY_DEBUG(Stage == ERenderStage::Init);
  430. AppendParsedValue<&THttpResponse::Protocol>(protocol);
  431. Append('/');
  432. AppendParsedValue<&THttpResponse::Version>(version);
  433. Append(' ');
  434. AppendParsedValue<&THttpResponse::Status>(status);
  435. Append(' ');
  436. AppendParsedValue<&THttpResponse::Message>(message);
  437. Append("\r\n");
  438. Stage = ERenderStage::Header;
  439. HeaderType::Headers = TStringBuf(BufferType::Pos(), size_t(0));
  440. }
  441. void Append(TStringBuf text) {
  442. EnsureEnoughSpaceAvailable(text.size());
  443. BufferType::Append(text.data(), text.size());
  444. }
  445. void Append(char c) {
  446. EnsureEnoughSpaceAvailable(sizeof(c));
  447. BufferType::Append(c);
  448. }
  449. template <TStringBuf HeaderType::* string>
  450. void AppendParsedValue(TStringBuf value) {
  451. Append(value);
  452. static_cast<HeaderType*>(this)->*string = TStringBuf(BufferType::Pos() - value.size(), value.size());
  453. }
  454. template <TStringBuf HeaderType::* name>
  455. void Set(TStringBuf value) {
  456. Y_VERIFY_DEBUG(Stage == ERenderStage::Header);
  457. Append(HeaderType::template GetName<name>());
  458. Append(": ");
  459. AppendParsedValue<name>(value);
  460. Append("\r\n");
  461. HeaderType::Headers = TStringBuf(HeaderType::Headers.Data(), BufferType::Pos() - HeaderType::Headers.Data());
  462. }
  463. void Set(TStringBuf name, TStringBuf value) {
  464. Y_VERIFY_DEBUG(Stage == ERenderStage::Header);
  465. Append(name);
  466. Append(": ");
  467. auto data = BufferType::Pos();
  468. Append(value);
  469. auto cit = HeaderType::HeadersLocation.find(name);
  470. if (cit != HeaderType::HeadersLocation.end()) {
  471. (this->*cit->second) = TStringBuf(data, BufferType::Pos());
  472. }
  473. Append("\r\n");
  474. HeaderType::Headers = TStringBuf(HeaderType::Headers.Data(), BufferType::Pos() - HeaderType::Headers.Data());
  475. }
  476. void Set(const THeaders& headers) {
  477. Y_VERIFY_DEBUG(Stage == ERenderStage::Header);
  478. for (const auto& [name, value] : headers.Headers) {
  479. Set(name, value);
  480. }
  481. HeaderType::Headers = TStringBuf(HeaderType::Headers.Data(), BufferType::Pos() - HeaderType::Headers.Data());
  482. }
  483. static constexpr TStringBuf ALLOWED_CONTENT_ENCODINGS[] = {"deflate"};
  484. void SetContentEncoding(TStringBuf contentEncoding) {
  485. Y_VERIFY_DEBUG(Stage == ERenderStage::Header);
  486. if (Count(ALLOWED_CONTENT_ENCODINGS, contentEncoding) != 0) {
  487. Set("Content-Encoding", contentEncoding);
  488. }
  489. }
  490. void FinishHeader() {
  491. Append("\r\n");
  492. HeaderType::Headers = TStringBuf(HeaderType::Headers.Data(), BufferType::Pos() - HeaderType::Headers.Data());
  493. Stage = ERenderStage::Body;
  494. }
  495. void SetBody(TStringBuf body) {
  496. Y_VERIFY_DEBUG(Stage == ERenderStage::Header);
  497. if (HeaderType::ContentLength.empty()) {
  498. Set<&HeaderType::ContentLength>(ToString(body.size()));
  499. }
  500. FinishHeader();
  501. AppendParsedValue<&HeaderType::Body>(body);
  502. Stage = ERenderStage::Done;
  503. }
  504. void FinishBody() {
  505. Stage = ERenderStage::Done;
  506. }
  507. bool IsDone() const {
  508. return Stage == ERenderStage::Done;
  509. }
  510. void Finish() {
  511. switch (Stage) {
  512. case ERenderStage::Header:
  513. FinishHeader();
  514. FinishBody();
  515. break;
  516. case ERenderStage::Body:
  517. FinishBody();
  518. break;
  519. default:
  520. break;
  521. }
  522. }
  523. bool EnsureEnoughSpaceAvailable(size_t need = BufferType::BUFFER_MIN_STEP) {
  524. bool result = BufferType::EnsureEnoughSpaceAvailable(need);
  525. if (!result && !BufferType::Empty()) {
  526. Reparse();
  527. }
  528. return true;
  529. }
  530. void Clear() {
  531. BufferType::Clear();
  532. HeaderType::Clear();
  533. }
  534. void Reparse() {
  535. // move-magic
  536. size_t size = BufferType::Size();
  537. THttpParser<HeaderType, BufferType> parser;
  538. // move the buffer to parser
  539. static_cast<BufferType&>(parser) = std::move(static_cast<BufferType&>(*this));
  540. // reparse
  541. parser.Clear();
  542. parser.Advance(size);
  543. // move buffer and result back
  544. bool needReassignBody = (parser.Body.data() == parser.Content.data());
  545. static_cast<HeaderType&>(*this) = std::move(static_cast<HeaderType&>(parser));
  546. static_cast<BufferType&>(*this) = std::move(static_cast<BufferType&>(parser));
  547. if (needReassignBody) {
  548. Content = std::move(parser.Content);
  549. HeaderType::Body = Content;
  550. }
  551. switch (parser.Stage) {
  552. case THttpParser<HeaderType, BufferType>::EParseStage::Method:
  553. case THttpParser<HeaderType, BufferType>::EParseStage::URL:
  554. case THttpParser<HeaderType, BufferType>::EParseStage::Protocol:
  555. case THttpParser<HeaderType, BufferType>::EParseStage::Version:
  556. case THttpParser<HeaderType, BufferType>::EParseStage::Status:
  557. case THttpParser<HeaderType, BufferType>::EParseStage::Message:
  558. Stage = ERenderStage::Init;
  559. break;
  560. case THttpParser<HeaderType, BufferType>::EParseStage::Header:
  561. Stage = ERenderStage::Header;
  562. break;
  563. case THttpParser<HeaderType, BufferType>::EParseStage::Body:
  564. case THttpParser<HeaderType, BufferType>::EParseStage::ChunkLength:
  565. case THttpParser<HeaderType, BufferType>::EParseStage::ChunkData:
  566. Stage = ERenderStage::Body;
  567. break;
  568. case THttpParser<HeaderType, BufferType>::EParseStage::Done:
  569. Stage = ERenderStage::Done;
  570. break;
  571. case THttpParser<HeaderType, BufferType>::EParseStage::Error:
  572. Stage = ERenderStage::Error;
  573. break;
  574. }
  575. Y_VERIFY(size == BufferType::Size());
  576. }
  577. TStringBuf GetRawData() const {
  578. return TStringBuf(BufferType::Data(), BufferType::Size());
  579. }
  580. };
  581. template <>
  582. template <>
  583. inline void THttpRenderer<THttpResponse, TSocketBuffer>::Set<&THttpResponse::Body>(TStringBuf value) {
  584. SetBody(value);
  585. }
  586. template <>
  587. template <>
  588. inline void THttpRenderer<THttpRequest, TSocketBuffer>::Set<&THttpRequest::Body>(TStringBuf value) {
  589. SetBody(value);
  590. }
  591. template <>
  592. template <>
  593. inline void THttpRenderer<THttpResponse, TSocketBuffer>::Set<&THttpResponse::ContentEncoding>(TStringBuf value) {
  594. SetContentEncoding(value);
  595. }
  596. struct THttpEndpointInfo {
  597. TString WorkerName;
  598. bool Secure = false;
  599. const std::vector<TString> CompressContentTypes; // content types, which will be automatically compressed on response
  600. THttpEndpointInfo() = default;
  601. protected:
  602. THttpEndpointInfo(std::vector<TString> compressContentTypes)
  603. : CompressContentTypes(std::move(compressContentTypes))
  604. {}
  605. };
  606. class THttpIncomingRequest;
  607. using THttpIncomingRequestPtr = TIntrusivePtr<THttpIncomingRequest>;
  608. class THttpOutgoingResponse;
  609. using THttpOutgoingResponsePtr = TIntrusivePtr<THttpOutgoingResponse>;
  610. class THttpIncomingRequest :
  611. public THttpParser<THttpRequest, TSocketBuffer>,
  612. public TRefCounted<THttpIncomingRequest, TAtomicCounter> {
  613. public:
  614. std::shared_ptr<THttpEndpointInfo> Endpoint;
  615. THttpConfig::SocketAddressType Address;
  616. THPTimer Timer;
  617. THttpIncomingRequest()
  618. : Endpoint(std::make_shared<THttpEndpointInfo>())
  619. {}
  620. THttpIncomingRequest(std::shared_ptr<THttpEndpointInfo> endpoint, const THttpConfig::SocketAddressType& address)
  621. : Endpoint(std::move(endpoint))
  622. , Address(address)
  623. {}
  624. THttpIncomingRequest(TStringBuf content, std::shared_ptr<THttpEndpointInfo> endpoint, const THttpConfig::SocketAddressType& address)
  625. : THttpParser(content)
  626. , Endpoint(std::move(endpoint))
  627. , Address(address)
  628. {}
  629. bool IsConnectionClose() const {
  630. if (Connection.empty()) {
  631. return Version == "1.0";
  632. } else {
  633. return TEqNoCase()(Connection, "close");
  634. }
  635. }
  636. TStringBuf GetConnection() const {
  637. if (!Connection.empty()) {
  638. if (TEqNoCase()(Connection, "keep-alive")) {
  639. return "keep-alive";
  640. }
  641. if (TEqNoCase()(Connection, "close")) {
  642. return "close";
  643. }
  644. }
  645. return Version == "1.0" ? "close" : "keep-alive";
  646. }
  647. THttpOutgoingResponsePtr CreateResponseOK(TStringBuf body, TStringBuf contentType = "text/html", TInstant lastModified = TInstant());
  648. THttpOutgoingResponsePtr CreateResponseString(TStringBuf data);
  649. THttpOutgoingResponsePtr CreateResponseBadRequest(TStringBuf html = TStringBuf(), TStringBuf contentType = "text/html"); // 400
  650. THttpOutgoingResponsePtr CreateResponseNotFound(TStringBuf html = TStringBuf(), TStringBuf contentType = "text/html"); // 404
  651. THttpOutgoingResponsePtr CreateResponseServiceUnavailable(TStringBuf html = TStringBuf(), TStringBuf contentType = "text/html"); // 503
  652. THttpOutgoingResponsePtr CreateResponseGatewayTimeout(TStringBuf html = TStringBuf(), TStringBuf contentType = "text/html"); // 504
  653. THttpOutgoingResponsePtr CreateResponse(TStringBuf status, TStringBuf message);
  654. THttpOutgoingResponsePtr CreateResponse(TStringBuf status, TStringBuf message, const THeaders& headers);
  655. THttpOutgoingResponsePtr CreateResponse(TStringBuf status, TStringBuf message, const THeaders& headers, TStringBuf body);
  656. THttpOutgoingResponsePtr CreateResponse(
  657. TStringBuf status,
  658. TStringBuf message,
  659. TStringBuf contentType,
  660. TStringBuf body = TStringBuf(),
  661. TInstant lastModified = TInstant());
  662. THttpOutgoingResponsePtr CreateIncompleteResponse(TStringBuf status, TStringBuf message, const THeaders& headers = {});
  663. THttpOutgoingResponsePtr CreateIncompleteResponse(TStringBuf status, TStringBuf message, const THeaders& headers, TStringBuf body);
  664. THttpIncomingRequestPtr Duplicate();
  665. private:
  666. THttpOutgoingResponsePtr ConstructResponse(TStringBuf status, TStringBuf message);
  667. void FinishResponse(THttpOutgoingResponsePtr& response, TStringBuf body = TStringBuf());
  668. };
  669. class THttpIncomingResponse;
  670. using THttpIncomingResponsePtr = TIntrusivePtr<THttpIncomingResponse>;
  671. class THttpOutgoingRequest;
  672. using THttpOutgoingRequestPtr = TIntrusivePtr<THttpOutgoingRequest>;
  673. class THttpIncomingResponse :
  674. public THttpParser<THttpResponse, TSocketBuffer>,
  675. public TRefCounted<THttpIncomingResponse, TAtomicCounter> {
  676. public:
  677. THttpIncomingResponse(THttpOutgoingRequestPtr request);
  678. THttpOutgoingRequestPtr GetRequest() const {
  679. return Request;
  680. }
  681. THttpIncomingResponsePtr Duplicate(THttpOutgoingRequestPtr request);
  682. THttpOutgoingResponsePtr Reverse(THttpIncomingRequestPtr request);
  683. protected:
  684. THttpOutgoingRequestPtr Request;
  685. };
  686. class THttpOutgoingRequest :
  687. public THttpRenderer<THttpRequest, TSocketBuffer>,
  688. public TRefCounted<THttpOutgoingRequest, TAtomicCounter> {
  689. public:
  690. THPTimer Timer;
  691. bool Secure = false;
  692. THttpOutgoingRequest() = default;
  693. THttpOutgoingRequest(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version);
  694. THttpOutgoingRequest(TStringBuf method, TStringBuf scheme, TStringBuf host, TStringBuf uri, TStringBuf protocol, TStringBuf version);
  695. static THttpOutgoingRequestPtr CreateRequestString(TStringBuf data);
  696. static THttpOutgoingRequestPtr CreateRequestString(const TString& data);
  697. static THttpOutgoingRequestPtr CreateRequestGet(TStringBuf url);
  698. static THttpOutgoingRequestPtr CreateRequestGet(TStringBuf host, TStringBuf uri); // http only
  699. static THttpOutgoingRequestPtr CreateRequestPost(TStringBuf url, TStringBuf contentType = {}, TStringBuf body = {});
  700. static THttpOutgoingRequestPtr CreateRequestPost(TStringBuf host, TStringBuf uri, TStringBuf contentType, TStringBuf body); // http only
  701. static THttpOutgoingRequestPtr CreateRequest(TStringBuf method, TStringBuf url, TStringBuf contentType = TStringBuf(), TStringBuf body = TStringBuf());
  702. static THttpOutgoingRequestPtr CreateHttpRequest(TStringBuf method, TStringBuf host, TStringBuf uri, TStringBuf contentType = TStringBuf(), TStringBuf body = TStringBuf());
  703. THttpOutgoingRequestPtr Duplicate();
  704. };
  705. class THttpOutgoingResponse :
  706. public THttpRenderer<THttpResponse, TSocketBuffer>,
  707. public TRefCounted<THttpOutgoingResponse, TAtomicCounter> {
  708. public:
  709. THttpOutgoingResponse(THttpIncomingRequestPtr request);
  710. THttpOutgoingResponse(THttpIncomingRequestPtr request, TStringBuf protocol, TStringBuf version, TStringBuf status, TStringBuf message);
  711. bool IsConnectionClose() const {
  712. if (!Connection.empty()) {
  713. return TEqNoCase()(Connection, "close");
  714. } else {
  715. return Request->IsConnectionClose();
  716. }
  717. }
  718. bool IsNeedBody() const {
  719. return GetRequest()->Method != "HEAD" && Status != "204";
  720. }
  721. bool EnableCompression() {
  722. TStringBuf acceptEncoding = Request->AcceptEncoding;
  723. std::vector<TStringBuf> encodings;
  724. TStringBuf encoding;
  725. while (acceptEncoding.NextTok(',', encoding)) {
  726. Trim(encoding, ' ');
  727. if (Count(ALLOWED_CONTENT_ENCODINGS, encoding) != 0) {
  728. encodings.push_back(encoding);
  729. }
  730. }
  731. if (!encodings.empty()) {
  732. // TODO: prioritize encodings
  733. SetContentEncoding(encodings.front());
  734. return true;
  735. }
  736. return false;
  737. }
  738. void SetBody(TStringBuf body) {
  739. if (ContentEncoding == "deflate") {
  740. TString compressedBody = CompressDeflate(body);
  741. THttpRenderer<THttpResponse, TSocketBuffer>::SetBody(compressedBody);
  742. Body = Content = body;
  743. } else {
  744. THttpRenderer<THttpResponse, TSocketBuffer>::SetBody(body);
  745. }
  746. }
  747. void SetBody(const TString& body) {
  748. if (ContentEncoding == "deflate") {
  749. TString compressedBody = CompressDeflate(body);
  750. THttpRenderer<THttpResponse, TSocketBuffer>::SetBody(compressedBody);
  751. Body = Content = body;
  752. } else {
  753. THttpRenderer<THttpResponse, TSocketBuffer>::SetBody(body);
  754. }
  755. }
  756. THttpIncomingRequestPtr GetRequest() const {
  757. return Request;
  758. }
  759. THttpOutgoingResponsePtr Duplicate(THttpIncomingRequestPtr request);
  760. // it's temporary accessible for cleanup
  761. //protected:
  762. THttpIncomingRequestPtr Request;
  763. std::unique_ptr<TSensors> Sensors;
  764. };
  765. }