forked from cutelyst/cutelyst
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathengine.h
223 lines (195 loc) · 6.38 KB
/
engine.h
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
* Copyright (C) 2013-2017 Daniel Nicoletti <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef CUTELYST_ENGINE_H
#define CUTELYST_ENGINE_H
#include <QObject>
#include <QHostAddress>
#include <Cutelyst/cutelyst_global.h>
#include <Cutelyst/Headers>
namespace Cutelyst {
class Application;
class Context;
class EngineRequest;
class EnginePrivate;
class CUTELYST_LIBRARY Engine : public QObject
{
Q_OBJECT
public:
/**
* Constructs an Engine object, where \p app is the application that might be
* used to create new instances if \p workerCore is greater than 1, \p opts
* is the options loaded by the engine subclass.
*/
explicit Engine(Application *app, int workerCore, const QVariantMap &opts);
virtual ~Engine();
/**
* Returns the application associated with this engine.
*/
Application *app() const;
/**
* Reimplement this to get the workerId of the engine subclass, this is
* the same as processes id.
*/
virtual int workerId() const = 0;
/**
* Returns the worker core set when constructing the engine
*/
int workerCore() const;
/**
* Returns true if this is the Zero worker,
* ie if workerId() == 0 and workerCore() == 0
*
* \note the value returned from this function is
* only valid when postFork() is issued.
*/
inline bool isZeroWorker() const;
/**
* Engine options
*/
QVariantMap opts() const;
/**
* @brief user configuration for the application
* @param entity the entity you are interested in
* @return the configuration settings
*/
QVariantMap config(const QString &entity) const;
/**
* Sets the configuration to be used by Application
*/
void setConfig(const QVariantMap &config);
/**
* Returns a QVariantMap with the INI parsed from \p filename.
*/
static QVariantMap loadIniConfig(const QString &filename);
/**
* Returns a QVariantMap with the JSON parsed from \p filename.
*/
static QVariantMap loadJsonConfig(const QString &filename);
/**
* @return current micro seconds time to be used for stats, the default implementation returns
* QDateTime::currentMSecsSinceEpoch() * 1000, to become micro seconds, so if the engine
* supports a more precise value it can reimplement this method.
*/
virtual quint64 time();
/**
* Process the EngineRequest \p req, the caller
* must delete the context when the request is finished.
*
* This method allows for engines to keep the Context alive
* while processing websocket data.
*/
void processRequest(EngineRequest *request);
/**
* Returns the header key in camel case form
*/
static inline QString camelCaseHeader(const QString &headerKey) {
// The RFC 2616 and 7230 states keys are not case
// case sensitive, however several tools fail
// if the headers are not on camel case form.
QString key = headerKey;
bool lastWasLetter = false;
for (int i = 0 ; i < key.size() ; ++i) {
QCharRef c = key[i];
if (c == QLatin1Char('_')) {
c = QLatin1Char('-');
lastWasLetter = false;
} else if (lastWasLetter) {
c = c.toLower();
} else if (c.isLetter()) {
lastWasLetter = true;
}
}
return key;
}
/**
* Convert Header key to camel case
*/
static inline void camelCaseByteArrayHeader(QByteArray &key) {
// The RFC 2616 and 7230 states keys are not case
// case sensitive, however several tools fail
// if the headers are not on camel case form.
bool lastWasLetter = false;
for (int i = 0 ; i < key.size() ; ++i) {
QByteRef c = key[i];
if (c == '_') {
c = '-';
lastWasLetter = false;
} else if (lastWasLetter) {
c = QChar::toLower(c);
} else if (QChar::isLetter(c)) {
lastWasLetter = true;
}
}
}
/**
* Returns the HTTP status message for the given \p status.
*/
static const char *httpStatusMessage(quint16 status, int *len = nullptr);
Q_SIGNALS:
/**
* Process the EngineRequest \p req Async, the caller
* must delete the context when the request is finished.
*
* This method allows for engines to keep the Context alive
* while processing websocket data.
*/
void processRequestAsync(EngineRequest *request);
protected:
/**
* @brief initApplication
*
* This method inits the application and
* calls init on the engine. It must be called on the
* engine's thread
*
* @return true if succeded
*/
bool initApplication();
/**
* @brief postForkApplication
*
* Subclasses must be call after the engine forks by the worker thread,
* if no forking is involved it must be called once the worker thread has
* started.
*
* For convenience QThread::currentThread() has it's object name set with
* the worker core number.
*
* @return true if the engine should use this process
*/
bool postForkApplication();
/**
* This is the HTTP default response headers that each request gets
*/
Headers &defaultHeaders();
EnginePrivate *d_ptr;
private:
Q_DECLARE_PRIVATE(Engine)
friend class Application;
friend class Response;
/**
* @brief init the engine
* @return true if succeeded
*/
virtual bool init() = 0;
};
inline bool Engine::isZeroWorker() const {
return !workerId() && !workerCore();
}
}
#endif // CUTELYST_ENGINE_H