6 #include "application.h" 10 #include "controller.h" 11 #include "dispatcher.h" 18 #include <QCoreApplication> 31 : d_ptr(new ContextPrivate(app, app->engine(), app->dispatcher(), app->plugins()))
33 auto dummyRequest =
new DummyRequest(
this);
34 dummyRequest->body =
new QBuffer(
this);
36 dummyRequest->context =
this;
39 d_ptr->request =
new Request(dummyRequest);
40 d_ptr->request->d_ptr->engine = d_ptr->engine;
46 delete d_ptr->request;
47 delete d_ptr->response;
54 return !d->error.isEmpty();
60 if (
error.isEmpty()) {
64 qCCritical(CUTELYST_CORE) <<
error;
119 return d->action->name();
125 return d->action->ns();
143 return d->dispatcher;
149 return d->action->className();
155 return d->action->controller();
161 return d->dispatcher->controller(name);
173 return d->app->view(name);
179 d->view = d->app->view(name);
192 return d->stash.value(key);
198 return d->stash.value(key, defaultValue);
204 return d->stash.take(key);
210 return d->stash.remove(key);
216 d->stash.insert(key, value);
237 QUrl uri = d->request->uri();
242 const QString controllerNS = d->action->controller()->ns();
251 if (_path.
compare(u
"/") == 0) {
252 _path += args.
join(u
'/');
254 _path = _path + u
'/' + args.
join(u
'/');
292 const Action *expandedAction = d->dispatcher->expandAction(
this,
action);
299 localCapturesAux.
append(localArgs);
300 localArgs = localCapturesAux;
304 const QString path = d->dispatcher->uriForAction(
action, localCaptures);
306 qCWarning(CUTELYST_CORE) <<
"Can not find action for" <<
action << localCaptures;
310 uri =
uriFor(path, localArgs, queryValues);
322 Action *actionFound = d->dispatcher->getActionByPath(path);
324 qCWarning(CUTELYST_CORE) <<
"Can not find action for" << path;
328 uri =
uriFor(actionFound, captures, args, queryValues);
342 d->dispatcher->forward(
this,
action);
363 if (--d->actionRefCount || !d->stack.isEmpty()) {
367 if (Q_UNLIKELY((d->engineRequest->status & EngineRequest::Finalized) &&
368 !(d->engineRequest->status & EngineRequest::Async))) {
369 qCWarning(CUTELYST_ASYNC) <<
"Trying to async attach to a finalized request! Skipping...";
373 if ((d->engineRequest->status & EngineRequest::Async) &&
374 !(d->engineRequest->status & EngineRequest::Finalized)) {
375 while (!d->pendingAsync.isEmpty()) {
376 Component *pendingAction = d->pendingAsync.dequeue();
377 const bool ret =
execute(pendingAction);
379 if (d->actionRefCount) {
388 Q_EMIT d->app->afterDispatch(
this);
397 return d->dispatcher->forward(
this,
action);
403 return d->dispatcher->forward(
this,
action);
409 return d->dispatcher->getAction(
action,
ns);
415 return d->dispatcher->getActions(
action,
ns);
427 Q_ASSERT_X(code,
"Context::execute",
"trying to execute a null Cutelyst::Component");
429 static int recursion =
430 qEnvironmentVariableIsSet(
"RECURSION") ? qEnvironmentVariableIntValue(
"RECURSION") : 1000;
431 if (d->stack.size() >= recursion) {
432 QString msg = u
"Deep recursion detected (stack size %1) calling %2, %3"_s.
arg(
443 const QString statsInfo = d->statsStartExecute(code);
449 if (d->stats && !statsInfo.
isEmpty()) {
450 d->statsFinishExecute(statsInfo);
476 return d->app->config(key, defaultValue);
482 return d->app->config();
486 const char *sourceText,
487 const char *disambiguation,
491 return d->app->translate(d->locale, context, sourceText, disambiguation, n);
498 if (Q_UNLIKELY(d->engineRequest->status & EngineRequest::Finalized)) {
499 qCWarning(CUTELYST_CORE) <<
"Trying to finalize a finalized request! Skipping...";
504 qCDebug(CUTELYST_STATS,
505 "Response Code: %d; Content-Type: %s; Content-Length: %s",
506 d->response->status(),
507 d->response->headers().header(
"Content-Type",
"unknown"_ba).constData(),
508 d->response->headers()
512 const std::chrono::duration<double> duration =
513 std::chrono::steady_clock::now() - d->engineRequest->startOfRequest;
516 if (duration.count() == 0.0) {
522 qCInfo(CUTELYST_STATS) << qPrintable(
523 u
"Request took: %1s (%2/s)\n%3"_s.arg(
QString::number(duration.count(),
'f'),
530 d->engineRequest->finalize();
543 if (qobject_cast<Action *>(code)) {
547 if (stack.size() > 2) {
548 actionName = u
"-> " + actionName;
549 actionName = actionName.
rightJustified(actionName.size() + stack.size() - 2, u
' ');
552 stats->profileStart(actionName);
557 void ContextPrivate::statsFinishExecute(
const QString &statsInfo)
559 stats->profileEnd(statsInfo);
566 d->stash.insert(unite);
569 #include "moc_context.cpp" 570 #include "moc_context_p.cpp" Context(Application *app)
void truncate(qsizetype position)
bool state() const noexcept
QString controllerName() const noexcept
bool error() const noexcept
virtual qint8 numberOfCaptures() const
const_iterator constEnd() const const
QString & prepend(QChar ch)
QVariant fromValue(T &&value)
Response * res() const noexcept
bool isEmpty() const const
qsizetype size() const const
Action * getAction(QStringView action, QStringView ns={}) const
void setStash(const QString &key, const QVariant &value)
QString ns() const noexcept
void detach(Action *action=nullptr)
QUrl uriFor(const QString &path={}, const QStringList &args={}, const ParamsMultiMap &queryValues={}) const
QString join(QChar separator) const const
Request * req() const noexcept
QString reverse() const noexcept
void appendError(const QString &error)
The Cutelyst Component base class.
QString actionName() const noexcept
qsizetype size() const const
This class represents a Cutelyst Action.
Headers & defaultHeaders() noexcept
void setPath(const QString &path, ParsingMode mode)
const_iterator constBegin() const const
void addQueryItem(const QString &key, const QString &value)
bool forward(Component *component)
QString number(double n, char format, int precision)
Cutelyst Controller base class.
QByteArray number(double n, char format, int precision)
QLocale defaultLocale() const noexcept
QString rightJustified(qsizetype width, QChar fill, bool truncate) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
Action * action() const noexcept
bool detached() const noexcept
bool isEmpty() const const
bool isEmpty() const const
Request * request() const noexcept
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
QVariantMap config() const noexcept
QString name() const noexcept
The Cutelyst namespace holds all public Cutelyst API.
void detachAsync() noexcept
QLocale locale() const noexcept
bool execute(Component *code)
QUrl uriForAction(QStringView path, const QStringList &captures={}, const QStringList &args={}, const ParamsMultiMap &queryValues={}) const
QVector< Plugin * > plugins() const
QVector< Action * > getActions(QStringView action, QStringView ns={}) const
void setLocale(const QLocale &locale)
Application * app() const noexcept
QString fromLatin1(QByteArrayView str)
QStack< Component * > stack() const noexcept
QVariant stashTake(const QString &key)
void append(QList< T > &&value)
Engine * engine() const noexcept
Abstract View component for Cutelyst.
View * view(QStringView name={}) const
Controller * controller() const noexcept
void setQuery(const QString &query, ParsingMode mode)
bool setCustomView(QStringView name)
The Cutelyst application.
bool stashRemove(const QString &key)
void setState(bool state) noexcept
Response * response() const noexcept
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
QString arg(Args &&... args) const const
View * customView() const noexcept
QStringList errors() const noexcept
Dispatcher * dispatcher() const noexcept