cutelyst  3.7.0
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
engine.cpp
1 /*
2  * SPDX-FileCopyrightText: (C) 2013-2022 Daniel Nicoletti <dantti12@gmail.com>
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 #include "engine_p.h"
6 
7 #include "context_p.h"
8 
9 #include "common.h"
10 #include "request_p.h"
11 #include "application.h"
12 #include "response_p.h"
13 #include "context_p.h"
14 
15 #include <QUrl>
16 #include <QSettings>
17 #include <QDir>
18 #include <QThread>
19 #include <QByteArray>
20 #include <QJsonDocument>
21 
22 using namespace Cutelyst;
23 
44 Engine::Engine(Cutelyst::Application *app, int workerCore, const QVariantMap &opts)
45  : d_ptr(new EnginePrivate)
46 {
47  Q_D(Engine);
48 
49  connect(this, &Engine::processRequestAsync, this, &Engine::processRequest, Qt::QueuedConnection);
50 
51  d->opts = opts;
52  d->workerCore = workerCore;
53  d->app = app;
54 }
55 
56 Engine::~Engine()
57 {
58  delete d_ptr;
59 }
60 
66 {
67  Q_D(const Engine);
68  Q_ASSERT(d->app);
69  return d->app;
70 }
71 
91 int Engine::workerCore() const
92 {
93  Q_D(const Engine);
94  return d->workerCore;
95 }
96 
98 {
99  Q_D(Engine);
100 
101  if (thread() != QThread::currentThread()) {
102  qCCritical(CUTELYST_ENGINE) << "Cannot init application on a different thread";
103  return false;
104  }
105 
106  if (!d->app->setup(this)) {
107  qCCritical(CUTELYST_ENGINE) << "Failed to setup application";
108  return false;
109  }
110 
111  return true;
112 }
113 
115 {
116  Q_D(Engine);
117 
118  if (!d->app) {
119  qCCritical(CUTELYST_ENGINE) << "Failed to postForkApplication on a null application";
120  return false;
121  }
122 
123  QThread::currentThread()->setObjectName(QString::number(d->workerCore));
124 
125  return d->app->enginePostFork();
126 }
127 
128 quint64 Engine::time()
129 {
130  return quint64(QDateTime::currentMSecsSinceEpoch() * 1000);
131 }
132 
133 const char *Engine::httpStatusMessage(quint16 status, int *len)
134 {
135  const char *ret;
136  switch (status) {
137  case Response::OK:
138  ret = "HTTP/1.1 200 OK";
139  break;
140  case Response::Found:
141  ret = "HTTP/1.1 302 Found";
142  break;
143  case Response::NotFound:
144  ret = "HTTP/1.1 404 Not Found";
145  break;
146  case Response::InternalServerError:
147  ret = "HTTP/1.1 500 Internal Server Error";
148  break;
149  case Response::MovedPermanently:
150  ret = "HTTP/1.1 301 Moved Permanently";
151  break;
152  case Response::NotModified:
153  ret = "HTTP/1.1 304 Not Modified";
154  break;
155  case Response::SeeOther:
156  ret = "HTTP/1.1 303 See Other";
157  break;
158  case Response::Forbidden:
159  ret = "HTTP/1.1 403 Forbidden";
160  break;
161  case Response::TemporaryRedirect:
162  ret = "HTTP/1.1 307 Temporary Redirect";
163  break;
164  case Response::Unauthorized:
165  ret = "HTTP/1.1 401 Unauthorized";
166  break;
167  case Response::BadRequest:
168  ret = "HTTP/1.1 400 Bad Request";
169  break;
170  case Response::MethodNotAllowed:
171  ret = "HTTP/1.1 405 Method Not Allowed";
172  break;
173  case Response::RequestTimeout:
174  ret = "HTTP/1.1 408 Request Timeout";
175  break;
176  case Response::Continue:
177  ret = "HTTP/1.1 100 Continue";
178  break;
179  case Response::SwitchingProtocols:
180  ret = "HTTP/1.1 101 Switching Protocols";
181  break;
182  case Response::Created:
183  ret = "HTTP/1.1 201 Created";
184  break;
185  case Response::Accepted:
186  ret = "HTTP/1.1 202 Accepted";
187  break;
188  case Response::NonAuthoritativeInformation:
189  ret = "HTTP/1.1 203 Non-Authoritative Information";
190  break;
191  case Response::NoContent:
192  ret = "HTTP/1.1 204 No Content";
193  break;
194  case Response::ResetContent:
195  ret = "HTTP/1.1 205 Reset Content";
196  break;
197  case Response::PartialContent:
198  ret = "HTTP/1.1 206 Partial Content";
199  break;
200  case Response::MultipleChoices:
201  ret = "HTTP/1.1 300 Multiple Choices";
202  break;
203  case Response::UseProxy:
204  ret = "HTTP/1.1 305 Use Proxy";
205  break;
206  case Response::PaymentRequired:
207  ret = "HTTP/1.1 402 Payment Required";
208  break;
209  case Response::NotAcceptable:
210  ret = "HTTP/1.1 406 Not Acceptable";
211  break;
212  case Response::ProxyAuthenticationRequired:
213  ret = "HTTP/1.1 407 Proxy Authentication Required";
214  break;
215  case Response::Conflict:
216  ret = "HTTP/1.1 409 Conflict";
217  break;
218  case Response::Gone:
219  ret = "HTTP/1.1 410 Gone";
220  break;
221  case Response::LengthRequired:
222  ret = "HTTP/1.1 411 Length Required";
223  break;
224  case Response::PreconditionFailed:
225  ret = "HTTP/1.1 412 Precondition Failed";
226  break;
227  case Response::RequestEntityTooLarge:
228  ret = "HTTP/1.1 413 Request Entity Too Large";
229  break;
230  case Response::RequestURITooLong:
231  ret = "HTTP/1.1 414 Request-URI Too Long";
232  break;
233  case Response::UnsupportedMediaType:
234  ret = "HTTP/1.1 415 Unsupported Media Type";
235  break;
236  case Response::RequestedRangeNotSatisfiable:
237  ret = "HTTP/1.1 416 Requested Range Not Satisfiable";
238  break;
239  case Response::ExpectationFailed:
240  ret = "HTTP/1.1 417 Expectation Failed";
241  break;
242  case Response::NotImplemented:
243  ret = "HTTP/1.1 501 Not Implemented";
244  break;
245  case Response::BadGateway:
246  ret = "HTTP/1.1 502 Bad Gateway";
247  break;
248  case Response::ServiceUnavailable:
249  ret = "HTTP/1.1 503 Service Unavailable";
250  break;
251  case Response::MultiStatus:
252  ret = "HTTP/1.1 207 Multi-Status";
253  break;
254  case Response::GatewayTimeout:
255  ret = "HTTP/1.1 504 Gateway Timeout";
256  break;
257  case Response::HTTPVersionNotSupported:
258  ret = "HTTP/1.1 505 HTTP Version Not Supported";
259  break;
260  case Response::BandwidthLimitExceeded:
261  ret = "HTTP/1.1 509 Bandwidth Limit Exceeded";
262  break;
263  default:
264  ret = QByteArrayLiteral("HTTP/1.1 ").append(QByteArray::number(status)).constData();
265  break;
266  }
267 
268  if (len) {
269  *len = int(strlen(ret));
270  }
271  return ret;
272 }
273 
275 {
276  Q_D(Engine);
277  return d->app->defaultHeaders();
278 }
279 
281 {
282  Q_D(Engine);
283  d->app->handleRequest(request);
284 }
285 
286 QVariantMap Engine::opts() const
287 {
288  Q_D(const Engine);
289  return d->opts;
290 }
291 
292 QVariantMap Engine::config(const QString &entity) const
293 {
294  Q_D(const Engine);
295  return d->config.value(entity).toMap();
296 }
297 
298 void Engine::setConfig(const QVariantMap &config)
299 {
300  Q_D(Engine);
301  d->config = config;
302 }
303 
304 QVariantMap Engine::loadIniConfig(const QString &filename)
305 {
306  QVariantMap ret;
307  QSettings settings(filename, QSettings::IniFormat);
308  if (settings.status() != QSettings::NoError) {
309  qCWarning(CUTELYST_ENGINE) << "Failed to load INI file:" << settings.status();
310  return ret;
311  }
312 
313  const auto groups = settings.childGroups();
314  for (const QString &group : groups) {
315  QVariantMap configGroup;
316  settings.beginGroup(group);
317  const auto child = settings.childKeys();
318  for (const QString &key : child) {
319  configGroup.insert(key, settings.value(key));
320  }
321  settings.endGroup();
322  ret.insert(group, configGroup);
323  }
324 
325  return ret;
326 }
327 
328 QVariantMap Engine::loadJsonConfig(const QString &filename)
329 {
330  QVariantMap ret;
331  QFile file(filename);
332  if (!file.open(QIODevice::ReadOnly)) {
333  return ret;
334  }
335  QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
336 
337  ret = doc.toVariant().toMap();
338 
339  return ret;
340 }
341 
342 #include "moc_engine.cpp"
The Cutelyst Application.
Definition: application.h:43
The Cutelyst Engine.
Definition: engine.h:21
static QVariantMap loadJsonConfig(const QString &filename)
Definition: engine.cpp:328
Engine(Application *app, int workerCore, const QVariantMap &opts)
Definition: engine.cpp:44
bool initApplication()
initApplication
Definition: engine.cpp:97
int workerCore() const
Each worker process migth have a number of worker cores (threads), a single process with two worker t...
Definition: engine.cpp:91
bool postForkApplication()
postForkApplication
Definition: engine.cpp:114
void setConfig(const QVariantMap &config)
Definition: engine.cpp:298
void processRequestAsync(Cutelyst::EngineRequest *request)
static const char * httpStatusMessage(quint16 status, int *len=nullptr)
Definition: engine.cpp:133
void processRequest(EngineRequest *request)
Definition: engine.cpp:280
QVariantMap opts() const
Definition: engine.cpp:286
QVariantMap config(const QString &entity) const
user configuration for the application
Definition: engine.cpp:292
Application * app() const
application
Definition: engine.cpp:65
virtual quint64 time()
Definition: engine.cpp:128
Headers & defaultHeaders()
Definition: engine.cpp:274
static QVariantMap loadIniConfig(const QString &filename)
Definition: engine.cpp:304
The Cutelyst namespace holds all public Cutelyst API.
Definition: Mainpage.dox:8