http.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  1. #include "http.h"
  2. #include "http_ex.h"
  3. #include <library/cpp/threading/equeue/equeue.h>
  4. #include <util/generic/buffer.h>
  5. #include <util/generic/cast.h>
  6. #include <util/generic/intrlist.h>
  7. #include <util/generic/yexception.h>
  8. #include <util/network/address.h>
  9. #include <util/network/socket.h>
  10. #include <util/network/poller.h>
  11. #include <util/system/atomic.h>
  12. #include <util/system/compat.h> // stricmp, strnicmp, strlwr, strupr, stpcpy
  13. #include <util/system/defaults.h>
  14. #include <util/system/event.h>
  15. #include <util/system/mutex.h>
  16. #include <util/system/pipe.h>
  17. #include <util/system/thread.h>
  18. #include <util/thread/factory.h>
  19. #include <cerrno>
  20. #include <cstring>
  21. #include <ctime>
  22. #include <sys/stat.h>
  23. #include <sys/types.h>
  24. using namespace NAddr;
  25. namespace {
  26. class IPollAble {
  27. public:
  28. inline IPollAble() noexcept {
  29. }
  30. virtual ~IPollAble() {
  31. }
  32. virtual void OnPollEvent(TInstant now) = 0;
  33. };
  34. struct TShouldStop {
  35. };
  36. struct TWakeupPollAble: public IPollAble {
  37. void OnPollEvent(TInstant) override {
  38. throw TShouldStop();
  39. }
  40. };
  41. }
  42. class TClientConnection: public IPollAble, public TIntrusiveListItem<TClientConnection> {
  43. public:
  44. TClientConnection(const TSocket& s, THttpServer::TImpl* serv, NAddr::IRemoteAddrRef listenerSockAddrRef);
  45. ~TClientConnection() override;
  46. void OnPollEvent(TInstant now) override;
  47. inline void Activate(TInstant now) noexcept;
  48. inline void DeActivate();
  49. inline void Reject();
  50. public:
  51. TSocket Socket_;
  52. NAddr::IRemoteAddrRef ListenerSockAddrRef_;
  53. THttpServer::TImpl* HttpServ_ = nullptr;
  54. bool Reject_ = false;
  55. TInstant LastUsed;
  56. TInstant AcceptMoment;
  57. size_t ReceivedRequests = 0;
  58. };
  59. class THttpServer::TImpl {
  60. public:
  61. class TConnections {
  62. public:
  63. inline TConnections(TSocketPoller* poller, const THttpServerOptions& options)
  64. : Poller_(poller)
  65. , Options(options)
  66. {
  67. }
  68. inline ~TConnections() {
  69. }
  70. inline void Add(TClientConnection* c) noexcept {
  71. TGuard<TMutex> g(Mutex_);
  72. Conns_.PushBack(c);
  73. Poller_->WaitRead(c->Socket_, (void*)static_cast<const IPollAble*>(c));
  74. }
  75. inline void Erase(TClientConnection* c, TInstant now) noexcept {
  76. TGuard<TMutex> g(Mutex_);
  77. EraseUnsafe(c);
  78. if (Options.ExpirationTimeout > TDuration::Zero()) {
  79. TryRemovingUnsafe(now - Options.ExpirationTimeout);
  80. }
  81. }
  82. inline void Clear() noexcept {
  83. TGuard<TMutex> g(Mutex_);
  84. Conns_.Clear();
  85. }
  86. inline bool RemoveOld(TInstant border) noexcept {
  87. TGuard<TMutex> g(Mutex_);
  88. return TryRemovingUnsafe(border);
  89. }
  90. bool TryRemovingUnsafe(TInstant border) noexcept {
  91. if (Conns_.Empty()) {
  92. return false;
  93. }
  94. TClientConnection* c = &*(Conns_.Begin());
  95. if (c->LastUsed > border) {
  96. return false;
  97. }
  98. EraseUnsafe(c);
  99. delete c;
  100. return true;
  101. }
  102. void EraseUnsafe(TClientConnection* c) noexcept {
  103. Poller_->Unwait(c->Socket_);
  104. c->Unlink();
  105. }
  106. public:
  107. TMutex Mutex_;
  108. TIntrusiveListWithAutoDelete<TClientConnection, TDelete> Conns_;
  109. TSocketPoller* Poller_ = nullptr;
  110. const THttpServerOptions& Options;
  111. };
  112. static void* ListenSocketFunction(void* param) {
  113. try {
  114. ((TImpl*)param)->ListenSocket();
  115. } catch (...) {
  116. }
  117. return nullptr;
  118. }
  119. TAutoPtr<TClientRequest> CreateRequest(TAutoPtr<TClientConnection> c) {
  120. THolder<TClientRequest> obj(Cb_->CreateClient());
  121. obj->Conn_.Reset(c.Release());
  122. return obj;
  123. }
  124. void AddRequestFromSocket(const TSocket& s, TInstant now, NAddr::IRemoteAddrRef listenerSockAddrRef) {
  125. if (MaxRequestsReached()) {
  126. Cb_->OnMaxConn();
  127. bool wasRemoved = Connections->RemoveOld(TInstant::Max());
  128. if (!wasRemoved && Options_.RejectExcessConnections) {
  129. (new TClientConnection(s, this, listenerSockAddrRef))->Reject();
  130. return;
  131. }
  132. }
  133. auto connection = new TClientConnection(s, this, listenerSockAddrRef);
  134. connection->LastUsed = now;
  135. connection->DeActivate();
  136. }
  137. void SaveErrorCode() {
  138. ErrorCode = WSAGetLastError();
  139. }
  140. int GetErrorCode() const {
  141. return ErrorCode;
  142. }
  143. const char* GetError() const {
  144. return LastSystemErrorText(ErrorCode);
  145. }
  146. bool Start() {
  147. Poller.Reset(new TSocketPoller());
  148. Connections.Reset(new TConnections(Poller.Get(), Options_));
  149. // Start the listener thread
  150. ListenerRunningOK = false;
  151. // throws on error
  152. TPipeHandle::Pipe(ListenWakeupReadFd, ListenWakeupWriteFd);
  153. SetNonBlock(ListenWakeupWriteFd, true);
  154. SetNonBlock(ListenWakeupReadFd, true);
  155. Poller->WaitRead(ListenWakeupReadFd, &WakeupPollAble);
  156. ListenStartEvent.Reset();
  157. try {
  158. ListenThread.Reset(new TThread(ListenSocketFunction, this));
  159. ListenThread->Start();
  160. } catch (const yexception&) {
  161. SaveErrorCode();
  162. return false;
  163. }
  164. // Wait until the thread has completely started and return the success indicator
  165. ListenStartEvent.Wait();
  166. return ListenerRunningOK;
  167. }
  168. void Wait() {
  169. Cb_->OnWait();
  170. TGuard<TMutex> g(StopMutex);
  171. if (ListenThread) {
  172. ListenThread->Join();
  173. ListenThread.Reset(nullptr);
  174. }
  175. }
  176. void Stop() {
  177. Shutdown();
  178. TGuard<TMutex> g(StopMutex);
  179. if (ListenThread) {
  180. ListenThread->Join();
  181. ListenThread.Reset(nullptr);
  182. }
  183. while (ConnectionCount) {
  184. usleep(10000);
  185. Connections->Clear();
  186. }
  187. Connections.Destroy();
  188. Poller.Destroy();
  189. }
  190. void Shutdown() {
  191. ListenWakeupWriteFd.Write("", 1);
  192. // ignore result
  193. }
  194. void AddRequest(TAutoPtr<TClientRequest> req, bool fail) {
  195. struct TFailRequest: public THttpClientRequestEx {
  196. inline TFailRequest(TAutoPtr<TClientRequest> parent) {
  197. Conn_.Reset(parent->Conn_.Release());
  198. HttpConn_.Reset(parent->HttpConn_.Release());
  199. }
  200. bool Reply(void*) override {
  201. if (!ProcessHeaders()) {
  202. return true;
  203. }
  204. ProcessFailRequest(0);
  205. return true;
  206. }
  207. };
  208. if (!fail && Requests->Add(req.Get())) {
  209. Y_UNUSED(req.Release());
  210. } else {
  211. req = new TFailRequest(req);
  212. if (FailRequests->Add(req.Get())) {
  213. Y_UNUSED(req.Release());
  214. } else {
  215. Cb_->OnFailRequest(-1);
  216. }
  217. }
  218. }
  219. size_t GetRequestQueueSize() const {
  220. return Requests->Size();
  221. }
  222. size_t GetFailQueueSize() const {
  223. return FailRequests->Size();
  224. }
  225. const IThreadPool& GetRequestQueue() const {
  226. return *Requests;
  227. }
  228. const IThreadPool& GetFailQueue() const {
  229. return *FailRequests;
  230. }
  231. class TListenSocket: public IPollAble, public TIntrusiveListItem<TListenSocket> {
  232. public:
  233. inline TListenSocket(const TSocket& s, TImpl* parent)
  234. : S_(s)
  235. , Server_(parent)
  236. , SockAddrRef_(GetSockAddr(S_))
  237. {
  238. }
  239. ~TListenSocket() override {
  240. }
  241. void OnPollEvent(TInstant) override {
  242. SOCKET s = ::accept(S_, nullptr, nullptr);
  243. if (s == INVALID_SOCKET) {
  244. ythrow yexception() << "accept: " << LastSystemErrorText();
  245. }
  246. Server_->AddRequestFromSocket(s, TInstant::Now(), SockAddrRef_);
  247. }
  248. SOCKET GetSocket() const noexcept {
  249. return S_;
  250. }
  251. private:
  252. TSocket S_;
  253. TImpl* Server_ = nullptr;
  254. NAddr::IRemoteAddrRef SockAddrRef_;
  255. };
  256. void ListenSocket() {
  257. TThread::SetCurrentThreadName(Options_.ListenThreadName.c_str());
  258. ErrorCode = 0;
  259. TIntrusiveListWithAutoDelete<TListenSocket, TDelete> Reqs;
  260. std::function<void(TSocket)> callback = [&](TSocket socket) {
  261. THolder<TListenSocket> ls(new TListenSocket(socket, this));
  262. Poller->WaitRead(socket, static_cast<IPollAble*>(ls.Get()));
  263. Reqs.PushBack(ls.Release());
  264. };
  265. bool addressesBound = TryToBindAddresses(Options_, &callback);
  266. if (!addressesBound) {
  267. SaveErrorCode();
  268. ListenStartEvent.Signal();
  269. return;
  270. }
  271. Requests->Start(Options_.nThreads, Options_.MaxQueueSize);
  272. FailRequests->Start(Options_.nFThreads, Options_.MaxFQueueSize);
  273. Cb_->OnListenStart();
  274. ListenerRunningOK = true;
  275. ListenStartEvent.Signal();
  276. TVector<void*> events;
  277. events.resize(1);
  278. TInstant now = TInstant::Now();
  279. for (;;) {
  280. try {
  281. const TInstant deadline = Options_.PollTimeout == TDuration::Zero() ? TInstant::Max() : now + Options_.PollTimeout;
  282. const size_t ret = Poller->WaitD(events.data(), events.size(), deadline);
  283. now = TInstant::Now();
  284. for (size_t i = 0; i < ret; ++i) {
  285. ((IPollAble*)events[i])->OnPollEvent(now);
  286. }
  287. if (ret == 0 && Options_.ExpirationTimeout > TDuration::Zero()) {
  288. Connections->RemoveOld(now - Options_.ExpirationTimeout);
  289. }
  290. // When MaxConnections is limited or ExpirationTimeout is set, OnPollEvent can call
  291. // RemoveOld and destroy other IPollAble* objects in the
  292. // poller. Thus in this case we can safely process only one
  293. // event from the poller at a time.
  294. if (!Options_.MaxConnections && Options_.ExpirationTimeout == TDuration::Zero()) {
  295. if (ret >= events.size()) {
  296. events.resize(ret * 2);
  297. }
  298. }
  299. } catch (const TShouldStop&) {
  300. break;
  301. } catch (...) {
  302. Cb_->OnException();
  303. }
  304. }
  305. while (!Reqs.Empty()) {
  306. THolder<TListenSocket> ls(Reqs.PopFront());
  307. Poller->Unwait(ls->GetSocket());
  308. }
  309. Requests->Stop();
  310. FailRequests->Stop();
  311. Cb_->OnListenStop();
  312. }
  313. void RestartRequestThreads(ui32 nTh, ui32 maxQS) {
  314. Requests->Stop();
  315. Options_.nThreads = nTh;
  316. Options_.MaxQueueSize = maxQS;
  317. Requests->Start(Options_.nThreads, Options_.MaxQueueSize);
  318. }
  319. TImpl(THttpServer* parent, ICallBack* cb, TMtpQueueRef mainWorkers, TMtpQueueRef failWorkers, const TOptions& options_)
  320. : Requests(mainWorkers)
  321. , FailRequests(failWorkers)
  322. , Options_(options_)
  323. , Cb_(cb)
  324. , Parent_(parent)
  325. {
  326. }
  327. TImpl(THttpServer* parent, ICallBack* cb, const TOptions& options, IThreadFactory* factory)
  328. : TImpl(
  329. parent,
  330. cb,
  331. MakeThreadPool<TSimpleThreadPool>(factory, options.UseElasticQueues, cb, options.RequestsThreadName),
  332. MakeThreadPool<TThreadPool>(factory, options.UseElasticQueues, nullptr, options.FailRequestsThreadName),
  333. options) {
  334. }
  335. ~TImpl() {
  336. try {
  337. Stop();
  338. } catch (...) {
  339. }
  340. }
  341. inline const TOptions& Options() const noexcept {
  342. return Options_;
  343. }
  344. inline void DecreaseConnections() noexcept {
  345. AtomicDecrement(ConnectionCount);
  346. }
  347. inline void IncreaseConnections() noexcept {
  348. AtomicIncrement(ConnectionCount);
  349. }
  350. inline i64 GetClientCount() const {
  351. return AtomicGet(ConnectionCount);
  352. }
  353. inline bool MaxRequestsReached() const {
  354. return Options_.MaxConnections && ((size_t)GetClientCount() >= Options_.MaxConnections);
  355. }
  356. THolder<TThread> ListenThread;
  357. TPipeHandle ListenWakeupReadFd;
  358. TPipeHandle ListenWakeupWriteFd;
  359. TSystemEvent ListenStartEvent;
  360. TMtpQueueRef Requests;
  361. TMtpQueueRef FailRequests;
  362. TAtomic ConnectionCount = 0;
  363. THolder<TSocketPoller> Poller;
  364. THolder<TConnections> Connections;
  365. bool ListenerRunningOK = false;
  366. int ErrorCode = 0;
  367. TOptions Options_;
  368. ICallBack* Cb_ = nullptr;
  369. THttpServer* Parent_ = nullptr;
  370. TWakeupPollAble WakeupPollAble;
  371. TMutex StopMutex;
  372. private:
  373. template <class TThreadPool_>
  374. static THolder<IThreadPool> MakeThreadPool(IThreadFactory* factory, bool elastic, ICallBack* callback = nullptr, const TString& threadName = {}) {
  375. if (!factory) {
  376. factory = SystemThreadFactory();
  377. }
  378. THolder<IThreadPool> pool;
  379. const auto params = IThreadPool::TParams().SetFactory(factory).SetThreadName(threadName);
  380. if (callback) {
  381. pool = MakeHolder<TThreadPoolBinder<TThreadPool_, THttpServer::ICallBack>>(callback, params);
  382. } else {
  383. pool = MakeHolder<TThreadPool_>(params);
  384. }
  385. if (elastic) {
  386. pool = MakeHolder<TElasticQueue>(std::move(pool));
  387. }
  388. return pool;
  389. }
  390. };
  391. THttpServer::THttpServer(ICallBack* cb, const TOptions& options, IThreadFactory* pool)
  392. : Impl_(new TImpl(this, cb, options, pool))
  393. {
  394. }
  395. THttpServer::THttpServer(ICallBack* cb, TMtpQueueRef mainWorkers, TMtpQueueRef failWorkers, const TOptions& options)
  396. : Impl_(new TImpl(this, cb, mainWorkers, failWorkers, options))
  397. {
  398. }
  399. THttpServer::~THttpServer() {
  400. }
  401. i64 THttpServer::GetClientCount() const {
  402. return Impl_->GetClientCount();
  403. }
  404. bool THttpServer::Start() {
  405. return Impl_->Start();
  406. }
  407. void THttpServer::Stop() {
  408. Impl_->Stop();
  409. }
  410. void THttpServer::Shutdown() {
  411. Impl_->Shutdown();
  412. }
  413. void THttpServer::Wait() {
  414. Impl_->Wait();
  415. }
  416. int THttpServer::GetErrorCode() {
  417. return Impl_->GetErrorCode();
  418. }
  419. const char* THttpServer::GetError() {
  420. return Impl_->GetError();
  421. }
  422. void THttpServer::RestartRequestThreads(ui32 n, ui32 queue) {
  423. Impl_->RestartRequestThreads(n, queue);
  424. }
  425. const THttpServer::TOptions& THttpServer::Options() const noexcept {
  426. return Impl_->Options();
  427. }
  428. size_t THttpServer::GetRequestQueueSize() const {
  429. return Impl_->GetRequestQueueSize();
  430. }
  431. size_t THttpServer::GetFailQueueSize() const {
  432. return Impl_->GetFailQueueSize();
  433. }
  434. const IThreadPool& THttpServer::GetRequestQueue() const {
  435. return Impl_->GetRequestQueue();
  436. }
  437. const IThreadPool& THttpServer::GetFailQueue() const {
  438. return Impl_->GetFailQueue();
  439. }
  440. bool THttpServer::MaxRequestsReached() const {
  441. return Impl_->MaxRequestsReached();
  442. }
  443. TClientConnection::TClientConnection(const TSocket& s, THttpServer::TImpl* serv, NAddr::IRemoteAddrRef listenerSockAddrRef)
  444. : Socket_(s)
  445. , ListenerSockAddrRef_(listenerSockAddrRef)
  446. , HttpServ_(serv)
  447. {
  448. SetNoDelay(Socket_, true);
  449. const TDuration& clientTimeout = HttpServ_->Options().ClientTimeout;
  450. if (clientTimeout != TDuration::Zero()) {
  451. SetSocketTimeout(Socket_, (long)clientTimeout.Seconds(), clientTimeout.MilliSecondsOfSecond());
  452. }
  453. HttpServ_->IncreaseConnections();
  454. }
  455. TClientConnection::~TClientConnection() {
  456. HttpServ_->DecreaseConnections();
  457. }
  458. void TClientConnection::OnPollEvent(TInstant now) {
  459. THolder<TClientConnection> this_(this);
  460. Activate(now);
  461. {
  462. char tmp[1];
  463. if (::recv(Socket_, tmp, 1, MSG_PEEK) < 1) {
  464. /*
  465. * We can received a FIN so our socket was moved to
  466. * TCP_CLOSE_WAIT state. Check it before adding work
  467. * for this socket.
  468. */
  469. return;
  470. }
  471. }
  472. THolder<TClientRequest> obj(HttpServ_->CreateRequest(this_));
  473. AcceptMoment = now;
  474. HttpServ_->AddRequest(obj, Reject_);
  475. }
  476. void TClientConnection::Activate(TInstant now) noexcept {
  477. HttpServ_->Connections->Erase(this, now);
  478. LastUsed = now;
  479. ++ReceivedRequests;
  480. }
  481. void TClientConnection::DeActivate() {
  482. HttpServ_->Connections->Add(this);
  483. }
  484. void TClientConnection::Reject() {
  485. Reject_ = true;
  486. HttpServ_->Connections->Add(this);
  487. }
  488. TClientRequest::TClientRequest() {
  489. }
  490. TClientRequest::~TClientRequest() {
  491. }
  492. bool TClientRequest::Reply(void* /*ThreadSpecificResource*/) {
  493. if (strnicmp(RequestString.data(), "GET ", 4)) {
  494. Output() << "HTTP/1.0 501 Not Implemented\r\n\r\n";
  495. } else {
  496. Output() << "HTTP/1.0 200 OK\r\n"
  497. "Content-Type: text/html\r\n"
  498. "\r\n"
  499. "Hello World!\r\n";
  500. }
  501. return true;
  502. }
  503. bool TClientRequest::IsLocal() const {
  504. return HasLocalAddress(Socket());
  505. }
  506. bool TClientRequest::CheckLoopback() {
  507. bool isLocal = false;
  508. try {
  509. isLocal = IsLocal();
  510. } catch (const yexception& e) {
  511. Output() << "HTTP/1.0 500 Oops\r\n\r\n"
  512. << e.what() << "\r\n";
  513. return false;
  514. }
  515. if (!isLocal) {
  516. Output() << "HTTP/1.0 403 Permission denied\r\n"
  517. "Content-Type: text/html; charset=windows-1251\r\n"
  518. "Connection: close\r\n"
  519. "\r\n"
  520. "<html><head><title>Permission denied</title></head>"
  521. "<body><h1>Permission denied</h1>"
  522. "<p>This request must be sent from the localhost.</p>"
  523. "</body></html>\r\n";
  524. return false;
  525. }
  526. return true;
  527. }
  528. void TClientRequest::ReleaseConnection() {
  529. if (Conn_ && HttpConn_ && HttpServ()->Options().KeepAliveEnabled && HttpConn_->CanBeKeepAlive() && (!HttpServ()->Options().RejectExcessConnections || !HttpServ()->MaxRequestsReached())) {
  530. Output().Finish();
  531. Conn_->DeActivate();
  532. Y_UNUSED(Conn_.Release());
  533. }
  534. }
  535. void TClientRequest::ResetConnection() {
  536. if (HttpConn_) {
  537. // send RST packet to client
  538. HttpConn_->Reset();
  539. HttpConn_.Destroy();
  540. }
  541. }
  542. void TClientRequest::Process(void* ThreadSpecificResource) {
  543. THolder<TClientRequest> this_(this);
  544. auto* serverImpl = Conn_->HttpServ_;
  545. try {
  546. if (!HttpConn_) {
  547. const size_t outputBufferSize = HttpServ()->Options().OutputBufferSize;
  548. if (outputBufferSize) {
  549. HttpConn_.Reset(new THttpServerConn(Socket(), outputBufferSize));
  550. } else {
  551. HttpConn_.Reset(new THttpServerConn(Socket()));
  552. }
  553. auto maxRequestsPerConnection = HttpServ()->Options().MaxRequestsPerConnection;
  554. HttpConn_->Output()->EnableKeepAlive(HttpServ()->Options().KeepAliveEnabled && (!maxRequestsPerConnection || Conn_->ReceivedRequests < maxRequestsPerConnection));
  555. HttpConn_->Output()->EnableCompression(HttpServ()->Options().CompressionEnabled);
  556. }
  557. if (ParsedHeaders.empty()) {
  558. RequestString = Input().FirstLine();
  559. const THttpHeaders& h = Input().Headers();
  560. ParsedHeaders.reserve(h.Count());
  561. for (THttpHeaders::TConstIterator it = h.Begin(); it != h.End(); ++it) {
  562. ParsedHeaders.emplace_back(it->Name(), it->Value());
  563. }
  564. }
  565. if (Reply(ThreadSpecificResource)) {
  566. ReleaseConnection();
  567. /*
  568. * *this will be destroyed...
  569. */
  570. return;
  571. }
  572. } catch (...) {
  573. serverImpl->Cb_->OnException();
  574. throw;
  575. }
  576. Y_UNUSED(this_.Release());
  577. }
  578. void TClientRequest::ProcessFailRequest(int failstate) {
  579. Output() << "HTTP/1.1 503 Service Unavailable\r\n"
  580. "Content-Type: text/plain\r\n"
  581. "Content-Length: 21\r\n"
  582. "\r\n"
  583. "Service Unavailable\r\n";
  584. TString url;
  585. if (!strnicmp(RequestString.data(), "GET ", 4)) {
  586. // Trying to extract url...
  587. const char* str = RequestString.data();
  588. // Skipping spaces before url...
  589. size_t start = 3;
  590. while (str[start] == ' ') {
  591. ++start;
  592. }
  593. if (str[start]) {
  594. // Traversing url...
  595. size_t idx = start;
  596. while (str[idx] != ' ' && str[idx]) {
  597. ++idx;
  598. }
  599. url = RequestString.substr(start, idx - start);
  600. }
  601. }
  602. const THttpServer::ICallBack::TFailLogData d = {
  603. failstate,
  604. url,
  605. };
  606. // Handling failure...
  607. Conn_->HttpServ_->Cb_->OnFailRequestEx(d);
  608. Output().Flush();
  609. }
  610. THttpServer* TClientRequest::HttpServ() const noexcept {
  611. return Conn_->HttpServ_->Parent_;
  612. }
  613. const TSocket& TClientRequest::Socket() const noexcept {
  614. return Conn_->Socket_;
  615. }
  616. NAddr::IRemoteAddrRef TClientRequest::GetListenerSockAddrRef() const noexcept {
  617. return Conn_->ListenerSockAddrRef_;
  618. }
  619. TInstant TClientRequest::AcceptMoment() const noexcept {
  620. return Conn_->AcceptMoment;
  621. }
  622. /*
  623. * TRequestReplier
  624. */
  625. TRequestReplier::TRequestReplier() {
  626. }
  627. TRequestReplier::~TRequestReplier() {
  628. }
  629. bool TRequestReplier::Reply(void* threadSpecificResource) {
  630. const TReplyParams params = {
  631. threadSpecificResource, Input(), Output()};
  632. return DoReply(params);
  633. }
  634. bool TryToBindAddresses(const THttpServerOptions& options, const std::function<void(TSocket)>* callbackOnBoundAddress) {
  635. THttpServerOptions::TBindAddresses addrs;
  636. try {
  637. options.BindAddresses(addrs);
  638. } catch (const std::exception&) {
  639. return false;
  640. }
  641. for (const auto& na : addrs) {
  642. for (TNetworkAddress::TIterator ai = na.Begin(); ai != na.End(); ++ai) {
  643. NAddr::TAddrInfo addr(&*ai);
  644. TSocket socket(::socket(addr.Addr()->sa_family, SOCK_STREAM, 0));
  645. if (socket == INVALID_SOCKET) {
  646. return false;
  647. }
  648. FixIPv6ListenSocket(socket);
  649. if (options.ReuseAddress) {
  650. int yes = 1;
  651. ::setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(yes));
  652. }
  653. if (options.ReusePort) {
  654. SetReusePort(socket, true);
  655. }
  656. if (::bind(socket, addr.Addr(), addr.Len()) == SOCKET_ERROR) {
  657. return false;
  658. }
  659. if (::listen(socket, options.ListenBacklog) == SOCKET_ERROR) {
  660. return false;
  661. }
  662. if (callbackOnBoundAddress != nullptr) {
  663. (*callbackOnBoundAddress)(socket);
  664. }
  665. }
  666. }
  667. return true;
  668. }