11 #include <QDomDocument>
12 #include <QJsonDocument>
13 #include <QJsonObject>
16 #define LOC QString("HTTPEnc: ")
33 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
34 auto types = Accept.split(
",", QString::SkipEmptyParts);
36 auto types = Accept.split(
",", Qt::SkipEmptyParts);
39 std::vector<MimePair> weightings;
42 QString mime =
type.trimmed();
45 if (
auto index =
type.lastIndexOf(
";"); index > -1)
47 mime =
type.mid(0, index).trimmed().toLower();
48 auto qual =
type.mid(index + 1).trimmed();
49 if (
auto index2 = qual.lastIndexOf(
"="); index2 > -1)
52 auto newquality = qual.mid(index2 + 1).toFloat(&ok);
57 weightings.emplace_back(quality, mime);
61 auto comp = [](
const MimePair& First,
const MimePair& Second) {
return First.first > Second.first; };
62 std::sort(weightings.begin(), weightings.end(), comp);
67 for (
const auto & weight : weightings)
68 result.append(weight.second);
72 result.append(
"application/xml");
86 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
87 auto types = contenttype.split(
";", QString::SkipEmptyParts);
89 auto types = contenttype.split(
";", Qt::SkipEmptyParts);
98 Request->m_content->m_mimeType = mime;
99 if (mime.Name() ==
"application/x-www-form-urlencoded")
101 else if (mime.Name() ==
"text/xml" || mime.Name() ==
"application/xml" ||
102 mime.Name() ==
"application/soap+xml")
104 else if (mime.Name() ==
"application/json")
107 LOG(VB_HTTP, LOG_ERR, QString(
"Don't know how to get the parameters for MIME type: '%1'").arg(mime.Name()));
110 LOG(VB_HTTP, LOG_ERR, QString(
"Unknown MIME type: '%1'").arg(
types[0]));
119 auto payload = QString::fromUtf8(
Request->m_content->constData(),
Request->m_content->size());
124 payload.replace(
"&",
"&");
125 if (!payload.isEmpty())
127 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
128 QStringList params = payload.split(
'&', QString::SkipEmptyParts);
130 QStringList params = payload.split(
'&', Qt::SkipEmptyParts);
132 for (
const auto & param : qAsConst(params))
134 QString name = param.section(
'=', 0, 0);
135 QString value = param.section(
'=', 1);
136 value.replace(
"+",
" ");
139 name = QUrl::fromPercentEncoding(name.toUtf8());
140 value = QUrl::fromPercentEncoding(value.toUtf8());
141 Request->m_queries.insert(name.trimmed().toLower(), value);
149 LOG(VB_HTTP, LOG_DEBUG,
"Inspecting XML payload");
155 QString soapaction =
Request->m_headers->value(
"soapaction");
156 soapaction.remove(
'"');
157 int lastSlashPos= soapaction.lastIndexOf(
'/');
158 if (lastSlashPos < 0)
162 Request->m_fileName = soapaction.right(soapaction.size()-lastSlashPos-1);
163 LOG(VB_HTTP, LOG_DEBUG, QString(
"Found method call (%1)").arg(
Request->m_fileName));
165 auto payload = QDomDocument();
169 if (!payload.setContent(
static_cast<QByteArray
>(
Request->m_content->constData()),
170 true, &err_msg, &err_line, &err_col))
172 LOG(VB_HTTP, LOG_WARNING,
"Unable to parse XML request body");
173 LOG(VB_HTTP, LOG_WARNING, QString(
"- Error at line %1, column %2, msg: %3")
174 .arg(err_line).arg(err_col).arg(err_msg));
177 QString doc_name = payload.documentElement().localName();
178 if (doc_name.compare(
"envelope", Qt::CaseInsensitive) == 0)
180 LOG(VB_HTTP, LOG_DEBUG,
"Found SOAP XML message envelope");
181 auto doc_body = payload.documentElement().namedItem(
"Body");
182 if (doc_body.isNull() || !doc_body.hasChildNodes())
184 LOG(VB_HTTP, LOG_DEBUG,
"Missing or empty SOAP body");
187 auto body_contents = doc_body.firstChild();
188 if (body_contents.hasChildNodes())
190 for (QDomNode node = body_contents.firstChild(); !node.isNull(); node = node.nextSibling())
192 QString name = node.localName();
193 QString value = node.toElement().text();
197 Request->m_queries.insert(name.trimmed().toLower(), value);
198 LOG(VB_HTTP, LOG_DEBUG, QString(
"Found URL param (%1=%2)").arg(name, value));
207 LOG(VB_HTTP, LOG_DEBUG,
"Inspecting JSON payload");
212 QByteArray jstr =
static_cast<QByteArray
>(
Request->m_content->constData());
213 QJsonParseError parseError {};
214 QJsonDocument doc = QJsonDocument::fromJson(jstr, &parseError);
215 if (parseError.error != QJsonParseError::NoError)
217 LOG(VB_HTTP, LOG_WARNING,
218 QString(
"Unable to parse JSON request body - Error at position %1, msg: %2")
219 .arg(parseError.offset).arg(parseError.errorString()));
223 QJsonObject json = doc.object();
224 foreach(
const QString& key, json.keys())
229 if (json.value(key).isObject())
231 QJsonDocument vd(json.value(key).toObject());
232 value = vd.toJson(QJsonDocument::Compact);
236 value = json.value(key).toVariant().toString();
240 LOG(VB_HTTP, LOG_WARNING,
241 QString(
"Failed to parse value for key '%1' from %2")
242 .arg(key, QString(jstr)));
246 Request->m_queries.insert(key.trimmed().toLower(), value);
247 LOG(VB_HTTP, LOG_DEBUG,
248 QString(
"Found URL param (%1=%2)").arg(key, value));
257 auto * data = std::get_if<HTTPData>(&
Content);
262 QString
filename = data ? (*data)->m_fileName :
file ? (*file)->m_fileName :
"";
266 if (
types.size() == 1)
267 return types.front();
271 static const std::map<QString,QString> s_mimeOverrides =
273 {
"ts",
"video/mp2t"}
277 for (
const auto &
type : s_mimeOverrides)
278 if (suffix.compare(
type.first, Qt::CaseInsensitive) == 0)
307 auto * data = std::get_if<HTTPData>(&Response->
m_response);
317 if ((data && !(*data)->m_ranges.empty()) || (
file && !(*file)->m_ranges.empty()))
330 bool chunky = Size > 102400;
336 bool gzipsize = Size > 512 && !chunky;
340 bool compressable = (data ? (*data)->m_mimeType : (*file)->m_mimeType).Inherits(
"text/plain");
343 bool gzip = wantgzip && gzipsize && compressable;
344 bool chunk = chunkable && chunky && allowchunk;
352 if (data) (*data)->m_encoding = result;
353 if (
file) (*file)->m_encoding = result;
364 Response->
AddHeader(
"Content-Encoding",
"gzip");
366 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"'%1' compressed from %2 to %3 bytes")
367 .arg(data ? (*data)->m_fileName : (*file)->fileName())
368 .arg(Size).arg(buffer->size()));
371 buffer->m_lastModified = data ? (*data)->m_lastModified : (*file)->m_lastModified;
372 buffer->m_etag = data ? (*data)->m_etag : (*file)->m_etag;
373 buffer->m_fileName = data ? (*data)->m_fileName : (*file)->m_fileName;
374 buffer->m_cacheType = data ? (*data)->m_cacheType : (*file)->m_cacheType;
377 Size = buffer->size();