aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/http/server
diff options
context:
space:
mode:
authorAnton Samokhvalov <pg83@yandex.ru>2022-02-10 16:45:15 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:15 +0300
commit72cb13b4aff9bc9cf22e49251bc8fd143f82538f (patch)
treeda2c34829458c7d4e74bdfbdf85dff449e9e7fb8 /library/cpp/http/server
parent778e51ba091dc39e7b7fcab2b9cf4dbedfb6f2b5 (diff)
downloadydb-72cb13b4aff9bc9cf22e49251bc8fd143f82538f.tar.gz
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 1 of 2.
Diffstat (limited to 'library/cpp/http/server')
-rw-r--r--library/cpp/http/server/conn.cpp84
-rw-r--r--library/cpp/http/server/conn.h56
-rw-r--r--library/cpp/http/server/http.cpp566
-rw-r--r--library/cpp/http/server/http.h86
-rw-r--r--library/cpp/http/server/http_ex.cpp120
-rw-r--r--library/cpp/http/server/http_ex.h24
-rw-r--r--library/cpp/http/server/http_ut.cpp140
-rw-r--r--library/cpp/http/server/options.cpp44
-rw-r--r--library/cpp/http/server/options.h130
-rw-r--r--library/cpp/http/server/response.cpp32
-rw-r--r--library/cpp/http/server/response.h26
-rw-r--r--library/cpp/http/server/response_ut.cpp26
-rw-r--r--library/cpp/http/server/ut/ya.make4
-rw-r--r--library/cpp/http/server/ya.make28
14 files changed, 683 insertions, 683 deletions
diff --git a/library/cpp/http/server/conn.cpp b/library/cpp/http/server/conn.cpp
index 38a76c4c30..dd0860a315 100644
--- a/library/cpp/http/server/conn.cpp
+++ b/library/cpp/http/server/conn.cpp
@@ -1,31 +1,31 @@
-#include "conn.h"
-
-#include <util/network/socket.h>
+#include "conn.h"
+
+#include <util/network/socket.h>
#include <util/stream/buffered.h>
-
-class THttpServerConn::TImpl {
-public:
+
+class THttpServerConn::TImpl {
+public:
inline TImpl(const TSocket& s, size_t outputBufferSize)
- : S_(s)
- , SI_(S_)
- , SO_(S_)
+ : S_(s)
+ , SI_(S_)
+ , SO_(S_)
, BO_(&SO_, outputBufferSize)
- , HI_(&SI_)
- , HO_(&BO_, &HI_)
- {
- }
-
+ , HI_(&SI_)
+ , HO_(&BO_, &HI_)
+ {
+ }
+
inline ~TImpl() {
- }
-
+ }
+
inline THttpInput* Input() noexcept {
- return &HI_;
- }
-
+ return &HI_;
+ }
+
inline THttpOutput* Output() noexcept {
- return &HO_;
- }
-
+ return &HO_;
+ }
+
inline void Reset() {
if (S_ != INVALID_SOCKET) {
// send RST packet to client
@@ -34,35 +34,35 @@ public:
}
}
-private:
- TSocket S_;
- TSocketInput SI_;
- TSocketOutput SO_;
- TBufferedOutput BO_;
- THttpInput HI_;
- THttpOutput HO_;
-};
-
-THttpServerConn::THttpServerConn(const TSocket& s)
+private:
+ TSocket S_;
+ TSocketInput SI_;
+ TSocketOutput SO_;
+ TBufferedOutput BO_;
+ THttpInput HI_;
+ THttpOutput HO_;
+};
+
+THttpServerConn::THttpServerConn(const TSocket& s)
: THttpServerConn(s, s.MaximumTransferUnit())
-{
-}
-
+{
+}
+
THttpServerConn::THttpServerConn(const TSocket& s, size_t outputBufferSize)
: Impl_(new TImpl(s, outputBufferSize))
{
}
THttpServerConn::~THttpServerConn() {
-}
-
+}
+
THttpInput* THttpServerConn::Input() noexcept {
- return Impl_->Input();
-}
-
+ return Impl_->Input();
+}
+
THttpOutput* THttpServerConn::Output() noexcept {
- return Impl_->Output();
-}
+ return Impl_->Output();
+}
void THttpServerConn::Reset() {
return Impl_->Reset();
diff --git a/library/cpp/http/server/conn.h b/library/cpp/http/server/conn.h
index 3aa5329af4..93c2358c23 100644
--- a/library/cpp/http/server/conn.h
+++ b/library/cpp/http/server/conn.h
@@ -1,37 +1,37 @@
-#pragma once
-
+#pragma once
+
#include <library/cpp/http/io/stream.h>
-#include <util/generic/ptr.h>
-
-class TSocket;
-
-/// Потоки ввода/вывода для получения запросов и отправки ответов HTTP-сервера.
-class THttpServerConn {
-public:
- explicit THttpServerConn(const TSocket& s);
- THttpServerConn(const TSocket& s, size_t outputBufferSize);
+#include <util/generic/ptr.h>
+
+class TSocket;
+
+/// Потоки ввода/вывода для получения запросов и отправки ответов HTTP-сервера.
+class THttpServerConn {
+public:
+ explicit THttpServerConn(const TSocket& s);
+ THttpServerConn(const TSocket& s, size_t outputBufferSize);
~THttpServerConn();
-
+
THttpInput* Input() noexcept;
THttpOutput* Output() noexcept;
-
+
inline const THttpInput* Input() const noexcept {
- return const_cast<THttpServerConn*>(this)->Input();
- }
-
+ return const_cast<THttpServerConn*>(this)->Input();
+ }
+
inline const THttpOutput* Output() const noexcept {
- return const_cast<THttpServerConn*>(this)->Output();
- }
-
- /// Проверяет, можно ли установить режим, при котором соединение с сервером
- /// не завершается после окончания транзакции.
+ return const_cast<THttpServerConn*>(this)->Output();
+ }
+
+ /// Проверяет, можно ли установить режим, при котором соединение с сервером
+ /// не завершается после окончания транзакции.
inline bool CanBeKeepAlive() const noexcept {
- return Output()->CanBeKeepAlive();
- }
-
+ return Output()->CanBeKeepAlive();
+ }
+
void Reset();
-private:
- class TImpl;
- THolder<TImpl> Impl_;
-};
+private:
+ class TImpl;
+ THolder<TImpl> Impl_;
+};
diff --git a/library/cpp/http/server/http.cpp b/library/cpp/http/server/http.cpp
index 128583bdd7..581fc77399 100644
--- a/library/cpp/http/server/http.cpp
+++ b/library/cpp/http/server/http.cpp
@@ -1,12 +1,12 @@
#include "http.h"
#include "http_ex.h"
-
+
#include <library/cpp/threading/equeue/equeue.h>
#include <util/generic/buffer.h>
#include <util/generic/cast.h>
-#include <util/generic/intrlist.h>
-#include <util/generic/yexception.h>
+#include <util/generic/intrlist.h>
+#include <util/generic/yexception.h>
#include <util/network/address.h>
#include <util/network/socket.h>
#include <util/network/poller.h>
@@ -18,7 +18,7 @@
#include <util/system/pipe.h>
#include <util/system/thread.h>
#include <util/thread/factory.h>
-
+
#include <cerrno>
#include <cstring>
#include <ctime>
@@ -28,39 +28,39 @@
using namespace NAddr;
-namespace {
- class IPollAble {
- public:
+namespace {
+ class IPollAble {
+ public:
inline IPollAble() noexcept {
- }
-
- virtual ~IPollAble() {
- }
-
+ }
+
+ virtual ~IPollAble() {
+ }
+
virtual void OnPollEvent(TInstant now) = 0;
- };
+ };
+
+ struct TShouldStop {
+ };
- struct TShouldStop {
- };
-
- struct TWakeupPollAble: public IPollAble {
+ struct TWakeupPollAble: public IPollAble {
void OnPollEvent(TInstant) override {
- throw TShouldStop();
- }
- };
-}
-
-class TClientConnection: public IPollAble, public TIntrusiveListItem<TClientConnection> {
+ throw TShouldStop();
+ }
+ };
+}
+
+class TClientConnection: public IPollAble, public TIntrusiveListItem<TClientConnection> {
public:
TClientConnection(const TSocket& s, THttpServer::TImpl* serv, NAddr::IRemoteAddrRef listenerSockAddrRef);
~TClientConnection() override;
-
+
void OnPollEvent(TInstant now) override;
-
+
inline void Activate(TInstant now) noexcept;
inline void DeActivate();
inline void Reject();
-
+
public:
TSocket Socket_;
NAddr::IRemoteAddrRef ListenerSockAddrRef_;
@@ -69,28 +69,28 @@ public:
TInstant LastUsed;
TInstant AcceptMoment;
size_t ReceivedRequests = 0;
-};
-
-class THttpServer::TImpl {
+};
+
+class THttpServer::TImpl {
public:
class TConnections {
- public:
+ public:
inline TConnections(TSocketPoller* poller, const THttpServerOptions& options)
: Poller_(poller)
, Options(options)
{
}
-
+
inline ~TConnections() {
}
-
+
inline void Add(TClientConnection* c) noexcept {
TGuard<TMutex> g(Mutex_);
-
+
Conns_.PushBack(c);
Poller_->WaitRead(c->Socket_, (void*)static_cast<const IPollAble*>(c));
}
-
+
inline void Erase(TClientConnection* c, TInstant now) noexcept {
TGuard<TMutex> g(Mutex_);
EraseUnsafe(c);
@@ -98,18 +98,18 @@ public:
TryRemovingUnsafe(now - Options.ExpirationTimeout);
}
}
-
+
inline void Clear() noexcept {
TGuard<TMutex> g(Mutex_);
-
+
Conns_.Clear();
}
-
+
inline bool RemoveOld(TInstant border) noexcept {
TGuard<TMutex> g(Mutex_);
return TryRemovingUnsafe(border);
}
-
+
bool TryRemovingUnsafe(TInstant border) noexcept {
if (Conns_.Empty()) {
return false;
@@ -122,7 +122,7 @@ public:
delete c;
return true;
}
-
+
void EraseUnsafe(TClientConnection* c) noexcept {
Poller_->Unwait(c->Socket_);
c->Unlink();
@@ -134,7 +134,7 @@ public:
TSocketPoller* Poller_ = nullptr;
const THttpServerOptions& Options;
};
-
+
static void* ListenSocketFunction(void* param) {
try {
((TImpl*)param)->ListenSocket();
@@ -144,10 +144,10 @@ public:
return nullptr;
}
-
+
TAutoPtr<TClientRequest> CreateRequest(TAutoPtr<TClientConnection> c) {
THolder<TClientRequest> obj(Cb_->CreateClient());
-
+
obj->Conn_.Reset(c.Release());
return obj;
@@ -161,13 +161,13 @@ public:
(new TClientConnection(s, this, listenerSockAddrRef))->Reject();
return;
}
- }
-
+ }
+
auto connection = new TClientConnection(s, this, listenerSockAddrRef);
connection->LastUsed = now;
connection->DeActivate();
}
-
+
void SaveErrorCode() {
ErrorCode = WSAGetLastError();
}
@@ -175,11 +175,11 @@ public:
int GetErrorCode() const {
return ErrorCode;
}
-
+
const char* GetError() const {
return LastSystemErrorText(ErrorCode);
}
-
+
bool Start() {
Poller.Reset(new TSocketPoller());
Connections.Reset(new TConnections(Poller.Get(), Options_));
@@ -202,14 +202,14 @@ public:
} catch (const yexception&) {
SaveErrorCode();
return false;
- }
-
+ }
+
// Wait until the thread has completely started and return the success indicator
ListenStartEvent.Wait();
-
+
return ListenerRunningOK;
}
-
+
void Wait() {
Cb_->OnWait();
TGuard<TMutex> g(StopMutex);
@@ -227,46 +227,46 @@ public:
ListenThread->Join();
ListenThread.Reset(nullptr);
}
-
+
while (ConnectionCount) {
usleep(10000);
Connections->Clear();
- }
-
+ }
+
Connections.Destroy();
Poller.Destroy();
}
-
+
void Shutdown() {
ListenWakeupWriteFd.Write("", 1);
// ignore result
}
-
+
void AddRequest(TAutoPtr<TClientRequest> req, bool fail) {
struct TFailRequest: public THttpClientRequestEx {
- inline TFailRequest(TAutoPtr<TClientRequest> parent) {
- Conn_.Reset(parent->Conn_.Release());
- HttpConn_.Reset(parent->HttpConn_.Release());
- }
-
+ inline TFailRequest(TAutoPtr<TClientRequest> parent) {
+ Conn_.Reset(parent->Conn_.Release());
+ HttpConn_.Reset(parent->HttpConn_.Release());
+ }
+
bool Reply(void*) override {
if (!ProcessHeaders()) {
return true;
}
- ProcessFailRequest(0);
- return true;
- }
+ ProcessFailRequest(0);
+ return true;
+ }
};
-
+
if (!fail && Requests->Add(req.Get())) {
Y_UNUSED(req.Release());
} else {
req = new TFailRequest(req);
-
+
if (FailRequests->Add(req.Get())) {
Y_UNUSED(req.Release());
- } else {
+ } else {
Cb_->OnFailRequest(-1);
}
}
@@ -288,44 +288,44 @@ public:
return *FailRequests;
}
- class TListenSocket: public IPollAble, public TIntrusiveListItem<TListenSocket> {
- public:
- inline TListenSocket(const TSocket& s, TImpl* parent)
- : S_(s)
- , Server_(parent)
+ class TListenSocket: public IPollAble, public TIntrusiveListItem<TListenSocket> {
+ public:
+ inline TListenSocket(const TSocket& s, TImpl* parent)
+ : S_(s)
+ , Server_(parent)
, SockAddrRef_(GetSockAddr(S_))
- {
- }
-
+ {
+ }
+
~TListenSocket() override {
- }
-
+ }
+
void OnPollEvent(TInstant) override {
SOCKET s = ::accept(S_, nullptr, nullptr);
-
- if (s == INVALID_SOCKET) {
- ythrow yexception() << "accept: " << LastSystemErrorText();
+
+ if (s == INVALID_SOCKET) {
+ ythrow yexception() << "accept: " << LastSystemErrorText();
}
Server_->AddRequestFromSocket(s, TInstant::Now(), SockAddrRef_);
- }
+ }
SOCKET GetSocket() const noexcept {
- return S_;
- }
-
- private:
- TSocket S_;
+ return S_;
+ }
+
+ private:
+ TSocket S_;
TImpl* Server_ = nullptr;
NAddr::IRemoteAddrRef SockAddrRef_;
};
-
+
void ListenSocket() {
TThread::SetCurrentThreadName(Options_.ListenThreadName.c_str());
ErrorCode = 0;
TIntrusiveListWithAutoDelete<TListenSocket, TDelete> Reqs;
-
+
std::function<void(TSocket)> callback = [&](TSocket socket) {
THolder<TListenSocket> ls(new TListenSocket(socket, this));
Poller->WaitRead(socket, static_cast<IPollAble*>(ls.Get()));
@@ -335,7 +335,7 @@ public:
if (!addressesBound) {
SaveErrorCode();
ListenStartEvent.Signal();
-
+
return;
}
@@ -347,18 +347,18 @@ public:
TVector<void*> events;
events.resize(1);
-
+
TInstant now = TInstant::Now();
- for (;;) {
+ for (;;) {
try {
const TInstant deadline = Options_.PollTimeout == TDuration::Zero() ? TInstant::Max() : now + Options_.PollTimeout;
const size_t ret = Poller->WaitD(events.data(), events.size(), deadline);
-
+
now = TInstant::Now();
for (size_t i = 0; i < ret; ++i) {
((IPollAble*)events[i])->OnPollEvent(now);
}
-
+
if (ret == 0 && Options_.ExpirationTimeout > TDuration::Zero()) {
Connections->RemoveOld(now - Options_.ExpirationTimeout);
}
@@ -370,26 +370,26 @@ public:
if (!Options_.MaxConnections && Options_.ExpirationTimeout == TDuration::Zero()) {
if (ret >= events.size()) {
events.resize(ret * 2);
- }
- }
- } catch (const TShouldStop&) {
- break;
+ }
+ }
+ } catch (const TShouldStop&) {
+ break;
} catch (...) {
Cb_->OnException();
- }
- }
+ }
+ }
while (!Reqs.Empty()) {
THolder<TListenSocket> ls(Reqs.PopFront());
-
+
Poller->Unwait(ls->GetSocket());
- }
-
+ }
+
Requests->Stop();
FailRequests->Stop();
Cb_->OnListenStop();
}
-
+
void RestartRequestThreads(ui32 nTh, ui32 maxQS) {
Requests->Stop();
Options_.nThreads = nTh;
@@ -408,24 +408,24 @@ public:
TImpl(THttpServer* parent, ICallBack* cb, const TOptions& options, IThreadFactory* factory)
: TImpl(
- parent,
- cb,
+ parent,
+ cb,
MakeThreadPool<TSimpleThreadPool>(factory, options.UseElasticQueues, cb, options.RequestsThreadName),
MakeThreadPool<TThreadPool>(factory, options.UseElasticQueues, nullptr, options.FailRequestsThreadName),
- options) {
+ options) {
}
~TImpl() {
try {
Stop();
} catch (...) {
- }
+ }
}
-
+
inline const TOptions& Options() const noexcept {
return Options_;
}
-
+
inline void DecreaseConnections() noexcept {
AtomicDecrement(ConnectionCount);
}
@@ -439,7 +439,7 @@ public:
}
inline bool MaxRequestsReached() const {
- return Options_.MaxConnections && ((size_t)GetClientCount() >= Options_.MaxConnections);
+ return Options_.MaxConnections && ((size_t)GetClientCount() >= Options_.MaxConnections);
}
THolder<TThread> ListenThread;
@@ -480,57 +480,57 @@ private:
return pool;
}
-};
+};
THttpServer::THttpServer(ICallBack* cb, const TOptions& options, IThreadFactory* pool)
: Impl_(new TImpl(this, cb, options, pool))
-{
-}
-
+{
+}
+
THttpServer::THttpServer(ICallBack* cb, TMtpQueueRef mainWorkers, TMtpQueueRef failWorkers, const TOptions& options)
: Impl_(new TImpl(this, cb, mainWorkers, failWorkers, options))
{
}
-THttpServer::~THttpServer() {
-}
-
+THttpServer::~THttpServer() {
+}
+
i64 THttpServer::GetClientCount() const {
return Impl_->GetClientCount();
}
-bool THttpServer::Start() {
- return Impl_->Start();
-}
-
-void THttpServer::Stop() {
- Impl_->Stop();
-}
-
-void THttpServer::Shutdown() {
- Impl_->Shutdown();
-}
-
-void THttpServer::Wait() {
- Impl_->Wait();
-}
-
-int THttpServer::GetErrorCode() {
- return Impl_->GetErrorCode();
-}
-
-const char* THttpServer::GetError() {
- return Impl_->GetError();
-}
-
-void THttpServer::RestartRequestThreads(ui32 n, ui32 queue) {
- Impl_->RestartRequestThreads(n, queue);
-}
-
+bool THttpServer::Start() {
+ return Impl_->Start();
+}
+
+void THttpServer::Stop() {
+ Impl_->Stop();
+}
+
+void THttpServer::Shutdown() {
+ Impl_->Shutdown();
+}
+
+void THttpServer::Wait() {
+ Impl_->Wait();
+}
+
+int THttpServer::GetErrorCode() {
+ return Impl_->GetErrorCode();
+}
+
+const char* THttpServer::GetError() {
+ return Impl_->GetError();
+}
+
+void THttpServer::RestartRequestThreads(ui32 n, ui32 queue) {
+ Impl_->RestartRequestThreads(n, queue);
+}
+
const THttpServer::TOptions& THttpServer::Options() const noexcept {
- return Impl_->Options();
-}
-
+ return Impl_->Options();
+}
+
size_t THttpServer::GetRequestQueueSize() const {
return Impl_->GetRequestQueueSize();
}
@@ -552,45 +552,45 @@ bool THttpServer::MaxRequestsReached() const {
}
TClientConnection::TClientConnection(const TSocket& s, THttpServer::TImpl* serv, NAddr::IRemoteAddrRef listenerSockAddrRef)
- : Socket_(s)
+ : Socket_(s)
, ListenerSockAddrRef_(listenerSockAddrRef)
- , HttpServ_(serv)
-{
- SetNoDelay(Socket_, true);
-
+ , HttpServ_(serv)
+{
+ SetNoDelay(Socket_, true);
+
const TDuration& clientTimeout = HttpServ_->Options().ClientTimeout;
if (clientTimeout != TDuration::Zero()) {
SetSocketTimeout(Socket_, (long)clientTimeout.Seconds(), clientTimeout.MilliSecondsOfSecond());
}
- HttpServ_->IncreaseConnections();
-}
-
+ HttpServ_->IncreaseConnections();
+}
+
TClientConnection::~TClientConnection() {
- HttpServ_->DecreaseConnections();
-}
-
+ HttpServ_->DecreaseConnections();
+}
+
void TClientConnection::OnPollEvent(TInstant now) {
THolder<TClientConnection> this_(this);
Activate(now);
-
- {
- char tmp[1];
-
- if (::recv(Socket_, tmp, 1, MSG_PEEK) < 1) {
- /*
- * We can received a FIN so our socket was moved to
- * TCP_CLOSE_WAIT state. Check it before adding work
- * for this socket.
- */
-
- return;
- }
- }
-
+
+ {
+ char tmp[1];
+
+ if (::recv(Socket_, tmp, 1, MSG_PEEK) < 1) {
+ /*
+ * We can received a FIN so our socket was moved to
+ * TCP_CLOSE_WAIT state. Check it before adding work
+ * for this socket.
+ */
+
+ return;
+ }
+ }
+
THolder<TClientRequest> obj(HttpServ_->CreateRequest(this_));
AcceptMoment = now;
-
+
HttpServ_->AddRequest(obj, Reject_);
}
@@ -600,35 +600,35 @@ void TClientConnection::Activate(TInstant now) noexcept {
++ReceivedRequests;
}
-void TClientConnection::DeActivate() {
+void TClientConnection::DeActivate() {
HttpServ_->Connections->Add(this);
-}
-
+}
+
void TClientConnection::Reject() {
Reject_ = true;
HttpServ_->Connections->Add(this);
}
-TClientRequest::TClientRequest() {
-}
-
-TClientRequest::~TClientRequest() {
-}
-
-bool TClientRequest::Reply(void* /*ThreadSpecificResource*/) {
+TClientRequest::TClientRequest() {
+}
+
+TClientRequest::~TClientRequest() {
+}
+
+bool TClientRequest::Reply(void* /*ThreadSpecificResource*/) {
if (strnicmp(RequestString.data(), "GET ", 4)) {
- Output() << "HTTP/1.0 501 Not Implemented\r\n\r\n";
- } else {
- Output() << "HTTP/1.0 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "\r\n"
- "Hello World!\r\n";
- }
-
- return true;
-}
-
+ Output() << "HTTP/1.0 501 Not Implemented\r\n\r\n";
+ } else {
+ Output() << "HTTP/1.0 200 OK\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n"
+ "Hello World!\r\n";
+ }
+
+ return true;
+}
+
bool TClientRequest::IsLocal() const {
return HasLocalAddress(Socket());
}
@@ -639,29 +639,29 @@ bool TClientRequest::CheckLoopback() {
try {
isLocal = IsLocal();
} catch (const yexception& e) {
- Output() << "HTTP/1.0 500 Oops\r\n\r\n"
- << e.what() << "\r\n";
- return false;
+ Output() << "HTTP/1.0 500 Oops\r\n\r\n"
+ << e.what() << "\r\n";
+ return false;
}
if (!isLocal) {
- Output() << "HTTP/1.0 403 Permission denied\r\n"
- "Content-Type: text/html; charset=windows-1251\r\n"
- "Connection: close\r\n"
- "\r\n"
- "<html><head><title>Permission denied</title></head>"
- "<body><h1>Permission denied</h1>"
- "<p>This request must be sent from the localhost.</p>"
- "</body></html>\r\n";
-
- return false;
- }
-
- return true;
-}
-
+ Output() << "HTTP/1.0 403 Permission denied\r\n"
+ "Content-Type: text/html; charset=windows-1251\r\n"
+ "Connection: close\r\n"
+ "\r\n"
+ "<html><head><title>Permission denied</title></head>"
+ "<body><h1>Permission denied</h1>"
+ "<p>This request must be sent from the localhost.</p>"
+ "</body></html>\r\n";
+
+ return false;
+ }
+
+ return true;
+}
+
void TClientRequest::ReleaseConnection() {
- if (Conn_ && HttpConn_ && HttpServ()->Options().KeepAliveEnabled && HttpConn_->CanBeKeepAlive() && (!HttpServ()->Options().RejectExcessConnections || !HttpServ()->MaxRequestsReached())) {
+ if (Conn_ && HttpConn_ && HttpServ()->Options().KeepAliveEnabled && HttpConn_->CanBeKeepAlive() && (!HttpServ()->Options().RejectExcessConnections || !HttpServ()->MaxRequestsReached())) {
Output().Finish();
Conn_->DeActivate();
Y_UNUSED(Conn_.Release());
@@ -676,101 +676,101 @@ void TClientRequest::ResetConnection() {
}
}
-void TClientRequest::Process(void* ThreadSpecificResource) {
+void TClientRequest::Process(void* ThreadSpecificResource) {
THolder<TClientRequest> this_(this);
-
+
auto* serverImpl = Conn_->HttpServ_;
- try {
- if (!HttpConn_) {
+ try {
+ if (!HttpConn_) {
const size_t outputBufferSize = HttpServ()->Options().OutputBufferSize;
if (outputBufferSize) {
HttpConn_.Reset(new THttpServerConn(Socket(), outputBufferSize));
} else {
HttpConn_.Reset(new THttpServerConn(Socket()));
}
-
+
auto maxRequestsPerConnection = HttpServ()->Options().MaxRequestsPerConnection;
HttpConn_->Output()->EnableKeepAlive(HttpServ()->Options().KeepAliveEnabled && (!maxRequestsPerConnection || Conn_->ReceivedRequests < maxRequestsPerConnection));
- HttpConn_->Output()->EnableCompression(HttpServ()->Options().CompressionEnabled);
- }
-
+ HttpConn_->Output()->EnableCompression(HttpServ()->Options().CompressionEnabled);
+ }
+
if (ParsedHeaders.empty()) {
RequestString = Input().FirstLine();
-
- const THttpHeaders& h = Input().Headers();
+
+ const THttpHeaders& h = Input().Headers();
ParsedHeaders.reserve(h.Count());
- for (THttpHeaders::TConstIterator it = h.Begin(); it != h.End(); ++it) {
+ for (THttpHeaders::TConstIterator it = h.Begin(); it != h.End(); ++it) {
ParsedHeaders.emplace_back(it->Name(), it->Value());
- }
- }
-
- if (Reply(ThreadSpecificResource)) {
+ }
+ }
+
+ if (Reply(ThreadSpecificResource)) {
ReleaseConnection();
-
- /*
- * *this will be destroyed...
- */
-
- return;
- }
- } catch (...) {
+
+ /*
+ * *this will be destroyed...
+ */
+
+ return;
+ }
+ } catch (...) {
serverImpl->Cb_->OnException();
-
- throw;
- }
-
+
+ throw;
+ }
+
Y_UNUSED(this_.Release());
-}
-
-void TClientRequest::ProcessFailRequest(int failstate) {
+}
+
+void TClientRequest::ProcessFailRequest(int failstate) {
Output() << "HTTP/1.1 503 Service Unavailable\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 21\r\n"
"\r\n"
"Service Unavailable\r\n";
-
+
TString url;
-
+
if (!strnicmp(RequestString.data(), "GET ", 4)) {
- // Trying to extract url...
+ // Trying to extract url...
const char* str = RequestString.data();
-
- // Skipping spaces before url...
- size_t start = 3;
+
+ // Skipping spaces before url...
+ size_t start = 3;
while (str[start] == ' ') {
- ++start;
- }
-
- if (str[start]) {
- // Traversing url...
- size_t idx = start;
-
- while (str[idx] != ' ' && str[idx]) {
- ++idx;
- }
-
+ ++start;
+ }
+
+ if (str[start]) {
+ // Traversing url...
+ size_t idx = start;
+
+ while (str[idx] != ' ' && str[idx]) {
+ ++idx;
+ }
+
url = RequestString.substr(start, idx - start);
- }
- }
-
- const THttpServer::ICallBack::TFailLogData d = {
- failstate,
- url,
- };
-
- // Handling failure...
- Conn_->HttpServ_->Cb_->OnFailRequestEx(d);
- Output().Flush();
-}
-
+ }
+ }
+
+ const THttpServer::ICallBack::TFailLogData d = {
+ failstate,
+ url,
+ };
+
+ // Handling failure...
+ Conn_->HttpServ_->Cb_->OnFailRequestEx(d);
+ Output().Flush();
+}
+
THttpServer* TClientRequest::HttpServ() const noexcept {
- return Conn_->HttpServ_->Parent_;
-}
-
+ return Conn_->HttpServ_->Parent_;
+}
+
const TSocket& TClientRequest::Socket() const noexcept {
- return Conn_->Socket_;
-}
+ return Conn_->Socket_;
+}
NAddr::IRemoteAddrRef TClientRequest::GetListenerSockAddrRef() const noexcept {
return Conn_->ListenerSockAddrRef_;
@@ -791,8 +791,8 @@ TRequestReplier::~TRequestReplier() {
bool TRequestReplier::Reply(void* threadSpecificResource) {
const TReplyParams params = {
- threadSpecificResource, Input(), Output()};
-
+ threadSpecificResource, Input(), Output()};
+
return DoReply(params);
}
@@ -833,7 +833,7 @@ bool TryToBindAddresses(const THttpServerOptions& options, const std::function<v
return false;
}
- if (callbackOnBoundAddress != nullptr) {
+ if (callbackOnBoundAddress != nullptr) {
(*callbackOnBoundAddress)(socket);
}
}
diff --git a/library/cpp/http/server/http.h b/library/cpp/http/server/http.h
index b292d38f27..1b72215706 100644
--- a/library/cpp/http/server/http.h
+++ b/library/cpp/http/server/http.h
@@ -1,92 +1,92 @@
#pragma once
-#include "conn.h"
-#include "options.h"
-
+#include "conn.h"
+#include "options.h"
+
#include <util/thread/pool.h>
#include <library/cpp/http/io/stream.h>
-#include <util/memory/blob.h>
+#include <util/memory/blob.h>
#include <util/generic/ptr.h>
#include <util/generic/vector.h>
#include <util/system/atomic.h>
-
+
class IThreadFactory;
-class TClientRequest;
-class TClientConnection;
+class TClientRequest;
+class TClientConnection;
-class THttpServer {
+class THttpServer {
friend class TClientRequest;
friend class TClientConnection;
-
+
public:
class ICallBack {
- public:
+ public:
struct TFailLogData {
int failstate;
TString url;
};
-
+
virtual ~ICallBack() {
}
-
+
virtual void OnFailRequest(int /*failstate*/) {
}
-
+
virtual void OnFailRequestEx(const TFailLogData& d) {
OnFailRequest(d.failstate);
}
-
+
virtual void OnException() {
}
-
+
virtual void OnMaxConn() {
}
-
+
virtual TClientRequest* CreateClient() = 0;
-
+
virtual void OnListenStart() {
}
-
+
virtual void OnListenStop() {
}
-
+
virtual void OnWait() {
}
-
- virtual void* CreateThreadSpecificResource() {
+
+ virtual void* CreateThreadSpecificResource() {
return nullptr;
}
-
+
virtual void DestroyThreadSpecificResource(void*) {
}
};
-
+
typedef THttpServerOptions TOptions;
typedef TSimpleSharedPtr<IThreadPool> TMtpQueueRef;
-
+
THttpServer(ICallBack* cb, const TOptions& options = TOptions(), IThreadFactory* pool = nullptr);
THttpServer(ICallBack* cb, TMtpQueueRef mainWorkers, TMtpQueueRef failWorkers, const TOptions& options = TOptions());
virtual ~THttpServer();
-
+
bool Start();
-
+
// shutdown a.s.a.p.
void Stop();
-
+
// graceful shutdown with serving all already open connections
void Shutdown();
-
+
void Wait();
int GetErrorCode();
const char* GetError();
void RestartRequestThreads(ui32 nTh, ui32 maxQS);
const TOptions& Options() const noexcept;
i64 GetClientCount() const;
-
+
class TImpl;
size_t GetRequestQueueSize() const;
size_t GetFailQueueSize() const;
-
+
const IThreadPool& GetRequestQueue() const;
const IThreadPool& GetFailQueue() const;
@@ -102,32 +102,32 @@ private:
/**
* @deprecated Use TRequestReplier instead
*/
-class TClientRequest: public IObjectInQueue {
+class TClientRequest: public IObjectInQueue {
friend class THttpServer::TImpl;
-
+
public:
TClientRequest();
~TClientRequest() override;
-
+
inline THttpInput& Input() noexcept {
return *HttpConn_->Input();
}
-
+
inline THttpOutput& Output() noexcept {
return *HttpConn_->Output();
}
-
+
THttpServer* HttpServ() const noexcept;
const TSocket& Socket() const noexcept;
NAddr::IRemoteAddrRef GetListenerSockAddrRef() const noexcept;
TInstant AcceptMoment() const noexcept;
-
+
bool IsLocal() const;
bool CheckLoopback();
void ProcessFailRequest(int failstate);
-
+
void ReleaseConnection();
-
+
void ResetConnection();
private:
@@ -138,17 +138,17 @@ private:
*/
virtual bool Reply(void* ThreadSpecificResource);
void Process(void* ThreadSpecificResource) override;
-
+
public:
TVector<std::pair<TString, TString>> ParsedHeaders;
TString RequestString;
-
+
private:
THolder<TClientConnection> Conn_;
THolder<THttpServerConn> HttpConn_;
-};
-
-class TRequestReplier: public TClientRequest {
+};
+
+class TRequestReplier: public TClientRequest {
public:
TRequestReplier();
~TRequestReplier() override;
diff --git a/library/cpp/http/server/http_ex.cpp b/library/cpp/http/server/http_ex.cpp
index e07db22bfc..2fa2ccfead 100644
--- a/library/cpp/http/server/http_ex.cpp
+++ b/library/cpp/http/server/http_ex.cpp
@@ -1,32 +1,32 @@
-#include "http_ex.h"
-
-#include <util/generic/buffer.h>
-#include <util/generic/cast.h>
+#include "http_ex.h"
+
+#include <util/generic/buffer.h>
+#include <util/generic/cast.h>
#include <util/stream/null.h>
-
+
bool THttpClientRequestExtension::Parse(char* req, TBaseServerRequestData& rd) {
rd.SetSocket(Socket());
-
+
if (!rd.Parse(req)) {
- Output() << "HTTP/1.1 403 Forbidden\r\n"
- "Content-Type: text/plain\r\n"
- "Content-Length: 39\r\n"
- "\r\n"
- "The server cannot be used as a proxy.\r\n";
-
- return false;
- }
-
- return true;
-}
-
+ Output() << "HTTP/1.1 403 Forbidden\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-Length: 39\r\n"
+ "\r\n"
+ "The server cannot be used as a proxy.\r\n";
+
+ return false;
+ }
+
+ return true;
+}
+
bool THttpClientRequestExtension::ProcessHeaders(TBaseServerRequestData& rd, TBlob& postData) {
- for (const auto& header : ParsedHeaders) {
+ for (const auto& header : ParsedHeaders) {
rd.AddHeader(header.first, header.second);
- }
-
+ }
+
char* s = RequestString.begin();
-
+
enum EMethod {
NotImplemented,
Get,
@@ -39,7 +39,7 @@ bool THttpClientRequestExtension::ProcessHeaders(TBaseServerRequestData& rd, TBl
enum EMethod foundMethod;
char* urlStart;
- if (strnicmp(s, "GET ", 4) == 0) {
+ if (strnicmp(s, "GET ", 4) == 0) {
foundMethod = Get;
urlStart = s + 4;
} else if (strnicmp(s, "POST ", 5) == 0) {
@@ -59,49 +59,49 @@ bool THttpClientRequestExtension::ProcessHeaders(TBaseServerRequestData& rd, TBl
}
switch (foundMethod) {
- case Get:
- case Delete:
- if (!Parse(urlStart, rd)) {
- return false;
- }
- break;
-
- case Post:
- case Put:
+ case Get:
+ case Delete:
+ if (!Parse(urlStart, rd)) {
+ return false;
+ }
+ break;
+
+ case Post:
+ case Put:
case Patch:
- try {
- ui64 contentLength = 0;
- if (Input().HasExpect100Continue()) {
- Output().SendContinue();
- }
-
- if (!Input().ContentEncoded() && Input().GetContentLength(contentLength)) {
+ try {
+ ui64 contentLength = 0;
+ if (Input().HasExpect100Continue()) {
+ Output().SendContinue();
+ }
+
+ if (!Input().ContentEncoded() && Input().GetContentLength(contentLength)) {
if (contentLength > HttpServ()->Options().MaxInputContentLength) {
Output() << "HTTP/1.1 413 Payload Too Large\r\nContent-Length:0\r\n\r\n";
Output().Finish();
return false;
}
- TBuffer buf(SafeIntegerCast<size_t>(contentLength));
- buf.Resize(Input().Load(buf.Data(), (size_t)contentLength));
- postData = TBlob::FromBuffer(buf);
- } else {
- postData = TBlob::FromStream(Input());
- }
- } catch (...) {
- Output() << "HTTP/1.1 400 Bad request\r\n\r\n";
- return false;
+ TBuffer buf(SafeIntegerCast<size_t>(contentLength));
+ buf.Resize(Input().Load(buf.Data(), (size_t)contentLength));
+ postData = TBlob::FromBuffer(buf);
+ } else {
+ postData = TBlob::FromStream(Input());
+ }
+ } catch (...) {
+ Output() << "HTTP/1.1 400 Bad request\r\n\r\n";
+ return false;
}
- if (!Parse(urlStart, rd)) {
- return false;
- }
- break;
-
- case NotImplemented:
- Output() << "HTTP/1.1 501 Not Implemented\r\n\r\n";
- return false;
- }
-
- return true;
-}
+ if (!Parse(urlStart, rd)) {
+ return false;
+ }
+ break;
+
+ case NotImplemented:
+ Output() << "HTTP/1.1 501 Not Implemented\r\n\r\n";
+ return false;
+ }
+
+ return true;
+}
diff --git a/library/cpp/http/server/http_ex.h b/library/cpp/http/server/http_ex.h
index 1ef43ea4fd..39cfbbe66f 100644
--- a/library/cpp/http/server/http_ex.h
+++ b/library/cpp/http/server/http_ex.h
@@ -1,28 +1,28 @@
-#pragma once
-
-#include "http.h"
-
+#pragma once
+
+#include "http.h"
+
#include <library/cpp/http/misc/httpreqdata.h>
-
-class THttpClientRequestExtension: public TClientRequest {
+
+class THttpClientRequestExtension: public TClientRequest {
public:
bool Parse(char* req, TBaseServerRequestData& rd);
bool ProcessHeaders(TBaseServerRequestData& rd, TBlob& postData);
};
-
+
template <class TRequestData>
-class THttpClientRequestExtImpl: public THttpClientRequestExtension {
-protected:
+class THttpClientRequestExtImpl: public THttpClientRequestExtension {
+protected:
bool Parse(char* req) {
return THttpClientRequestExtension::Parse(req, RD);
}
bool ProcessHeaders() {
return THttpClientRequestExtension::ProcessHeaders(RD, Buf);
}
-
+
protected:
TRequestData RD;
- TBlob Buf;
-};
+ TBlob Buf;
+};
using THttpClientRequestEx = THttpClientRequestExtImpl<TServerRequestData>;
diff --git a/library/cpp/http/server/http_ut.cpp b/library/cpp/http/server/http_ut.cpp
index cc62bb988e..ab24207eac 100644
--- a/library/cpp/http/server/http_ut.cpp
+++ b/library/cpp/http/server/http_ut.cpp
@@ -1,58 +1,58 @@
-#include "http.h"
-#include "http_ex.h"
-
+#include "http.h"
+#include "http_ex.h"
+
#include <library/cpp/testing/unittest/registar.h>
#include <library/cpp/testing/unittest/tests_data.h>
-
+
#include <util/generic/cast.h>
#include <util/stream/output.h>
#include <util/stream/zlib.h>
#include <util/system/datetime.h>
#include <util/system/sem.h>
-
+
Y_UNIT_TEST_SUITE(THttpServerTest) {
- class TEchoServer: public THttpServer::ICallBack {
+ class TEchoServer: public THttpServer::ICallBack {
class TRequest: public THttpClientRequestEx {
- public:
- inline TRequest(TEchoServer* parent)
- : Parent_(parent)
- {
- }
-
+ public:
+ inline TRequest(TEchoServer* parent)
+ : Parent_(parent)
+ {
+ }
+
bool Reply(void* /*tsr*/) override {
- if (!ProcessHeaders()) {
+ if (!ProcessHeaders()) {
return true;
- }
-
- Output() << "HTTP/1.1 200 Ok\r\n\r\n";
+ }
+
+ Output() << "HTTP/1.1 200 Ok\r\n\r\n";
if (Buf.Size()) {
Output().Write(Buf.AsCharPtr(), Buf.Size());
- } else {
- Output() << Parent_->Res_;
- }
- Output().Finish();
-
- return true;
- }
-
- private:
+ } else {
+ Output() << Parent_->Res_;
+ }
+ Output().Finish();
+
+ return true;
+ }
+
+ private:
TEchoServer* Parent_ = nullptr;
- };
-
- public:
+ };
+
+ public:
inline TEchoServer(const TString& res)
- : Res_(res)
- {
- }
-
+ : Res_(res)
+ {
+ }
+
TClientRequest* CreateClient() override {
- return new TRequest(this);
- }
-
- private:
+ return new TRequest(this);
+ }
+
+ private:
TString Res_;
- };
-
+ };
+
class TSleepingServer: public THttpServer::ICallBack {
class TReplier: public TRequestReplier {
public:
@@ -269,7 +269,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
TStringStream ss;
ss << (KeepAliveConnection ? "keep-alive " : "") << Type;
if (ContentEncoding.size()) {
- ss << " with encoding=" << ContentEncoding;
+ ss << " with encoding=" << ContentEncoding;
}
return ss.Str();
} else {
@@ -292,7 +292,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
class TFailingMtpQueue: public TSimpleThreadPool {
private:
bool FailOnAdd_ = false;
-
+
public:
void SetFailOnAdd(bool fail = true) {
FailOnAdd_ = fail;
@@ -313,47 +313,47 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
TString TestData(size_t size = 5 * 4096) {
TString res;
-
+
for (size_t i = 0; i < size; ++i) {
- res += (char)i;
- }
+ res += (char)i;
+ }
return res;
}
-
+
Y_UNIT_TEST(TestEchoServer) {
TString res = TestData();
TPortManager pm;
const ui16 port = pm.GetPort();
const bool trueFalse[] = {true, false};
-
- TEchoServer serverImpl(res);
- THttpServer server(&serverImpl, THttpServer::TOptions(port).EnableKeepAlive(true).EnableCompression(true));
-
+
+ TEchoServer serverImpl(res);
+ THttpServer server(&serverImpl, THttpServer::TOptions(port).EnableKeepAlive(true).EnableCompression(true));
+
for (int i = 0; i < 2; ++i) {
UNIT_ASSERT(server.Start());
-
+
TTestRequest r(port);
r.Content = res;
-
- for (bool keepAlive : trueFalse) {
+
+ for (bool keepAlive : trueFalse) {
r.KeepAliveConnection = keepAlive;
-
+
// THttpOutput use chunked stream, else use Content-Length
- for (bool useHttpOutput : trueFalse) {
+ for (bool useHttpOutput : trueFalse) {
r.UseHttpOutput = useHttpOutput;
-
- for (bool enableResponseEncoding : trueFalse) {
+
+ for (bool enableResponseEncoding : trueFalse) {
r.EnableResponseEncoding = enableResponseEncoding;
-
+
const TString reqTypes[] = {"GET", "POST"};
for (const TString& reqType : reqTypes) {
r.Type = reqType;
-
+
const TString encoders[] = {"", "deflate"};
for (const TString& encoder : encoders) {
r.ContentEncoding = encoder;
-
- for (bool expect100Continue : trueFalse) {
+
+ for (bool expect100Continue : trueFalse) {
r.Expect100Continue = expect100Continue;
TString resp = r.Execute();
UNIT_ASSERT_C(resp == res, "diff echo response for request:\n" + r.GetDescription());
@@ -365,12 +365,12 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
}
server.Stop();
- }
- }
+ }
+ }
Y_UNIT_TEST(TestReusePortEnabled) {
if (!IsReusePortAvailable()) {
- return; // skip test
+ return; // skip test
}
TString res = TestData();
TPortManager pm;
@@ -383,7 +383,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
}
for (ui32 testRun = 0; testRun < 3; testRun++) {
- for (auto& server : servers) {
+ for (auto& server : servers) {
// start servers one at a time and check at least one of them is replying
UNIT_ASSERT(server->Start());
@@ -391,7 +391,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
UNIT_ASSERT_C(r.Execute() == res, "diff echo response for request:\n" + r.GetDescription());
}
- for (auto& server : servers) {
+ for (auto& server : servers) {
// ping servers and stop them one at a time
// at the last iteration only one server is still working and then gets stopped as well
@@ -471,7 +471,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
return true;
}
};
-
+
public:
TClientRequest* CreateClient() override {
return new TRequest();
@@ -684,7 +684,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
server.Stop();
};
-#if 0
+#if 0
Y_UNIT_TEST(TestSocketsLeak) {
const bool trueFalse[] = {true, false};
TPortManager portManager;
@@ -709,7 +709,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
server.BusyThread();
for (size_t i = 0; i < 3; ++i) {
- auto func = [&server, port, keepAlive]() {
+ auto func = [&server, port, keepAlive]() {
server.BusyThread();
THolder<TTestRequest> r = MakeHolder<TTestRequest>(port);
r->KeepAliveConnection = keepAlive;
@@ -722,7 +722,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
Sleep(TDuration::MilliSeconds(100));
server.BusyThread(); // we wait while connections are established by the
// system and accepted by the server
- server.Free(3); // we release all connections processing
+ server.Free(3); // we release all connections processing
for (auto&& thread : threads) {
thread->Join();
@@ -735,5 +735,5 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
UNIT_ASSERT_EQUAL_C(server.RepliesCount(), 1, "only one request should have been processed, got " + ToString(server.RepliesCount()));
}
}
-#endif
-}
+#endif
+}
diff --git a/library/cpp/http/server/options.cpp b/library/cpp/http/server/options.cpp
index 05c954384a..391ac68a11 100644
--- a/library/cpp/http/server/options.cpp
+++ b/library/cpp/http/server/options.cpp
@@ -1,12 +1,12 @@
-#include "options.h"
-
+#include "options.h"
+
#include <util/string/cast.h>
-#include <util/digest/numeric.h>
-#include <util/network/ip.h>
-#include <util/network/socket.h>
-#include <util/generic/hash_set.h>
-#include <util/generic/yexception.h>
-
+#include <util/digest/numeric.h>
+#include <util/network/ip.h>
+#include <util/network/socket.h>
+#include <util/generic/hash_set.h>
+#include <util/generic/yexception.h>
+
using TAddr = THttpServerOptions::TAddr;
static inline TString AddrToString(const TAddr& addr) {
@@ -16,28 +16,28 @@ static inline TString AddrToString(const TAddr& addr) {
static inline TNetworkAddress ToNetworkAddr(const TString& address, ui16 port) {
if (address.empty() || address == TStringBuf("*")) {
return TNetworkAddress(port);
- }
-
+ }
+
return TNetworkAddress(address, port);
-}
-
-void THttpServerOptions::BindAddresses(TBindAddresses& ret) const {
+}
+
+void THttpServerOptions::BindAddresses(TBindAddresses& ret) const {
THashSet<TString> check;
-
+
for (auto addr : BindSockaddr) {
if (!addr.Port) {
addr.Port = Port;
- }
-
+ }
+
const TString straddr = AddrToString(addr);
if (check.find(straddr) == check.end()) {
check.insert(straddr);
ret.push_back(ToNetworkAddr(addr.Addr, addr.Port));
- }
- }
-
- if (ret.empty()) {
+ }
+ }
+
+ if (ret.empty()) {
ret.push_back(Host ? TNetworkAddress(Host, Port) : TNetworkAddress(Port));
- }
-}
+ }
+}
diff --git a/library/cpp/http/server/options.h b/library/cpp/http/server/options.h
index 38eda0e5e7..28ce8be0e1 100644
--- a/library/cpp/http/server/options.h
+++ b/library/cpp/http/server/options.h
@@ -1,49 +1,49 @@
#pragma once
-
-#include <util/network/ip.h>
-#include <util/network/init.h>
+
+#include <util/network/ip.h>
+#include <util/network/init.h>
#include <util/network/address.h>
#include <util/generic/size_literals.h>
#include <util/generic/string.h>
-#include <util/generic/vector.h>
+#include <util/generic/vector.h>
#include <util/datetime/base.h>
-
-class THttpServerOptions {
-public:
+
+class THttpServerOptions {
+public:
inline THttpServerOptions(ui16 port = 17000) noexcept
: Port(port)
- {
- }
-
+ {
+ }
+
using TBindAddresses = TVector<TNetworkAddress>;
- void BindAddresses(TBindAddresses& ret) const;
-
+ void BindAddresses(TBindAddresses& ret) const;
+
inline THttpServerOptions& AddBindAddress(const TString& address, ui16 port) {
const TAddr addr = {
- address,
- port,
- };
-
+ address,
+ port,
+ };
+
BindSockaddr.push_back(addr);
return *this;
}
inline THttpServerOptions& AddBindAddress(const TString& address) {
return AddBindAddress(address, 0);
- }
-
+ }
+
inline THttpServerOptions& EnableKeepAlive(bool enable) noexcept {
- KeepAliveEnabled = enable;
-
- return *this;
- }
-
+ KeepAliveEnabled = enable;
+
+ return *this;
+ }
+
inline THttpServerOptions& EnableCompression(bool enable) noexcept {
- CompressionEnabled = enable;
-
- return *this;
- }
-
+ CompressionEnabled = enable;
+
+ return *this;
+ }
+
inline THttpServerOptions& EnableRejectExcessConnections(bool enable) noexcept {
RejectExcessConnections = enable;
@@ -63,11 +63,11 @@ public:
}
inline THttpServerOptions& SetThreads(ui32 threads) noexcept {
- nThreads = threads;
-
- return *this;
- }
-
+ nThreads = threads;
+
+ return *this;
+ }
+
/// Default interface name to bind the server. Used when none of BindAddress are provided.
inline THttpServerOptions& SetHost(const TString& host) noexcept {
Host = host;
@@ -77,35 +77,35 @@ public:
/// Default port to bind the server. Used when none of BindAddress are provided.
inline THttpServerOptions& SetPort(ui16 port) noexcept {
- Port = port;
-
- return *this;
- }
-
+ Port = port;
+
+ return *this;
+ }
+
inline THttpServerOptions& SetMaxConnections(ui32 mc = 0) noexcept {
- MaxConnections = mc;
-
- return *this;
- }
-
+ MaxConnections = mc;
+
+ return *this;
+ }
+
inline THttpServerOptions& SetMaxQueueSize(ui32 mqs = 0) noexcept {
- MaxQueueSize = mqs;
-
- return *this;
- }
+ MaxQueueSize = mqs;
+
+ return *this;
+ }
inline THttpServerOptions& SetClientTimeout(const TDuration& timeout) noexcept {
- ClientTimeout = timeout;
-
- return *this;
- }
+ ClientTimeout = timeout;
+ return *this;
+ }
+
inline THttpServerOptions& SetListenBacklog(int val) noexcept {
- ListenBacklog = val;
-
- return *this;
- }
-
+ ListenBacklog = val;
+
+ return *this;
+ }
+
inline THttpServerOptions& SetOutputBufferSize(size_t val) noexcept {
OutputBufferSize = val;
@@ -149,19 +149,19 @@ public:
bool KeepAliveEnabled = true;
bool CompressionEnabled = false;
bool RejectExcessConnections = false;
- bool ReusePort = false; // set SO_REUSEPORT socket option
+ bool ReusePort = false; // set SO_REUSEPORT socket option
bool ReuseAddress = true; // set SO_REUSEADDR socket option
- TAddrs BindSockaddr;
- ui16 Port = 17000; // The port on which to run the web server
- TString Host; // DNS entry
- const char* ServerName = "YWS/1.0"; // The Web server name to return in HTTP headers
- ui32 nThreads = 0; // Thread count for requests processing
- ui32 MaxQueueSize = 0; // Max allowed request count in queue
+ TAddrs BindSockaddr;
+ ui16 Port = 17000; // The port on which to run the web server
+ TString Host; // DNS entry
+ const char* ServerName = "YWS/1.0"; // The Web server name to return in HTTP headers
+ ui32 nThreads = 0; // Thread count for requests processing
+ ui32 MaxQueueSize = 0; // Max allowed request count in queue
ui32 nFThreads = 1;
ui32 MaxFQueueSize = 0;
ui32 MaxConnections = 100;
int ListenBacklog = SOMAXCONN;
- TDuration ClientTimeout;
+ TDuration ClientTimeout;
size_t OutputBufferSize = 0;
ui64 MaxInputContentLength = sizeof(size_t) <= 4 ? 2_GB : 64_GB;
size_t MaxRequestsPerConnection = 0; // If keep-alive is enabled, request limit before connection is closed
@@ -173,4 +173,4 @@ public:
TString ListenThreadName = "HttpListen";
TString RequestsThreadName = "HttpServer";
TString FailRequestsThreadName = "HttpServer";
-};
+};
diff --git a/library/cpp/http/server/response.cpp b/library/cpp/http/server/response.cpp
index 52d64c91ce..3c7a3e6a93 100644
--- a/library/cpp/http/server/response.cpp
+++ b/library/cpp/http/server/response.cpp
@@ -1,7 +1,7 @@
#include "response.h"
-
+
#include <util/stream/output.h>
-#include <util/stream/mem.h>
+#include <util/stream/mem.h>
#include <util/string/cast.h>
THttpResponse& THttpResponse::AddMultipleHeaders(const THttpHeaders& headers) {
@@ -11,16 +11,16 @@ THttpResponse& THttpResponse::AddMultipleHeaders(const THttpHeaders& headers) {
return *this;
}
-THttpResponse& THttpResponse::SetContentType(const TStringBuf& contentType) {
+THttpResponse& THttpResponse::SetContentType(const TStringBuf& contentType) {
Headers.AddOrReplaceHeader(THttpInputHeader("Content-Type", ToString(contentType)));
-
- return *this;
+
+ return *this;
}
void THttpResponse::OutTo(IOutputStream& os) const {
TVector<IOutputStream::TPart> parts;
const size_t FIRST_LINE_PARTS = 3;
- const size_t HEADERS_PARTS = Headers.Count() * 4;
+ const size_t HEADERS_PARTS = Headers.Count() * 4;
const size_t CONTENT_PARTS = 5;
parts.reserve(FIRST_LINE_PARTS + HEADERS_PARTS + CONTENT_PARTS);
@@ -30,20 +30,20 @@ void THttpResponse::OutTo(IOutputStream& os) const {
parts.push_back(IOutputStream::TPart::CrLf());
// headers
- for (THttpHeaders::TConstIterator i = Headers.Begin(); i != Headers.End(); ++i) {
+ for (THttpHeaders::TConstIterator i = Headers.Begin(); i != Headers.End(); ++i) {
parts.push_back(IOutputStream::TPart(i->Name()));
parts.push_back(IOutputStream::TPart(TStringBuf(": ")));
parts.push_back(IOutputStream::TPart(i->Value()));
parts.push_back(IOutputStream::TPart::CrLf());
}
- char buf[50];
-
+ char buf[50];
+
if (!Content.empty()) {
- TMemoryOutput mo(buf, sizeof(buf));
+ TMemoryOutput mo(buf, sizeof(buf));
mo << Content.size();
-
+
parts.push_back(IOutputStream::TPart(TStringBuf("Content-Length: ")));
parts.push_back(IOutputStream::TPart(buf, mo.Buf() - buf));
parts.push_back(IOutputStream::TPart::CrLf());
@@ -51,15 +51,15 @@ void THttpResponse::OutTo(IOutputStream& os) const {
// content
parts.push_back(IOutputStream::TPart::CrLf());
-
+
if (!Content.empty()) {
parts.push_back(IOutputStream::TPart(Content));
}
os.Write(parts.data(), parts.size());
-}
-
-template <>
+}
+
+template <>
void Out<THttpResponse>(IOutputStream& os, const THttpResponse& resp) {
- resp.OutTo(os);
+ resp.OutTo(os);
}
diff --git a/library/cpp/http/server/response.h b/library/cpp/http/server/response.h
index a75cb85605..7880babac5 100644
--- a/library/cpp/http/server/response.h
+++ b/library/cpp/http/server/response.h
@@ -1,8 +1,8 @@
#pragma once
-
+
#include <library/cpp/http/misc/httpcodes.h>
#include <library/cpp/http/io/stream.h>
-
+
#include <util/generic/strbuf.h>
#include <util/string/cast.h>
@@ -12,23 +12,23 @@ class IOutputStream;
class THttpResponse {
public:
THttpResponse() noexcept
- : Code(HTTP_OK)
- {
- }
-
+ : Code(HTTP_OK)
+ {
+ }
+
explicit THttpResponse(HttpCodes code) noexcept
: Code(code)
{
}
- template <typename ValueType>
+ template <typename ValueType>
THttpResponse& AddHeader(const TString& name, const ValueType& value) {
return AddHeader(THttpInputHeader(name, ToString(value)));
}
THttpResponse& AddHeader(const THttpInputHeader& header) {
Headers.AddHeader(header);
-
+
return *this;
}
@@ -38,8 +38,8 @@ public:
return Headers;
}
- THttpResponse& SetContentType(const TStringBuf& contentType);
-
+ THttpResponse& SetContentType(const TStringBuf& contentType);
+
/**
* @note If @arg content isn't empty its size is automatically added as a
* "Content-Length" header during output to IOutputStream.
@@ -47,7 +47,7 @@ public:
*/
THttpResponse& SetContent(const TString& content) {
Content = content;
-
+
return *this;
}
@@ -61,8 +61,8 @@ public:
* @see IOutputStream& operator << (IOutputStream&, const THttpResponse&)
*/
THttpResponse& SetContent(const TString& content, const TStringBuf& contentType) {
- return SetContent(content).SetContentType(contentType);
- }
+ return SetContent(content).SetContentType(contentType);
+ }
HttpCodes HttpCode() const {
return Code;
diff --git a/library/cpp/http/server/response_ut.cpp b/library/cpp/http/server/response_ut.cpp
index 73e2112ad3..ecd41015d9 100644
--- a/library/cpp/http/server/response_ut.cpp
+++ b/library/cpp/http/server/response_ut.cpp
@@ -2,11 +2,11 @@
#include <library/cpp/testing/unittest/registar.h>
-#include <util/string/cast.h>
-
+#include <util/string/cast.h>
+
Y_UNIT_TEST_SUITE(TestHttpResponse) {
Y_UNIT_TEST(TestCodeOnly) {
- UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse()), "HTTP/1.1 200 Ok\r\n\r\n");
+ UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse()), "HTTP/1.1 200 Ok\r\n\r\n");
UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse(HTTP_NOT_FOUND)), "HTTP/1.1 404 Not found\r\n\r\n");
}
@@ -70,7 +70,7 @@ Y_UNIT_TEST_SUITE(TestHttpResponse) {
"Content-Length: 10\r\n"
"\r\n"
"0123456789";
- UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse().SetContent("0123456789")),
+ UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse().SetContent("0123456789")),
EXPECTED);
}
@@ -80,8 +80,8 @@ Y_UNIT_TEST_SUITE(TestHttpResponse) {
"Content-Length: 28\r\n"
"\r\n"
"<xml><tag value=\"1\" /></xml>";
- THttpResponse resp;
- resp.SetContent("<xml><tag value=\"1\" /></xml>").SetContentType("text/xml");
+ THttpResponse resp;
+ resp.SetContent("<xml><tag value=\"1\" /></xml>").SetContentType("text/xml");
UNIT_ASSERT_STRINGS_EQUAL(ToString(resp), EXPECTED);
}
@@ -90,8 +90,8 @@ Y_UNIT_TEST_SUITE(TestHttpResponse) {
resp.AddHeader(THttpInputHeader("X-Header-1", "ValueOne"))
.AddHeader("X-Header-2", "ValueTwo")
.AddHeader(THttpInputHeader("X-Header-3", "ValueThree"))
- .SetContent("Some stuff")
- .SetContentType("text/plain");
+ .SetContent("Some stuff")
+ .SetContentType("text/plain");
THttpResponse copy = resp;
UNIT_ASSERT_STRINGS_EQUAL(ToString(copy), ToString(resp));
@@ -102,19 +102,19 @@ Y_UNIT_TEST_SUITE(TestHttpResponse) {
resp.AddHeader(THttpInputHeader("X-Header-1", "ValueOne"));
resp.AddHeader(THttpInputHeader("X-Header-2", "ValueTwo"));
resp.AddHeader(THttpInputHeader("X-Header-3", "ValueThree"));
- resp.SetContent("Some stuff").SetContentType("text/plain");
+ resp.SetContent("Some stuff").SetContentType("text/plain");
- THttpResponse copy;
+ THttpResponse copy;
copy = resp;
UNIT_ASSERT_STRINGS_EQUAL(ToString(copy), ToString(resp));
}
Y_UNIT_TEST(TestEmptyContent) {
- UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse().SetContent("")), "HTTP/1.1 200 Ok\r\n\r\n");
+ UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse().SetContent("")), "HTTP/1.1 200 Ok\r\n\r\n");
}
Y_UNIT_TEST(TestReturnReference) {
- THttpResponse resp;
+ THttpResponse resp;
UNIT_ASSERT_EQUAL(&resp, &resp.AddHeader("Header1", 1));
UNIT_ASSERT_EQUAL(&resp, &resp.AddHeader(THttpInputHeader("Header2", "2")));
@@ -124,7 +124,7 @@ Y_UNIT_TEST_SUITE(TestHttpResponse) {
UNIT_ASSERT_EQUAL(&resp, &resp.AddMultipleHeaders(headers));
UNIT_ASSERT_EQUAL(&resp, &resp.SetContent("some stuff"));
- UNIT_ASSERT_EQUAL(&resp, &resp.SetContent("some other stuff").SetContentType("text/plain"));
+ UNIT_ASSERT_EQUAL(&resp, &resp.SetContent("some other stuff").SetContentType("text/plain"));
}
Y_UNIT_TEST(TestSetContentType) {
diff --git a/library/cpp/http/server/ut/ya.make b/library/cpp/http/server/ut/ya.make
index bcb4d4c0b8..17c20a8138 100644
--- a/library/cpp/http/server/ut/ya.make
+++ b/library/cpp/http/server/ut/ya.make
@@ -2,8 +2,8 @@ UNITTEST_FOR(library/cpp/http/server)
OWNER(pg)
-SIZE(MEDIUM)
-
+SIZE(MEDIUM)
+
SRCS(
http_ut.cpp
response_ut.cpp
diff --git a/library/cpp/http/server/ya.make b/library/cpp/http/server/ya.make
index bae6f33306..7b6bd59024 100644
--- a/library/cpp/http/server/ya.make
+++ b/library/cpp/http/server/ya.make
@@ -1,27 +1,27 @@
-LIBRARY()
-
-OWNER(
- pg
+LIBRARY()
+
+OWNER(
+ pg
mvel
kulikov
g:base
g:middle
-)
-
-SRCS(
- conn.cpp
- http.cpp
- http_ex.cpp
- options.cpp
+)
+
+SRCS(
+ conn.cpp
+ http.cpp
+ http_ex.cpp
+ options.cpp
response.cpp
-)
-
+)
+
PEERDIR(
library/cpp/http/misc
library/cpp/http/io
library/cpp/threading/equeue
)
-END()
+END()
RECURSE_FOR_TESTS(ut)