6#include "application.h"
10#include "controller.h"
11#include "dispatcher.h"
18#include <QCoreApplication>
32 auto req =
new DummyRequest(
this);
33 req->body =
new QBuffer(
this);
34 req->body->open(QBuffer::ReadWrite);
37 d_ptr->response =
new Response(
app->defaultHeaders(), req);
38 d_ptr->request =
new Request(req);
39 d_ptr->request->d_ptr->engine = d_ptr->engine;
44 delete d_ptr->request;
45 delete d_ptr->response;
52 return !d->error.isEmpty();
58 if (
error.isEmpty()) {
62 qCCritical(CUTELYST_CORE) <<
error;
117 return d->action->name();
123 return d->action->ns();
141 return d->dispatcher;
147 return QString::fromLatin1(d->action->controller()->metaObject()->className());
153 return d->action->controller();
159 return d->dispatcher->controllers().value(name);
171 return d->app->view(name);
177 return d->app->view(name);
183 d->view = d->app->view(name);
196 return d->stash.value(key);
202 return d->stash.value(key, defaultValue);
208 return d->stash.take(key);
214 return d->stash.remove(key);
220 d->stash.insert(key, value);
226 d->stash.insert(key, QVariant::fromValue(map));
236 const QStringList &args,
241 QUrl uri = d->request->uri();
244 if (path.isEmpty()) {
246 const QString controllerNS = d->action->controller()->ns();
247 if (!controllerNS.isEmpty()) {
248 _path.prepend(controllerNS);
254 if (!args.isEmpty()) {
255 if (_path.compare(u
"/") == 0) {
256 _path += args.join(u
'/');
258 _path = _path + u
'/' + args.join(u
'/');
262 if (!_path.startsWith(u
'/')) {
265 uri.setPath(_path, QUrl::DecodedMode);
268 if (!queryValues.isEmpty()) {
270 if (queryValues.size()) {
271 auto it = queryValues.constEnd();
272 while (it != queryValues.constBegin()) {
274 query.addQueryItem(it.key(), it.value());
284 const QStringList &captures,
285 const QStringList &args,
291 Action *localAction = action;
293 localAction = d->action;
296 QStringList localArgs = args;
297 QStringList localCaptures = captures;
299 Action *expandedAction = d->dispatcher->expandAction(
this, action);
301 while (localCaptures.size() < expandedAction->
numberOfCaptures() && localArgs.size()) {
302 localCaptures.append(localArgs.takeFirst());
305 QStringList localCapturesAux = localCaptures;
306 localCapturesAux.append(localArgs);
307 localArgs = localCapturesAux;
308 localCaptures = QStringList();
311 const QString path = d->dispatcher->uriForAction(localAction, localCaptures);
312 if (path.isEmpty()) {
313 qCWarning(CUTELYST_CORE) <<
"Can not find action for" << localAction << localCaptures;
317 uri =
uriFor(path, localArgs, queryValues);
322 const QStringList &captures,
323 const QStringList &args,
329 Action *action = d->dispatcher->getActionByPath(path);
331 qCWarning(CUTELYST_CORE) <<
"Can not find action for" << path;
335 uri =
uriFor(action, captures, args, queryValues);
349 d->dispatcher->forward(
this, action);
370 if (--d->actionRefCount || !d->stack.isEmpty()) {
374 if (Q_UNLIKELY(d->engineRequest->status & EngineRequest::Finalized)) {
375 qCWarning(CUTELYST_ASYNC) <<
"Trying to async attach to a finalized request! Skipping...";
379 if (d->engineRequest->status & EngineRequest::Async) {
380 while (!d->pendingAsync.isEmpty()) {
381 Component *action = d->pendingAsync.dequeue();
382 const bool ret =
execute(action);
384 if (d->actionRefCount) {
393 Q_EMIT d->app->afterDispatch(
this);
402 return d->dispatcher->forward(
this, action);
408 return d->dispatcher->forward(
this, action);
414 return d->dispatcher->getAction(action, ns);
420 return d->dispatcher->getActions(action, ns);
432 Q_ASSERT_X(code,
"Context::execute",
"trying to execute a null Cutelyst::Component");
434 static int recursion =
435 qEnvironmentVariableIsSet(
"RECURSION") ? qEnvironmentVariableIntValue(
"RECURSION") : 1000;
436 if (d->stack.size() >= recursion) {
437 QString msg = QStringLiteral(
"Deep recursion detected (stack size %1) calling %2, %3")
438 .arg(QString::number(d->stack.size()), code->
reverse(), code->
name());
448 const QString statsInfo = d->statsStartExecute(code);
454 if (d->stats && !statsInfo.isEmpty()) {
455 d->statsFinishExecute(statsInfo);
481 return d->app->config(key, defaultValue);
487 return d->app->config();
491 const char *sourceText,
492 const char *disambiguation,
496 return d->app->translate(d->locale, context, sourceText, disambiguation, n);
503 if (Q_UNLIKELY(d->engineRequest->status & EngineRequest::Finalized)) {
504 qCWarning(CUTELYST_CORE) <<
"Trying to finalize a finalized request! Skipping...";
509 qCDebug(CUTELYST_STATS,
510 "Response Code: %d; Content-Type: %s; Content-Length: %s",
511 d->response->status(),
512 qPrintable(d->response->headers().header(QStringLiteral(
"CONTENT_TYPE"),
513 QStringLiteral(
"unknown"))),
514 qPrintable(d->response->headers().header(QStringLiteral(
"CONTENT_LENGTH"),
515 QStringLiteral(
"unknown"))));
517 const double enlapsed = d->engineRequest->elapsed.nsecsElapsed() / 1000000000.0;
519 if (enlapsed == 0.0) {
520 average = QStringLiteral(
"??");
522 average = QString::number(1.0 / enlapsed,
'f');
523 average.truncate(average.size() - 3);
525 qCInfo(CUTELYST_STATS) << qPrintable(QStringLiteral(
"Request took: %1s (%2/s)\n%3")
526 .arg(QString::number(enlapsed,
'f'),
528 QString::fromLatin1(d->stats->report())));
533 d->engineRequest->finalize();
536QString ContextPrivate::statsStartExecute(
Component *code)
540 if (code->
name().startsWith(u
'_')) {
546 if (qobject_cast<Action *>(code)) {
547 actionName.prepend(u
'/');
550 if (stack.size() > 2) {
551 actionName = u
"-> " + actionName;
553 actionName.rightJustified(actionName.size() + stack.size() - 2, QLatin1Char(
' '));
556 stats->profileStart(actionName);
561void ContextPrivate::statsFinishExecute(
const QString &statsInfo)
563 stats->profileEnd(statsInfo);
569 auto it = unite.constBegin();
570 while (it != unite.constEnd()) {
571 d->stash.insert(it.key(), it.value());
576#include "moc_context.cpp"
577#include "moc_context_p.cpp"
virtual qint8 numberOfCaptures() const noexcept
The Cutelyst Component base class.
QVector< Action * > getActions(const QString &action, const QString &ns={}) const
QStringList errors() const noexcept
Returns a list of errors that were defined.
bool forward(Component *component)
QUrl uriFor(const QString &path=QString(), const QStringList &args=QStringList(), const ParamsMultiMap &queryValues=ParamsMultiMap()) const
QVector< Plugin * > plugins() const
Context(Application *app)
Constructs a new DUMMY Context object that is child of Application This currently is experimental to ...
Action * getAction(const QString &action, const QString &ns={}) const
QString ns() const noexcept
void detach(Action *action=nullptr)
QStack< Component * > stack() const noexcept
QLocale locale() const noexcept
void setState(bool state) noexcept
Sets the state of the current executed action, setting to false will make the dispatcher skip non pro...
Response * res() const noexcept
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
void setStash(const QString &key, const QVariant &value)
QString actionName() const noexcept
void finalize()
finalize the request right away this is automatically called at the end of the actions chain
bool stashRemove(const QString &key)
Action * action() const noexcept
QVariant stashTake(const QString &key)
void attachAsync()
attachAsync
Request * request() const noexcept
void setLocale(const QLocale &locale)
View * customView() const noexcept
bool detached() const noexcept
View * view(const QString &name) const
QUrl uriForAction(const QString &path, const QStringList &captures=QStringList(), const QStringList &args=QStringList(), const ParamsMultiMap &queryValues=ParamsMultiMap()) const
Dispatcher * dispatcher() const noexcept
Application * app() const noexcept
QString controllerName() const
Request * req() const noexcept
Controller * controller() const noexcept
void detachAsync() noexcept
bool execute(Component *code)
bool setCustomView(const QString &name)
Engine * engine() const noexcept
bool state() const noexcept
QVariantMap config() const noexcept
bool error() const noexcept
Returns true if an error was set.
Response * response() const noexcept
Cutelyst View abstract view component
The Cutelyst namespace holds all public Cutelyst API.
QMultiMap< QString, QString > ParamsMultiMap