8 #include "multipartformdataparser.h" 14 #include <QJsonDocument> 15 #include <QJsonObject> 21 : d_ptr(new RequestPrivate)
23 d_ptr->engineRequest = engineRequest;
29 qDeleteAll(d_ptr->uploads);
37 return d->engineRequest->remoteAddress;
45 quint32 data = d->engineRequest->remoteAddress.toIPv4Address(&ok);
49 return d->engineRequest->remoteAddress.toString();
59 if (!d->remoteHostname.isEmpty()) {
60 ret = d->remoteHostname;
66 qCDebug(CUTELYST_REQUEST) <<
"DNS lookup for the client hostname failed" 67 << d->engineRequest->remoteAddress;
72 ret = d->remoteHostname;
79 return d->engineRequest->remotePort;
87 if (!(d->parserStatus & RequestPrivate::UrlParsed)) {
89 if (d->engineRequest->serverAddress.isEmpty()) {
95 uri.
setScheme(d->engineRequest->isSecure ? u
"https"_s : u
"http"_s);
101 if (!d->engineRequest->query.isEmpty()) {
106 d->parserStatus |= RequestPrivate::UrlParsed;
115 if (!(d->parserStatus & RequestPrivate::BaseParsed)) {
116 base = d->engineRequest->isSecure ? u
"https://"_s : u
"http://"_s;
119 if (d->engineRequest->serverAddress.isEmpty()) {
126 d->parserStatus |= RequestPrivate::BaseParsed;
134 return d->engineRequest->path;
176 return d->engineRequest->isSecure;
188 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
216 return RequestPrivate::paramsMultiMapToVariantMap(
bodyParameters());
222 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
234 while (it != query.
constEnd() && it.
key() == key) {
244 if (!(d->parserStatus & RequestPrivate::QueryParsed)) {
247 return d->queryKeywords;
258 if (!(d->parserStatus & RequestPrivate::QueryParsed)) {
261 return d->queryParam;
270 while (it != query.
constEnd() && it.
key() == key) {
280 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
284 return d->cookies.value(name).value;
292 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
296 for (
auto it = d->cookies.constFind(name); it != d->cookies.constEnd() && it->name == name;
306 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
315 return d->engineRequest->headers;
321 return d->engineRequest->method;
327 return d->engineRequest->method.compare(
"POST") == 0;
333 return d->engineRequest->method.compare(
"GET") == 0;
339 return d->engineRequest->method.compare(
"HEAD") == 0;
345 return d->engineRequest->method.compare(
"PUT") == 0;
351 return d->engineRequest->method.compare(
"PATCH") == 0;
357 return d->engineRequest->method.compare(
"DELETE") == 0;
363 return d->engineRequest->protocol;
369 return d->engineRequest->headers.header(
"X-Requested-With").compare(
"XMLHttpRequest") == 0;
375 return d->engineRequest->remoteUser;
381 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
390 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
393 return d->uploadsMap;
400 const auto range = map.equal_range(name);
401 for (
auto i = range.first; i != range.second; ++i) {
416 ret.
replace(it.key(), it.value());
444 void RequestPrivate::parseUrlQuery()
const 447 if (engineRequest->query.size()) {
449 if (engineRequest->query.indexOf(
'=') < 0) {
451 queryKeywords = Utils::decodePercentEncoding(&aux);
453 if (parserStatus & RequestPrivate::UrlParsed) {
454 queryParam = Utils::decodePercentEncoding(engineRequest->query.data(),
455 engineRequest->query.size());
459 queryParam = Utils::decodePercentEncoding(aux.
data(), aux.
size());
463 parserStatus |= RequestPrivate::QueryParsed;
466 void RequestPrivate::parseBody()
const 469 parserStatus |= RequestPrivate::BodyParsed;
473 bool sequencial = body->isSequential();
474 qint64 posOrig = body->pos();
475 if (sequencial && posOrig) {
476 qCWarning(CUTELYST_REQUEST) <<
"Can not parse sequential post body out of beginning";
477 parserStatus |= RequestPrivate::BodyParsed;
481 const QByteArray contentType = engineRequest->headers.header(
"Content-Type");
482 if (contentType.
startsWith(
"application/x-www-form-urlencoded")) {
490 bodyParam = Utils::decodePercentEncoding(line.
data(), line.
size());
492 }
else if (contentType.
startsWith(
"multipart/form-data")) {
498 for (
Upload *upload : ups) {
499 if (upload->filename().isEmpty() &&
500 upload->headers().header(
"Content-Type").isEmpty()) {
504 uploadsMap.insert(upload->name(), upload);
508 }
else if (contentType.
startsWith(
"application/cbor")) {
514 }
else if (contentType.
startsWith(
"application/json")) {
526 parserStatus |= RequestPrivate::BodyParsed;
530 inline bool isSlit(
char c)
532 return c ==
';' || c ==
',';
537 while (from < length) {
538 if (isSlit(text.
at(from))) {
546 inline bool isLWS(
char c)
548 return c ==
' ' || c ==
'\t' || c ==
'\r' || c ==
'\n';
557 while (from < length) {
558 if (isLWS(text.
at(from))) {
576 const int length = text.
length();
577 position = nextNonWhitespace(text, position, length);
579 int semiColonPosition = findNextSplit(text, position, length);
580 if (semiColonPosition < 0) {
581 semiColonPosition = length;
584 int equalsPosition = text.
indexOf(
'=', position);
585 if (equalsPosition < 0 || equalsPosition > semiColonPosition) {
590 int secondLength = semiColonPosition - equalsPosition - 1;
591 if (secondLength > 0) {
595 position = semiColonPosition;
600 void RequestPrivate::parseCookies()
const 602 const QByteArray cookieString = engineRequest->headers.header(
"Cookie");
604 const int length = cookieString.
length();
605 while (position < length) {
606 const auto cookie = nextField(cookieString, position);
617 cookies.insert(cookie.name, cookie);
621 parserStatus |= RequestPrivate::CookiesParsed;
624 QVariantMap RequestPrivate::paramsMultiMapToVariantMap(
const ParamsMultiMap ¶ms)
630 ret.insert(ret.constBegin(), end.key(), end.value());
635 #include "moc_request.cpp" QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QString url(FormattingOptions options) const const
Request(EngineRequest *engineRequest)
QString & append(QChar ch)
QByteArray toByteArray() const const
const_iterator constFind(const Key &key) const const
QJsonDocument toJsonDocument() const const
QJsonArray array() const const
iterator replace(const Key &key, const T &value)
QVariant bodyData() const
void push_back(parameter_type value)
QByteArray protocol() const noexcept
const_iterator constEnd() const const
QCborValue bodyCbor() const
bool isDelete() const noexcept
QVariant fromValue(T &&value)
QJsonObject object() const const
QStringList arguments() const noexcept
bool isEmpty() const const
bool startsWith(QByteArrayView bv) const const
QJsonArray bodyJsonArray() const
QByteArrayView sliced(qsizetype pos) const const
QString toString() const const
QString fromUtf8(QByteArrayView str)
qsizetype length() const const
void setMatch(const QString &match)
QIODevice * body() const noexcept
QString match() const noexcept
Cutelyst Upload handles file upload requests.
void setPath(const QString &path, ParsingMode mode)
const_iterator constBegin() const const
ParamsMultiMap queryParams() const
ParamsMultiMap bodyParameters() const
QCborValue fromCbor(QCborStreamReader &reader)
void addQueryItem(const QString &key, const QString &value)
QVector< Upload * > uploads() const
QHostAddress address() const noexcept
void setAuthority(const QString &authority, ParsingMode mode)
QMultiMap< QAnyStringView, Cookie > cookies() const
QString addressString() const
Headers headers() const noexcept
bool isGet() const noexcept
void setScheme(const QString &scheme)
The Cutelyst namespace holds all public Cutelyst API.
const Key & key() const const
QStringList args() const noexcept
QJsonObject bodyJsonObject() const
QByteArrayView trimmed() const const
void setCaptures(const QStringList &captures)
qsizetype length() const const
void setArguments(const QStringList &arguments)
QJsonDocument bodyJsonDocument() const
void prepend(parameter_type value)
QHostInfo fromName(const QString &name)
ParamsMultiMap queryParameters() const
bool isPost() const noexcept
QByteArray method() const noexcept
ParamsMultiMap mangleParams(const ParamsMultiMap &args, bool append=false) const
bool xhr() const noexcept
QString fromLatin1(QByteArrayView str)
qsizetype indexOf(QByteArrayView bv, qsizetype from) const const
quint16 port() const noexcept
QStringList captures() const noexcept
QByteArray cookie(QAnyStringView name) const
void setQuery(const QString &query, ParsingMode mode)
QString queryKeywords() const
char at(qsizetype n) const const
bool isPut() const noexcept
QVariantMap bodyParametersVariant() const
void setHost(const QString &host, ParsingMode mode)
bool secure() const noexcept
bool isPatch() const noexcept
QUrl uriWith(const ParamsMultiMap &args, bool append=false) const
const_iterator constEnd() const const
const_iterator constBegin() const const
qsizetype size() const const
HostInfoError error() const const
QVariantMap queryParametersVariant() const
QString remoteUser() const noexcept
bool isHead() const noexcept
QMultiMap< QAnyStringView, Upload * > uploadsMap() const
QMultiMap< Key, T > & unite(QMultiMap< Key, T > &&other)
QString path() const noexcept
Engine * engine() const noexcept
QString hostName() const const