Hobrasoft httpd server
Embedded HTTP server for Qt and C++
abstractcontroller.cpp
Go to the documentation of this file.
1 
7 #include "abstractcontroller.h"
8 #include "httprequesthandler.h"
9 #include "httprequest.h"
10 #include "httpresponse.h"
11 #include "httpconnection.h"
12 #include "json.h"
13 #include <QString>
14 #include <QStringList>
15 
16 
17 using namespace Example::Httpd;
18 
19 
21  m_connection = parent;
22  m_checkId = true;
23 }
24 
25 
26 HobrasoftHttpd::HttpRequest *AbstractController::request() const {
27  return m_request;
28 }
29 
30 
32  return m_connection;
33 }
34 
35 
37  m_request = request;
38  QString path = request->path();
39  QStringList parts = path.split("/");
40 
41  if (parts.size() <= 1) {
42  serviceError(request, response, 404, "not-found", "Object not found");
43  return;
44  }
45 
46  parts.removeFirst();
47 
48  switch (parts.size()) {
49  case 1:
50  if (request->method() != "GET") {
51  serviceError(request, response, 405, "bad-request", "Method not allowed");
52  return;
53  }
54  serviceList(request, response);
55  return;
56 
57  case 2:
58  if (parts[1] == "events") {
59  if (request->method() != "GET") {
60  serviceError(request, response, 405, "bad-request", "Method not allowed");
61  return;
62  }
63  response->setHeader("Content-Type", "text/event-stream");
64  response->setHeader("Cache-Control", "no-cache,public");
65  response->setHeader("Transfer-Encoding", "chunked");
67  serviceEvents(request, response);
68  return;
69  }
70 
71  if (parts[1] != "events") {
72  QString id = parts[1];
73  if (request->method() == "GET") {
74  response->setHeader("Content-Type", "application/json");
75  response->setHeader("Cache-Control", "no-cache,public");
76  if (!exists(id)) {
77  serviceError(request, response, 404, "not-found", "Not found");
78  return;
79  }
80  serviceIdGet(request, response, id);
81  return;
82  }
83  if (request->method() == "PUT") {
84  response->setHeader("Content-Type", "application/json");
85  response->setHeader("Cache-Control", "no-cache,public");
86 
87  QVariantMap data = JSON::data(request->body()).toMap();
88  if (m_checkId && !data.contains("id")) {
89  serviceError(request, response, 400, "bad-request", "Data must contain ID");
90  return;
91  }
92 
93  serviceIdPut(request, response, data);
94  return;
95  }
96  if (request->method() == "POST") {
97  response->setHeader("Content-Type", "application/json");
98  response->setHeader("Cache-Control", "no-cache,public");
99 
100  QVariantMap data = JSON::data(request->body()).toMap();
101  if (m_checkId && !data.contains("id")) {
102  serviceError(request, response, 400, "bad-request", "Data must contain ID");
103  return;
104  }
105 
106  serviceIdPost(request, response, data);
107  return;
108  }
109  if (request->method() == "DELETE") {
110  response->setHeader("Content-Type", "application/json");
111  response->setHeader("Cache-Control", "no-cache,public");
112  if (!exists(id)) {
113  serviceError(request, response, 404, "not-found", "Not found");
114  return;
115  }
116  serviceIdDelete(request, response, id);
117  return;
118  }
119  }
120  break;
121 
122  case 3:
123  if (parts[1] == "events" || parts[2] != "events") {
124  serviceError(request, response, 404, "not-found", "Not found");
125  return;
126  }
127 
128  if (request->method() != "GET") {
129  serviceError(request, response, 405, "bad-request", "Method not allowed");
130  return;
131  }
132 
133  if (!exists(parts[1])) {
134  serviceError(request, response, 404, "not-found", "Not found");
135  return;
136  }
137 
138  response->setHeader("Content-Type", "text/event-stream");
139  response->setHeader("Cache-Control", "no-cache,public");
140  response->setHeader("Transfer-Encoding", "chunked");
142  serviceIdEvents(request, response, parts[1]);
143  return;
144 
145  default:
146  serviceError(request, response, 400, "bad-request", "Request could not be recognized");
147  return;
148  }
149 }
150 
151 void AbstractController::serviceError(
152  HobrasoftHttpd::HttpRequest *request,
153  HobrasoftHttpd::HttpResponse *response,
154  int code,
155  const QString& error,
156  const QString& reason) {
157 
158  Q_UNUSED(request);
159 
160  QVariantMap data;
161  data["error"] = error;
162  data["reason"] = reason;
163 
165  response->setHeader("Content-Type", "application/json");
166  response->setHeader("Cache-Control", "no-cache,public");
167  response->setStatus(code, reason);
168  response->write( JSON::json(data) );
169  response->flush();
170 }
171 
172 
174  HobrasoftHttpd::HttpRequest *request,
175  HobrasoftHttpd::HttpResponse *response,
176  const QVariant& data) {
177 
178  Q_UNUSED(request);
179 
180  QVariantMap okdata;
181  okdata["ok"] = true;
182 
183  if (!response->containsHeader("Content-Type")) { response->setHeader("Content-Type", "application/json"); }
184  if (!response->containsHeader("Cache-Control")) { response->setHeader("Cache-Control", "no-cache,public"); }
185  response->setStatus(200, "OK");
186  response->write( JSON::json( (!data.isValid() || data.isNull()) ? okdata : data) );
187  response->flush();
188 }
189 
190 
191 void AbstractController::serviceEvent (
192  HobrasoftHttpd::HttpRequest *request,
193  HobrasoftHttpd::HttpResponse *response,
194  const QVariant& data) {
195  Q_UNUSED(request);
196  Q_UNUSED(response);
197 
198  connection()->setTimeout(0);
200  lresponse->setHeader("Transfer-Encoding", "chunked");
201  lresponse->setHeader("Content-Type", "text/event-stream");
202  lresponse->setHeader("Cache-Control", "no-cache,public");
203  lresponse->setSendHeaders(false);
204 
205  QByteArray datagram;
206  datagram += "event: status\n";
207  datagram += "data: ";
208  datagram += JSON::json(data);
209  datagram += "\n";
210  datagram += "\n";
211  lresponse->write(datagram);
212  lresponse->flushSocket();
213  lresponse->flushAndDelete();
214 }
215 
216 void AbstractController::serviceList (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response) {
217  serviceError(request, response, 501, "not-implemeted", "Method not implemented");
218 }
219 
220 
221 void AbstractController::serviceEvents (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response) {
222  serviceError(request, response, 501, "not-implemeted", "Method not implemented");
223 }
224 
225 
226 void AbstractController::serviceIdEvents (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QString&) {
227  serviceError(request, response, 501, "not-implemeted", "Method not implemented");
228 }
229 
230 
231 void AbstractController::serviceIdDelete (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QString&) {
232  serviceError(request, response, 501, "not-implemeted", "Method not implemented");
233 }
234 
235 
236 void AbstractController::serviceIdGet (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QString&) {
237  serviceError(request, response, 501, "not-implemeted", "Method not implemented");
238 }
239 
240 
241 void AbstractController::serviceIdPut (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QVariantMap&) {
242  serviceError(request, response, 501, "not-implemeted", "Method not implemented");
243 }
244 
245 
246 void AbstractController::serviceIdPost (HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QVariantMap&) {
247  serviceError(request, response, 501, "not-implemeted", "Method not implemented");
248 }
249 
virtual void serviceOK(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response, const QVariant &data=QVariant())
Sends 200 OK response.
AbstractController(HobrasoftHttpd::HttpConnection *parent)
Constructor.
HttpResponse * response()
Returns new instance of HttpResponse class.
QString path() const
Returns path of the request (/files/index.html)
Definition: httprequest.h:78
HttpConnection * connection() const
Returns pointer to parent HttpConnection class.
virtual void service(HobrasoftHttpd::HttpRequest *request, HobrasoftHttpd::HttpResponse *response)
Request processing.
Name space for own application HTTP server.
void flush()
Writes last part of the response and closes the socket when possible.
void setSendHeaders(bool send)
Sets the header sending.
Definition: httpresponse.h:59
virtual bool exists(const QString &id) const
Check existence of th ID.
Response to HTTP request - headers, cookies and body.
Definition: httpresponse.h:30
void flushSocket()
Flushed sockets data to network.
void write(const QByteArray &data)
Writes data to response body.
static QVariant data(const QByteArray &json)
Converts json to data.
Definition: json.cpp:45
static QByteArray json(const QVariant &data)
Converts data to json.
Definition: json.cpp:22
bool containsHeader(const QString &name)
Returns true if headers contains specific header.
Definition: httpresponse.h:122
HttpResponse * response()
Returns new instance of class HttpResponse.
QByteArray body() const
Returns the body of the request.
Definition: httprequest.h:133
Processes HTTP request, parses headers, body and files sent by HTTP protocol.
Definition: httprequest.h:23
void setStatus(int code, const QString &description=QString())
Set the status code and the description of the response.
void setHeader(const QString &name, const QString &value)
Sets or rewrite one header.
void clearHeaders()
Clears all headers set.
QString method() const
Returns used HTTP method of the request (GET, PUT, POST or DELETE)
Definition: httprequest.h:73
Namespace of HTTP server.
One single connection to http server.