MythTV  master
mythhttpservice.cpp
Go to the documentation of this file.
1 #include <QFileInfo>
2 
3 // MythTV
4 #include "mythlogging.h"
5 #include "mythdate.h"
6 #include "http/mythwsdl.h"
7 #include "http/mythhttpservice.h"
8 #include "http/mythhttprequest.h"
11 #include "http/mythhttpencoding.h"
13 
14 #define LOC QString("HTTPService: ")
15 
17  : m_name(MetaService->m_name),
18  m_staticMetaService(MetaService)
19 {
20 }
21 
28 {
29  QString& method = Request->m_fileName;
30  if (method.isEmpty())
31  return nullptr;
33  // WSDL
34  if (method == "wsdl") {
36  return wsdl.GetWSDL( Request );
37  }
38  if ( method == "xsd" )
39  {
40  MythXSD xsd;
41  if (Request->m_queries.contains( "type" ))
42  return xsd.GetXSD( Request, Request->m_queries.value("type"));
43  // The xsd for enums does not work, so it is commented for now.
44  // else
45  // return xsd.GetEnumXSD( Request, Request->m_queries.value("enum"));
46  }
47 
48  // Find the method
49  LOG(VB_HTTP, LOG_DEBUG, LOC + QString("Looking for method '%1'").arg(method));
50  HTTPMethodPtr handler = nullptr;
51  // cppcheck-suppress unassignedVariable
52  for (auto & [path, handle] : m_staticMetaService->m_slots)
53  if (path == method) { handler = handle; break; }
54 
55  if (handler == nullptr)
56  {
57  // Should we just return not found here rather than falling through
58  // to all of the other handlers? Do we need other handlers?
59  LOG(VB_HTTP, LOG_DEBUG, LOC + "Failed to find method");
60  return nullptr;
61  }
62 
63  // Authentication required
64  if (handler->m_protected)
65  {
66  LOG(VB_HTTP, LOG_INFO, LOC + "Authentication required for this call");
67  }
68 
69  // Sanity check type count (handler should have the return type at least)
70  if (handler->m_types.empty())
71  return nullptr;
72 
73  // Handle options
74  Request->m_allowed = handler->m_requestTypes;
76  return options;
77 
78  // Parse the parameters and match against those expected by the method.
79  // As for the old code, this allows parameters to be missing and they will
80  // thus be allocated a default/null/value.
81  size_t typecount = std::min(handler->m_types.size(), static_cast<size_t>(100));
82 
83  // Build parameters list
84  // Note: We allow up to 100 args but anything above Q_METAMETHOD_INVOKE_MAX_ARGS
85  // will be ignored
86  std::array<void*, 100> param { nullptr};
87  std::array<int, 100> types { 0 };
88 
89  // Return type
90 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
91  param[0] = handler->m_types[0] == 0 ? nullptr : QMetaType::create(handler->m_types[0]);
92 #else
93  param[0] = handler->m_types[0] == 0 ? nullptr : QMetaType(handler->m_types[0]).create();
94 #endif
95  types[0] = handler->m_types[0];
96 
97  // Parameters
98  // Iterate over the method's parameters and search for the incoming values...
99  size_t count = 1;
100  QString error;
101  while (count < typecount)
102  {
103  auto name = handler->m_names[count];
104  auto value = Request->m_queries.value(name.toLower(), "");
105  auto type = handler->m_types[count];
106  types[count] = type;
107  // These should be filtered out in MythHTTPMetaMethod
108  if (type == 0)
109  {
110  error = QString("Unknown parameter type '%1'").arg(name);
111  break;
112  }
113 
114 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
115  auto * newparam = QMetaType::create(type);
116 #else
117  auto * newparam = QMetaType(type).create();
118 #endif
119  param[count] = handler->CreateParameter(newparam, type, value);
120  ++count;
121  }
122 
123  HTTPResponse result = nullptr;
124  if (count == typecount)
125  {
126  // Invoke
127  QVariant returnvalue;
128  try {
129  if (qt_metacall(QMetaObject::InvokeMetaMethod, handler->m_index, param.data()) >= 0)
130  LOG(VB_GENERAL, LOG_ERR, "qt_metacall error");
131  else
132  {
133  // Retrieve result
134  returnvalue = handler->CreateReturnValue(types[0], param[0]);
135  }
136  }
137  catch( QString &msg ) {
138  LOG(VB_GENERAL, LOG_ERR, "Service Exception: " + msg);
139  Request->m_status = HTTPBadRequest;
141  }
142  catch (V2HttpRedirectException &ex) {
144  }
145 
146  if (!returnvalue.isValid())
147  {
148  if (!result)
149  result = MythHTTPResponse::ErrorResponse(Request, "Unknown Failure");
150  }
151  else if (returnvalue.canConvert<QFileInfo>())
152  {
153  if (!result)
154  {
155  auto info = returnvalue.value<QFileInfo>();
156  QString file = info.absoluteFilePath();
157  if (file.size() == 0)
158  {
159  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Invalid request for unknown file"));
160  Request->m_status = HTTPNotFound;
162  }
163  else
164  {
165  HTTPFile httpfile = MythHTTPFile::Create(info.fileName(),file);
166  if (!httpfile->open(QIODevice::ReadOnly))
167  {
168  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Failed to open '%1'").arg(file));
169  Request->m_status = HTTPNotFound;
171  }
172  else
173  {
174  httpfile->m_lastModified = info.lastModified();
175  httpfile->m_cacheType = HTTPLastModified | HTTPLongLife;
176  LOG(VB_HTTP, LOG_DEBUG, LOC + QString("Last modified: %2")
177  .arg(MythDate::toString(httpfile->m_lastModified, MythDate::kOverrideUTC | MythDate::kRFC822)));
178  // Create our response
179  result = MythHTTPResponse::FileResponse(Request, httpfile);
180  }
181  }
182  }
183  }
184  else
185  {
186  auto accept = MythHTTPEncoding::GetMimeTypes(MythHTTP::GetHeader(Request->m_headers, "accept"));
187  HTTPData content = MythSerialiser::Serialise(handler->m_returnTypeName, returnvalue, accept);
188  content->m_cacheType = HTTPETag | HTTPShortLife;
190 
191  // If the return type is QObject* we need to cleanup
192  if (returnvalue.canConvert<QObject*>())
193  {
194  LOG(VB_HTTP, LOG_DEBUG, LOC + "Deleting object");
195  auto * object = returnvalue.value<QObject*>();
196  delete object;
197  }
198  }
199  }
200 
201  // Cleanup
202  for (size_t i = 0; i < typecount; ++i)
203  {
204  if ((param[i] != nullptr) && (types[i] != 0))
205  {
206 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
207  QMetaType::destroy(types[i], param[i]);
208 #else
209  QMetaType(types[i]).destroy(param[i]);
210 #endif
211  }
212  }
213 
214  // Return the previous error
215  if (count != typecount)
216  {
217  LOG(VB_HTTP, LOG_ERR, LOC + error);
218  Request->m_status = HTTPBadRequest;
220  }
221 
222  // Valid result...
223  return result;
224 }
225 
226 
228 {
229  return m_name;
230 }
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:84
MythWSDL::GetWSDL
HTTPResponse GetWSDL(const HTTPRequest2 &Request)
Definition: mythwsdl.cpp:28
error
static void error(const char *str,...)
Definition: vbi.cpp:36
V2HttpRedirectException
Definition: mythhttpservice.h:40
MythHTTPResponse::FileResponse
static HTTPResponse FileResponse(const HTTPRequest2 &Request, const HTTPFile &File)
Definition: mythhttpresponse.cpp:260
MythWSDL
Definition: mythwsdl.h:34
MythHTTPResponse::DataResponse
static HTTPResponse DataResponse(const HTTPRequest2 &Request, const HTTPData &Data)
Definition: mythhttpresponse.cpp:249
build_compdb.content
content
Definition: build_compdb.py:38
MythHTTPFile::Create
static HTTPFile Create(const QString &ShortName, const QString &FullName)
Definition: mythhttpfile.cpp:14
MythHTTP::GetHeader
static QString GetHeader(const HTTPHeaders &Headers, const QString &Value, const QString &Default="")
Definition: mythhttptypes.h:316
MythDate::kOverrideUTC
@ kOverrideUTC
Present date/time in UTC.
Definition: mythdate.h:31
mythhttpmetaservice.h
MythSerialiser::Serialise
static HTTPData Serialise(const QString &Name, const QVariant &Value, const QStringList &Accept)
Serialise the given data with an encoding suggested by Accept.
Definition: mythserialiser.cpp:27
HTTPETag
@ HTTPETag
Definition: mythhttptypes.h:144
types
static const struct wl_interface * types[]
Definition: idle_inhibit_unstable_v1.c:39
MythXSD
Definition: mythxsd.h:33
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
HTTPLongLife
@ HTTPLongLife
Definition: mythhttptypes.h:148
build_compdb.file
file
Definition: build_compdb.py:55
MythHTTPService::HTTPRequest
virtual HTTPResponse HTTPRequest(const HTTPRequest2 &Request)
Respond to a valid HTTPRequest.
Definition: mythhttpservice.cpp:27
HTTPNotFound
@ HTTPNotFound
Definition: mythhttptypes.h:114
HTTPData
std::shared_ptr< MythHTTPData > HTTPData
Definition: mythhttptypes.h:36
MythHTTPResponse::HandleOptions
static HTTPResponse HandleOptions(const HTTPRequest2 &Request)
Definition: mythhttpresponse.cpp:179
MythHTTPService::m_staticMetaService
MythHTTPMetaService * m_staticMetaService
Definition: mythhttpservice.h:34
mythdate.h
MythXSD::GetXSD
HTTPResponse GetXSD(const HTTPRequest2 &pRequest, QString sTypeName)
Definition: mythxsd.cpp:209
mythlogging.h
LOC
#define LOC
Definition: mythhttpservice.cpp:14
mythwsdl.h
V2HttpRedirectException::m_hostName
QString m_hostName
Definition: mythhttpservice.h:44
MythHTTPResponse::ErrorResponse
static HTTPResponse ErrorResponse(MythHTTPStatus Status, const QString &ServerName)
Definition: mythhttpresponse.cpp:203
mythhttpencoding.h
HTTPLastModified
@ HTTPLastModified
Definition: mythhttptypes.h:145
mythhttpresponse.h
MythHTTPResponse::RedirectionResponse
static HTTPResponse RedirectionResponse(const HTTPRequest2 &Request, const QString &Redirect)
Definition: mythhttpresponse.cpp:220
MythHTTPService::m_name
QString m_name
Definition: mythhttpservice.h:33
mythserialiser.h
HTTPResponse
std::shared_ptr< MythHTTPResponse > HTTPResponse
Definition: mythhttptypes.h:39
hardwareprofile.distros.mythtv_data.request.Request
def Request(url=None)
Definition: distros/mythtv_data/request.py:64
mythhttpservice.h
MythHTTPService::Name
QString & Name()
Definition: mythhttpservice.cpp:227
HTTPBadRequest
@ HTTPBadRequest
Definition: mythhttptypes.h:111
MythHTTPMetaService::m_slots
HTTPMethods m_slots
Definition: mythhttpmetaservice.h:24
MythDate::kRFC822
@ kRFC822
HTTP Date format.
Definition: mythdate.h:30
HTTPRequest2
std::shared_ptr< MythHTTPRequest > HTTPRequest2
Definition: mythhttptypes.h:38
mythhttprequest.h
MythHTTPService::m_request
HTTPRequest2 m_request
Definition: mythhttpservice.h:35
MythHTTPEncoding::GetMimeTypes
static QStringList GetMimeTypes(const QString &Accept)
Definition: mythhttpencoding.cpp:30
HTTPFile
std::shared_ptr< MythHTTPFile > HTTPFile
Definition: mythhttptypes.h:40
HTTPShortLife
@ HTTPShortLife
Definition: mythhttptypes.h:146
HTTPMethodPtr
std::shared_ptr< MythHTTPMetaMethod > HTTPMethodPtr
Definition: mythhttpmetamethod.h:14
build_compdb.options
options
Definition: build_compdb.py:11
MythHTTPService::MythHTTPService
MythHTTPService(MythHTTPMetaService *MetaService)
Definition: mythhttpservice.cpp:16
MythHTTPMetaService
Definition: mythhttpmetaservice.h:10