1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#pragma once
#include <library/cpp/coroutine/engine/impl.h>
#include <library/cpp/coroutine/listener/listen.h>
#include <library/cpp/http/fetch/httpheader.h>
#include <library/cpp/http/server/http.h>
#include <library/cpp/logger/all.h>
#include <util/network/ip.h>
#include <library/cpp/cgiparam/cgiparam.h>
#include <functional>
struct TMonitor;
namespace NMonitoring {
struct IHttpRequest {
virtual ~IHttpRequest() {
}
virtual const char* GetURI() const = 0;
virtual const char* GetPath() const = 0;
virtual const TCgiParameters& GetParams() const = 0;
virtual const TCgiParameters& GetPostParams() const = 0;
virtual TStringBuf GetPostContent() const = 0;
virtual HTTP_METHOD GetMethod() const = 0;
virtual const THttpHeaders& GetHeaders() const = 0;
virtual TString GetRemoteAddr() const = 0;
};
// first param - output stream to write result to
// second param - URL of request
typedef std::function<void(IOutputStream&, const IHttpRequest&)> THandler;
class TCoHttpServer: private TContListener::ICallBack {
public:
// initialize and schedule coroutines for execution
TCoHttpServer(TContExecutor& executor, const TString& bindAddr, TIpPort port, THandler handler);
void Start();
void Stop();
// this function implements THandler interface
// by forwarding it to the httpserver
// @note this call may be blocking; don't use inside coroutines
// @throws may throw in case of connection error, etc
void ProcessRequest(IOutputStream&, const IHttpRequest&);
private:
class TConnection;
// ICallBack implementation
void OnAcceptFull(const TAcceptFull& a) override;
void OnError() override;
private:
TContExecutor& Executor;
TContListener Listener;
THandler Handler;
TString BindAddr;
TIpPort Port;
};
class TMtHttpServer: public THttpServer, private THttpServer::ICallBack {
public:
TMtHttpServer(const TOptions& options, THandler handler, IThreadFactory* pool = nullptr);
TMtHttpServer(const TOptions& options, THandler handler, TSimpleSharedPtr<IThreadPool> pool);
/**
* This will cause the server start to accept incoming connections.
*
* @return true if the port binding was successfull,
* false otherwise.
*/
bool Start();
/**
* Same as Start() member-function, but will throw TSystemError if
* there were some errors.
*/
void StartOrThrow();
/**
* Stops the server from accepting new connections.
*/
void Stop();
private:
class TConnection;
TClientRequest* CreateClient() override;
THandler Handler;
};
// this class implements hybrid coroutine and threaded approach
// requests for main page which holds counters and simple tables are served in a thread
// requests for other pages which include access with inter-thread synchonization
// will be served in a coroutine context
class TMonService {
public:
TMonService(TContExecutor& executor, TIpPort internalPort, TIpPort externalPort,
THandler coHandler, THandler mtHandler);
void Start();
void Stop();
protected:
void DispatchRequest(IOutputStream& out, const IHttpRequest&);
private:
TCoHttpServer CoServer;
TMtHttpServer MtServer;
THandler MtHandler;
};
}
|