Timesheets-Server
Timesheets server
Načítám...
Vyhledávám...
Nebylo nic nalezeno
abstractcontroller.cpp
Zobrazit dokumentaci tohoto souboru.
1
8#include "httprequesthandler.h"
9#include "httprequest.h"
10#include "httpresponse.h"
11#include "httpconnection.h"
12#include "requestauthorizer.h"
13#include "json.h"
14#include "pdebug.h"
15#include <QUrl>
16#include <QStringList>
17
18using namespace Httpd;
19
20AbstractController::AbstractController(HobrasoftHttpd::HttpConnection *parent) : HobrasoftHttpd::HttpRequestHandler(parent) {
21 m_authorizer = NULL;
22 m_connection = parent;
23 m_checkId = false;
24}
25
26
27Db::Database *AbstractController::db() {
28 return (authenticatedUser() != nullptr)
29 ? Db::Database::create(this, authenticatedUser())
30 : Db::Database::create(this);
31}
32
33
34HobrasoftHttpd::HttpRequest *AbstractController::request() const {
35 return m_request;
36}
37
38
39HobrasoftHttpd::HttpConnection *AbstractController::connection() const {
40 return m_connection;
41}
42
43
44bool AbstractController::isAuthorized(Security::Permissions::Permission permission) {
45 if (m_authorizer == NULL) {
46 return true;
47 }
48 return m_authorizer->isAuthorized(permission);
49}
50
51
52void AbstractController::service(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response) {
53 m_request = request;
54 QString path = request->path();
55 QStringList parts = path.split("/");
56
57 if (parts.size() <= 1) {
58 serviceError(request, response, 404, "not-found", "Object not found");
59 return;
60 }
61
62 parts.removeFirst();
63 if (parts.first() == "api") { parts.removeAt(0); }
64 if (parts.first() == "v1") { parts.removeAt(0); }
65
66 switch (parts.size()) {
67 case 1:
68 if (request->method() != "GET") {
69 serviceError(request, response, 405, "bad-request", "Method not allowed");
70 return;
71 }
72 serviceList(request, response);
73 return;
74
75 case 2:
76 if (parts[1] == "events") {
77 if (request->method() != "GET") {
78 serviceError(request, response, 405, "bad-request", "Method not allowed");
79 return;
80 }
81 response->setHeader("Content-Type", "text/event-stream");
82 response->setHeader("Cache-Control", "no-cache,public");
83 response->setHeader("Transfer-Encoding", "chunked");
84 if (!request->header("Referer").isEmpty()) {
85 QUrl referer = QUrl::fromUserInput(request->header("Referer"));
86 QUrl allow;
87 allow.setScheme(referer.scheme());
88 allow.setHost(referer.host());
89 allow.setPort(referer.port());
90 response->setHeader("Access-Control-Allow-Origin", allow.toString());
91 }
92 response->flushSocket();
93 serviceEvents(request, response);
94 return;
95 }
96
97 if (parts[1] != "events") {
98 QString id = parts[1];
99 if (request->method() == "GET") {
100 if (!exists(request, id)) {
101 serviceError(request, response, 404, "not-found", "Not found");
102 return;
103 }
104 response->setHeader("Content-Type", "application/json");
105 response->setHeader("Cache-Control", "no-cache,public");
106 serviceIdGet(request, response, id);
107 return;
108 }
109 if (request->method() == "PUT") {
110
111 bool ok = false;
112 QVariantMap data = JSON::data(request->body(), &ok).toMap();
113 if (!ok) {
114 serviceError(request, response, 400, "bad-request", "Could not parse JSON data");
115 return;
116 }
117
118 if (m_checkId && !data.contains("id")) {
119 serviceError(request, response, 400, "bad-request", "Data must contain ID");
120 return;
121 }
122
123 response->setHeader("Content-Type", "application/json");
124 response->setHeader("Cache-Control", "no-cache,public");
125 serviceIdPut(request, response, data);
126 return;
127 }
128 if (request->method() == "POST") {
129
130 bool ok = false;
131 QVariantMap data = JSON::data(request->body(), &ok).toMap();
132 if (!ok) {
133 serviceError(request, response, 400, "bad-request", "Could not parse JSON data");
134 return;
135 }
136
137 if (m_checkId && !data.contains("id")) {
138 serviceError(request, response, 400, "bad-request", "Data must contain ID");
139 return;
140 }
141
142 response->setHeader("Content-Type", "application/json");
143 response->setHeader("Cache-Control", "no-cache,public");
144 serviceIdPost(request, response, data);
145 return;
146 }
147 if (request->method() == "DELETE") {
148 if (!exists(request, id)) {
149 serviceError(request, response, 404, "not-found", "Not found");
150 return;
151 }
152 response->setHeader("Content-Type", "application/json");
153 response->setHeader("Cache-Control", "no-cache,public");
154 serviceIdDelete(request, response, id);
155 return;
156 }
157 }
158 return;
159
160 case 3:
161 if (parts[1] == "events" || parts[2] != "events") {
162 serviceError(request, response, 404, "not-found", "Not found");
163 return;
164 }
165
166 if (request->method() != "GET") {
167 serviceError(request, response, 405, "bad-request", "Method not allowed");
168 return;
169 }
170
171 if (!exists(request, parts[1])) {
172 serviceError(request, response, 404, "not-found", "Not found");
173 return;
174 }
175
176 response->setHeader("Content-Type", "text/event-stream");
177 response->setHeader("Cache-Control", "no-cache,public");
178 response->setHeader("Transfer-Encoding", "chunked");
179 if (!request->header("Referer").isEmpty()) {
180 QUrl referer = QUrl::fromUserInput(request->header("Referer"));
181 QUrl allow;
182 allow.setScheme(referer.scheme());
183 allow.setHost(referer.host());
184 allow.setPort(referer.port());
185 response->setHeader("Access-Control-Allow-Origin", allow.toString());
186 }
187 response->flushSocket();
188 serviceIdEvents(request, response, parts[1]);
189 return;
190
191 default:
192 serviceError(request, response, 400, "bad-request", "Request could not be recognized");
193 return;
194 }
195}
196
197
199 HobrasoftHttpd::HttpRequest *request,
200 HobrasoftHttpd::HttpResponse *response,
201 int code,
202 const QString& error,
203 const QString& reason) {
204
205 Q_UNUSED(request);
206
207 QVariantMap data;
208 data["error"] = error;
209 data["reason"] = reason;
210
211 HobrasoftHttpd::HttpResponse *r = (response == nullptr) ? new HobrasoftHttpd::HttpResponse(connection()) : response;
212 r->clearHeaders();
213 r->setHeader("Content-Type", "application/json");
214 r->setHeader("Cache-Control", "no-cache,public");
215 r->setStatus(code, error);
216 r->write( JSON::json(data) );
217 r->flush();
218// connection()->deleteLater();
219}
220
221
223 HobrasoftHttpd::HttpRequest *request,
224 HobrasoftHttpd::HttpResponse *response,
225 int code,
226 const QString& error,
227 const QVariantMap& data) {
228
229 Q_UNUSED(request);
230
231 HobrasoftHttpd::HttpResponse *r = (response == nullptr) ? new HobrasoftHttpd::HttpResponse(connection()) : response;
232 r->clearHeaders();
233 r->setHeader("Content-Type", "application/json");
234 r->setHeader("Cache-Control", "no-cache,public");
235 r->setStatus(code, error);
236 r->write( JSON::json(data) );
237 r->flush();
238// connection()->deleteLater();
239}
240
241
243 HobrasoftHttpd::HttpRequest *request,
244 HobrasoftHttpd::HttpResponse *response,
245 const QVariant& data) {
246
247 Q_UNUSED(request);
248
249 QVariantMap okdata;
250 okdata["ok"] = true;
251
252 if (!response->containsHeader("Content-Type")) { response->setHeader("Content-Type", "application/json"); }
253 if (!response->containsHeader("Cache-Control")) { response->setHeader("Cache-Control", "no-cache,public"); }
254 response->setStatus(200, "OK");
255 response->write( JSON::json( (!data.isValid() || data.isNull()) ? okdata : data) );
256 response->flush();
257}
258
259
261 HobrasoftHttpd::HttpRequest *request,
262 HobrasoftHttpd::HttpResponse *response,
263 const QVariant& data) {
264 Q_UNUSED(request);
265 Q_UNUSED(response);
266
267 // Pozor! Hlavička se neposílá, ale je potřeba
268 // Skutečná hlavička se posílá v metodě service()
269 HobrasoftHttpd::HttpResponse *lresponse = HttpRequestHandler::response();
270 lresponse->setHeader("Transfer-Encoding", "chunked");
271 lresponse->setHeader("Content-Type", "text/event-stream");
272 lresponse->setHeader("Cache-Control", "no-cache,public");
273 lresponse->setSendHeaders(false);
274
275 QByteArray datagram;
276 datagram += "event: status\n";
277 datagram += "data: ";
278 datagram += JSON::json(data);
279 datagram += "\n";
280 datagram += "\n";
281 lresponse->write(datagram);
282 lresponse->flushSocket();
283 lresponse->flushAndDelete();
284
285}
286
287void AbstractController::serviceList (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response) {
288 serviceError(request, response, 501, "not-implemeted", "Method not implemented");
289}
290
291
292void AbstractController::serviceEvents (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response) {
293 serviceError(request, response, 501, "not-implemeted", "Method not implemented");
294}
295
296
297void AbstractController::serviceIdEvents (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QString&) {
298 serviceError(request, response, 501, "not-implemeted", "Method not implemented");
299}
300
301
302void AbstractController::serviceIdDelete (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QString&) {
303 serviceError(request, response, 501, "not-implemeted", "Method not implemented");
304}
305
306
307void AbstractController::serviceIdGet (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QString&) {
308 serviceError(request, response, 501, "not-implemeted", "Method not implemented");
309}
310
311
312void AbstractController::serviceIdPut (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QVariantMap&) {
313 serviceError(request, response, 501, "not-implemeted", "Method not implemented");
314}
315
316
317void AbstractController::serviceIdPost (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QVariantMap&) {
318 serviceError(request, response, 501, "not-implemeted", "Method not implemented");
319}
320
virtual void serviceIdPut(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QVariantMap &data)
Pošle odpověď na požadavek konkrétního ID metodou PUT - obvykle vloží nový objekt nebo přepíše existu...
AbstractController(HobrasoftHttpd::HttpConnection *parent)
Konstruktor.
virtual void serviceIdGet(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QString &id)
Pošle odpověď na požadavek konkrétního ID metodou GET.
HobrasoftHttpd::HttpConnection * connection() const
Vrací ukazatel na aktuální connection.
virtual void serviceEvent(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QVariant &data)
Pošle do otevřeného proudu událostí jednu událost.
virtual void serviceIdDelete(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QString &id)
Pošle odpověď na požadavek konkrétního ID metodou DELETE - obvykle objekt smaže.
virtual void serviceIdEvents(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QString &id)
Pošle v odpovědi proud událostí spojených se všemi objekty ve třídě
virtual void serviceEvents(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response)
Pošle v odpovědi kompletní seznam všech objektů ve třídě a následně
virtual void serviceError(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, int code, const QString &error, const QVariantMap &data)
Pošle chybovou odpověď
virtual void serviceIdPost(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QVariantMap &data)
Pošle odpověď na požadavek konkrétního ID metodou PUT - obvykle vloží nový objekt nebo přepíše existu...
virtual void service(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response)
Obsluha požadavku.
virtual void serviceOK(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QVariant &data=QVariant())
Pošle odpověď 200 OK.
virtual bool exists(const QString &id)
Kontrola existence zadaného ID.
HobrasoftHttpd::HttpRequest * request() const
Vrací ukazatel na aktuální request.
virtual void serviceList(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response)
Měl by poslat v odpovědi kompletní seznam všech objektů ve třídě a ukončit se.
static QVariant data(const QByteArray &json)
Converts json to data.
Definition json.cpp:69
static QByteArray json(const QVariant &data)
Converts data to json.
Definition json.cpp:21
Jmenný prostor pro obsluhu konkrétních HTTP požadavků aplikace.
Permission
Seznam jednotlivých oprávnění
Definition permissions.h:22