18 #include "context_p.h" 24 #include "dispatcher.h" 25 #include "controller.h" 26 #include "application.h" 28 #include "enginerequest.h" 34 #include <QCoreApplication> 44 d_ptr(new ContextPrivate(app, app->engine(), app->dispatcher(), app->plugins()))
46 auto req =
new DummyRequest(
this);
48 req->
body->open(QBuffer::ReadWrite);
53 d_ptr->request->d_ptr->engine = d_ptr->engine;
58 delete d_ptr->request;
59 delete d_ptr->response;
66 return !d->error.isEmpty();
72 if (
error.isEmpty()) {
76 qCCritical(CUTELYST_CORE) <<
error;
131 return d->action->name();
137 return d->action->ns();
155 return d->dispatcher;
161 return QString::fromLatin1(d->action->controller()->metaObject()->className());
167 return d->action->controller();
173 return d->dispatcher->controllers().value(name);
185 return d->app->view(name);
191 d->view = d->app->view(name);
204 return d->stash.value(key);
210 return d->stash.value(key, defaultValue);
216 return d->stash.take(key);
222 return d->stash.remove(key);
228 d->stash.insert(key, value);
234 d->stash.insert(key, QVariant::fromValue(map));
247 QUrl uri = d->request->uri();
250 if (path.isEmpty()) {
252 const QString controllerNS = d->action->controller()->ns();
253 if (!controllerNS.isEmpty()) {
254 _path.prepend(controllerNS);
260 if (!args.isEmpty()) {
271 uri.setPath(_path, QUrl::DecodedMode);
276 if (queryValues.
size()) {
280 query.addQueryItem(it.key(), it.value());
296 localAction = d->action;
302 Action *expandedAction = d->dispatcher->expandAction(
this,
action);
305 && localArgs.size()) {
306 localCaptures.append(localArgs.takeFirst());
310 localCapturesAux.append(localArgs);
311 localArgs = localCapturesAux;
315 const QString path = d->dispatcher->uriForAction(localAction, localCaptures);
316 if (path.isEmpty()) {
317 qCWarning(CUTELYST_CORE) <<
"Can not find action for" << localAction << localCaptures;
321 uri =
uriFor(path, localArgs, queryValues);
332 qCWarning(CUTELYST_CORE) <<
"Can not find action for" << path;
350 d->dispatcher->forward(
this,
action);
359 d->asyncDetached =
true;
360 d->engineRequest->status |= EngineRequest::Async;
366 bool &asyncDetached = d->asyncDetached;
367 asyncDetached =
false;
369 while (!d->pendingAsync.isEmpty()) {
373 }
else if (asyncDetached) {
378 if (d->engineRequest->status & EngineRequest::Async) {
379 Q_EMIT d->app->afterDispatch(
this);
388 return d->dispatcher->forward(
this,
action);
394 return d->dispatcher->forward(
this,
action);
400 return d->dispatcher->getAction(
action,
ns);
406 return d->dispatcher->getActions(
action,
ns);
418 Q_ASSERT_X(code,
"Context::execute",
"trying to execute a null Cutelyst::Component");
420 static int recursion = qEnvironmentVariableIsSet(
"RECURSION") ? qEnvironmentVariableIntValue(
"RECURSION") : 1000;
421 if (d->stack.size() >= recursion) {
422 QString msg = QStringLiteral(
"Deep recursion detected (stack size %1) calling %2, %3")
423 .arg(QString::number(d->stack.size()), code->
reverse(), code->
name());
433 const QString statsInfo = d->statsStartExecute(code);
437 if (!statsInfo.isEmpty()) {
438 d->statsFinishExecute(statsInfo);
464 return d->app->config(key, defaultValue);
470 return d->app->config();
473 QString
Context::translate(
const char *context,
const char *sourceText,
const char *disambiguation,
int n)
const 476 return d->app->translate(d->locale, context, sourceText, disambiguation, n);
497 void Context::finalize()
502 qCDebug(CUTELYST_STATS,
"Response Code: %d; Content-Type: %s; Content-Length: %s",
503 d->response->status(),
504 qPrintable(d->response->headers().header(QStringLiteral(
"CONTENT_TYPE"), QStringLiteral(
"unknown"))),
505 qPrintable(d->response->headers().header(QStringLiteral(
"CONTENT_LENGTH"), QStringLiteral(
"unknown"))));
507 const double enlapsed = d->engineRequest->elapsed.nsecsElapsed() / 1000000000.0;
509 if (enlapsed == 0.0) {
510 average = QStringLiteral(
"??");
512 average = QString::number(1.0 / enlapsed,
'f');
513 average.truncate(average.size() - 3);
515 qCInfo(CUTELYST_STATS) << qPrintable(QStringLiteral(
"Request took: %1s (%2/s)\n%3")
516 .arg(QString::number(enlapsed,
'f'),
518 QString::fromLatin1(d->stats->report())));
523 d->engineRequest->finalize();
539 QString ContextPrivate::statsStartExecute(
Component *code)
549 if (qobject_cast<Action *>(code)) {
553 if (stack.size() > 2) {
555 actionName = actionName.rightJustified(actionName.size() + stack.size() - 2,
QLatin1Char(
' '));
558 stats->profileStart(actionName);
563 void ContextPrivate::statsFinishExecute(
const QString &statsInfo)
565 stats->profileEnd(statsInfo);
568 #include "moc_context.cpp" 569 #include "moc_context_p.cpp" Context(Application *app)
Constructs a new DUMMY Context object that is child of Application This currently is experimental to ...
Application * app() const
QString actionName() const
Request * request() const
virtual qint8 numberOfCaptures() const
bool setCustomView(const QString &name)
QMap::const_iterator constBegin() const const
Dispatcher * dispatcher() const
void setStash(const QString &key, const QVariant &value)
void detach(Action *action=nullptr)
QString join(const QString &sep) const const
QUrl uriFor(const QString &path=QString(), const QStringList &args=QStringList(), const ParamsMultiMap &queryValues=ParamsMultiMap()) const
The Cutelyst Component base class.
This class represents a Cutelyst Action.
QVector< Action * > getActions(const QString &action, const QString &ns=QString()) const
QUrl uriForAction(const QString &path, const QStringList &captures=QStringList(), const QStringList &args=QStringList(), const ParamsMultiMap &queryValues=ParamsMultiMap()) const
QStack< Component * > stack() const
Headers & defaultHeaders()
bool forward(Component *component)
Cutelyst Controller base class
void next(bool force=false)
This method is deprecated and no longer works, creating local event loops leads to crashes.
QStringList errors() const
Returns a list of errors that were defined.
QMap::const_iterator constEnd() const const
Response * response() const
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
View * view(const QString &name=QString()) const
QVariantMap config() const
The Cutelyst namespace holds all public Cutelyst API.
Action * getAction(const QString &action, const QString &ns=QString()) const
bool execute(Component *code)
void setState(bool state)
Sets the state of the current executed action, setting to false will make the dispatcher skip non pro...
QVector< Plugin * > plugins() const
void setLocale(const QLocale &locale)
QVariant stashTake(const QString &key)
Cutelyst View abstract view component
Controller * controller() const
View * customView() const
The Cutelyst Application.
bool stashRemove(const QString &key)
bool isEmpty() const const
Q_DECL_DEPRECATED bool wait(uint count=1)
This method is deprecated and no longer works, creating local event loops leads to crashes.
bool error() const
Returns true if an error was set.
QString controllerName() const
void attachAsync()
attachAsync