Stellarium  0.90.0
RemoteControlServiceInterface.hpp
1 /*
2  * Stellarium Remote Control plugin
3  * Copyright (C) 2017 Florian Schaukowitsch
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18  */
19 
20 #ifndef REMOTECONTROLSERVICEINTERFACE_HPP_
21 #define REMOTECONTROLSERVICEINTERFACE_HPP_
22 
23 #include <QByteArray>
24 #include <QDebug>
25 #include <QFile>
26 #include <QJsonDocument>
27 #include <QMap>
28 #include <QMimeDatabase>
29 #include <QObject>
30 
33 
37 {
38 public:
40  APIServiceResponse() : status(-1)
41  {
42 
43  }
44 
46  void setHeader(const QByteArray &name, const QByteArray &val)
47  {
48  headers[name]=val;
49  }
51  void setHeader(const QByteArray& name, const int val)
52  {
53  headers[name]=QByteArray::number(val);
54  }
55 
57  void setCacheTime(int seconds)
58  {
59  setHeader("Cache-Control","max-age="+QByteArray::number(seconds));
60  }
61 
63  void setStatus(int status, const QByteArray& text)
64  {
65  this->status = status;
66  this->statusText = text;
67  }
68 
70  void setData(const QByteArray& data)
71  {
72  this->responseData = data;
73  }
75  void appendData(const QByteArray& data)
76  {
77  this->responseData.append(data);
78  }
79 
81  void writeRequestError(const QByteArray& msg)
82  {
83  setStatus(400,"Bad Request");
84  responseData = msg;
85  }
88  void writeJSON(const QJsonDocument& doc)
89  {
90  #ifdef QT_NO_DEBUG
91  //Use compact JSON format for release builds for smaller files
92  QByteArray data = doc.toJson(QJsonDocument::Compact);
93  #else
94  //Use indented JSON format in debug builds for easier human reading
95  QByteArray data = doc.toJson(QJsonDocument::Indented);
96  #endif
97  //setHeader("Content-Length",data.size());
98  setHeader("Content-Type","application/json; charset=utf-8");
99  setData(data);
100  }
101 
109  void writeWrappedHTML(const QString& html, const QString& title)
110  {
111  QString wrapped = QStringLiteral("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html><head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>")
112  + title + QStringLiteral("</title>\n<link type=\"text/css\" rel=\"stylesheet\" href=\"/iframestyle.css\">\n<base target=\"_blank\">\n</head><body>\n")
113  + html + QStringLiteral("</body></html>");
114 
115  setHeader("Content-Type","text/html; charset=UTF-8");
116  setData(wrapped.toUtf8());
117  }
118 
122  void writeFile(const QString& path, bool allowCaching = false)
123  {
124  QFile file(path);
125  if (path.isEmpty() || !file.exists())
126  {
127  setStatus(404,"not found");
128  setData("requested file resource not found");
129  return;
130  }
131 
132  QMimeType mime = QMimeDatabase().mimeTypeForFile(path);
133 
134  if(file.open(QIODevice::ReadOnly))
135  {
136  if(allowCaching)
137  setHeader("Cache-Control","max-age="+QByteArray::number(60*60));
138 
139  //reply with correct mime type if possible
140  if(!mime.isDefault())
141  {
142  setHeader("Content-Type", mime.name().toLatin1());
143  }
144 
145  //load and write data
146  setData(file.readAll());
147  }
148  else
149  {
150  qWarning()<<"Could not open requested file resource"<<path<<file.errorString();
151  setStatus(500,"internal server error");
152  setData("could not open file resource");
153  }
154  }
155 
156 private:
157 
158  int status;
159  QByteArray statusText;
160  QMap<QByteArray,QByteArray> headers;
161  QByteArray responseData;
162 
163  static int metaTypeId;
164  static int parametersMetaTypeId;
165  friend class APIController;
166 };
167 
169 typedef QMultiMap<QByteArray, QByteArray> APIParameters;
170 
171 Q_DECLARE_METATYPE(APIServiceResponse)
172 Q_DECLARE_METATYPE(APIParameters)
173 
180 {
181 public:
182  virtual ~RemoteControlServiceInterface() {}
183 
186  virtual QLatin1String getPath() const = 0;
191  virtual bool isThreadSafe() const = 0;
199  virtual void get(const QByteArray& operation, const APIParameters& parameters, APIServiceResponse& response) = 0;
208  virtual void post(const QByteArray& operation, const APIParameters& parameters, const QByteArray& data, APIServiceResponse& response) = 0;
211  virtual void update(double deltaTime) = 0;
212 };
213 
214 // Q_DECLARE_INTERFACE enables qobject_cast for the interface
215 #define RemoteControlServiceInterface_iid "org.stellarium.plugin.RemoteSync.RemoteControlServiceInterface/1.0"
216 Q_DECLARE_INTERFACE(RemoteControlServiceInterface, RemoteControlServiceInterface_iid)
217 
218 
220 #endif
void writeRequestError(const QByteArray &msg)
Sets the HTTP status to 400, and sets the response data to the message.
void setCacheTime(int seconds)
Sets the time in seconds for which the browser is allowed to cache the reply.
void writeJSON(const QJsonDocument &doc)
Sets the Content-Type to "application/json" and serializes the given document into JSON text format...
Thread-safe version of HttpResponse that can be passed around through QMetaObject::invokeMethod.
APIServiceResponse()
Constructs an invalid response.
void appendData(const QByteArray &data)
Appends to the current return data.
void writeWrappedHTML(const QString &html, const QString &title)
Because the HTML descriptions in Stellarium are often not compatible with "clean" HTML5 which is used...
void setHeader(const QByteArray &name, const QByteArray &val)
Sets a specific HTTP header to the specified value.
QMultiMap< QByteArray, QByteArray > APIParameters
Defines the HTTP request parameters for the service.
void update(double deltaTime)
Should be called each frame from the main thread, like from StelModule::update.
Interface for all Remote Control Plug-in services.
void setData(const QByteArray &data)
Replaces the current return data.
This class handles the API-specific requests and dispatches them to the correct RemoteControlServiceI...
void setStatus(int status, const QByteArray &text)
Sets the HTTP status type and status text.
void setHeader(const QByteArray &name, const int val)
Shortcut for int header values.
void writeFile(const QString &path, bool allowCaching=false)
Writes the specified file contents into the response.