cutelyst 3.9.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
actionrest.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2013-2022 Daniel Nicoletti <dantti12@gmail.com>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5#include "actionrest_p.h"
6#include "context.h"
7#include "controller.h"
8#include "dispatcher.h"
9
10#include <QDebug>
11#include <QUrl>
12
13using namespace Cutelyst;
14
52 : Action(new ActionRESTPrivate(this), parent)
53{
54}
55
57{
58 Q_D(const ActionREST);
59
60 if (!Action::doExecute(c)) {
61 return false;
62 }
63
64 return d->dispatchRestMethod(c, c->request()->method());
65}
66
67ActionRESTPrivate::ActionRESTPrivate(ActionREST *q)
68 : q_ptr(q)
69{
70}
71
72bool ActionRESTPrivate::dispatchRestMethod(Context *c, const QString &httpMethod) const
73{
74 Q_Q(const ActionREST);
75 const QString restMethod = q->name() + u'_' + httpMethod;
76
77 Controller *controller = q->controller();
78 Action *action = controller->actionFor(restMethod);
79 if (!action) {
80 // Look for non registered actions in this controller
81 const ActionList actions = controller->actions();
82 for (Action *controllerAction : actions) {
83 if (controllerAction->name() == restMethod) {
84 action = controllerAction;
85 break;
86 }
87 }
88 }
89
90 if (action) {
91 return c->execute(action);
92 }
93
94 bool ret = false;
95 if (httpMethod.compare(u"OPTIONS") == 0) {
96 ret = returnOptions(c, q->name());
97 } else if (httpMethod.compare(u"HEAD") == 0) {
98 // redispatch to GET
99 ret = dispatchRestMethod(c, QStringLiteral("GET"));
100 } else if (httpMethod.compare(u"not_implemented") != 0) {
101 // try dispatching to foo_not_implemented
102 ret = dispatchRestMethod(c, QStringLiteral("not_implemented"));
103 } else {
104 // not_implemented
105 ret = returnNotImplemented(c, q->name());
106 }
107
108 return ret;
109}
110
111bool ActionRESTPrivate::returnOptions(Context *c, const QString &methodName) const
112{
113 Response *response = c->response();
114 response->setContentType(QStringLiteral("text/plain"));
115 response->setStatus(Response::OK); // 200
116 response->setHeader(QStringLiteral("ALLOW"), getAllowedMethods(c->controller(), methodName));
117 response->body().clear();
118 return true;
119}
120
121bool ActionRESTPrivate::returnNotImplemented(Context *c, const QString &methodName) const
122{
123 Response *response = c->response();
124 response->setStatus(Response::MethodNotAllowed); // 405
125 response->setHeader(QStringLiteral("ALLOW"), getAllowedMethods(c->controller(), methodName));
126 const QString body = QLatin1String("Method ") + c->req()->method() +
127 QLatin1String(" not implemented for ") + c->uriFor(methodName).toString();
128 response->setBody(body);
129 return true;
130}
131
132QString Cutelyst::ActionRESTPrivate::getAllowedMethods(Controller *controller,
133 const QString &methodName) const
134{
135 QStringList methods;
136 const QString name = methodName + u'_';
137 const ActionList actions = controller->actions();
138 for (Action *action : actions) {
139 const QString method = action->name();
140 if (method.startsWith(name)) {
141 methods.append(method.mid(name.size()));
142 }
143 }
144
145 if (methods.contains(u"GET")) {
146 methods.append(QStringLiteral("HEAD"));
147 }
148
149 methods.removeAll(QStringLiteral("not_implemented"));
150 methods.sort();
151 methods.removeDuplicates();
152
153 return methods.join(u", ");
154}
155
156#include "moc_actionrest.cpp"
Automated REST Method Dispatching.
Definition actionrest.h:16
bool doExecute(Context *c) override
ActionREST(QObject *parent=nullptr)
This class represents a Cutelyst Action.
Definition action.h:35
virtual bool doExecute(Context *c) override
Definition action.cpp:136
Action(QObject *parent=nullptr)
Definition action.cpp:12
QString name() const
Definition component.cpp:33
The Cutelyst Context.
Definition context.h:39
QUrl uriFor(const QString &path=QString(), const QStringList &args=QStringList(), const ParamsMultiMap &queryValues=ParamsMultiMap()) const
Definition context.cpp:235
bool execute(Component *code)
Definition context.cpp:429
Response * response() const noexcept
Definition context.cpp:96
Cutelyst Controller base class
Definition controller.h:88
Action * actionFor(const QString &name) const
ActionList actions() const
void setStatus(quint16 status) noexcept
Definition response.cpp:70
void setBody(QIODevice *body)
Definition response.cpp:100
Q_REQUIRED_RESULT QByteArray & body()
Definition response.cpp:83
void setHeader(const QString &field, const QString &value)
Definition response.cpp:328
void setContentType(const QString &type)
Definition response.h:220
The Cutelyst namespace holds all public Cutelyst API.
Definition Mainpage.dox:8
QVector< Action * > ActionList
Definition action.h:154
void clear()
void append(const T &value)
int removeAll(const T &value)
QObject(QObject *parent)
QObject * parent() const const
QString mid(int position, int n) const const
int size() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
QString join(const QString &separator) const const
int removeDuplicates()
void sort(Qt::CaseSensitivity cs)
QString toString(FormattingOptions options) const const