8 #include "multipartformdataparser.h" 14 #include <QJsonDocument> 15 #include <QJsonObject> 20 : d_ptr(new RequestPrivate)
22 d_ptr->engineRequest = engineRequest;
28 qDeleteAll(d_ptr->uploads);
36 return d->engineRequest->remoteAddress;
44 quint32 data = d->engineRequest->remoteAddress.toIPv4Address(&ok);
48 return d->engineRequest->remoteAddress.toString();
58 if (!d->remoteHostname.isEmpty()) {
59 ret = d->remoteHostname;
65 qCDebug(CUTELYST_REQUEST) <<
"DNS lookup for the client hostname failed" 66 << d->engineRequest->remoteAddress;
71 ret = d->remoteHostname;
78 return d->engineRequest->remotePort;
86 if (!(d->parserStatus & RequestPrivate::UrlParsed)) {
88 if (d->engineRequest->serverAddress.isEmpty()) {
94 uri.
setScheme(d->engineRequest->isSecure ? QStringLiteral(
"https")
95 : QStringLiteral(
"http"));
100 if (!d->engineRequest->query.isEmpty()) {
105 d->parserStatus |= RequestPrivate::UrlParsed;
114 if (!(d->parserStatus & RequestPrivate::BaseParsed)) {
115 base = d->engineRequest->isSecure ? QStringLiteral(
"https://") : QStringLiteral(
"http://");
118 if (d->engineRequest->serverAddress.isEmpty()) {
128 d->parserStatus |= RequestPrivate::BaseParsed;
136 return d->engineRequest->path;
178 return d->engineRequest->isSecure;
190 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
213 return RequestPrivate::paramsMultiMapToVariantMap(
bodyParameters());
219 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
231 while (it != query.
constEnd() && it.
key() == key) {
241 if (!(d->parserStatus & RequestPrivate::QueryParsed)) {
244 return d->queryKeywords;
255 if (!(d->parserStatus & RequestPrivate::QueryParsed)) {
258 return d->queryParam;
267 while (it != query.
constEnd() && it.
key() == key) {
277 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
281 return d->cookies.value(name);
289 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
293 auto it = d->cookies.constFind(name);
294 while (it != d->cookies.constEnd() && it.key() == name) {
304 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
313 return d->engineRequest->headers;
319 return d->engineRequest->method;
325 return d->engineRequest->method.compare(u
"POST") == 0;
331 return d->engineRequest->method.compare(u
"GET") == 0;
337 return d->engineRequest->method.compare(u
"HEAD") == 0;
343 return d->engineRequest->method.compare(u
"PUT") == 0;
349 return d->engineRequest->method.compare(u
"PATCH") == 0;
355 return d->engineRequest->method.compare(u
"DELETE") == 0;
361 return d->engineRequest->protocol;
367 return d->engineRequest->headers.header(QStringLiteral(
"X_REQUESTED_WITH"))
368 .compare(u
"XMLHttpRequest") == 0;
374 return d->engineRequest->remoteUser;
380 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
389 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
392 return d->uploadsMap;
399 const auto range = map.equal_range(name);
400 for (
auto i = range.first; i != range.second; ++i) {
415 ret.
replace(it.key(), it.value());
443 void RequestPrivate::parseUrlQuery()
const 446 if (engineRequest->query.size()) {
448 if (engineRequest->query.indexOf(
'=') < 0) {
450 queryKeywords = Utils::decodePercentEncoding(&aux);
452 if (parserStatus & RequestPrivate::UrlParsed) {
453 queryParam = Utils::decodePercentEncoding(engineRequest->query.data(),
454 engineRequest->query.size());
458 queryParam = Utils::decodePercentEncoding(aux.
data(), aux.
size());
462 parserStatus |= RequestPrivate::QueryParsed;
465 void RequestPrivate::parseBody()
const 468 parserStatus |= RequestPrivate::BodyParsed;
472 bool sequencial = body->isSequential();
473 qint64 posOrig = body->pos();
474 if (sequencial && posOrig) {
475 qCWarning(CUTELYST_REQUEST) <<
"Can not parse sequential post body out of beginning";
476 parserStatus |= RequestPrivate::BodyParsed;
480 const QString contentTypeKey = QStringLiteral(
"CONTENT_TYPE");
481 const QString contentType = engineRequest->headers.header(contentTypeKey);
490 bodyParam = Utils::decodePercentEncoding(line.
data(), line.
size());
498 for (
Upload *upload : ups) {
499 if (upload->filename().isEmpty() &&
500 upload->headers().header(contentTypeKey).isEmpty()) {
504 uploadsMap.insert(upload->name(), upload);
520 parserStatus |= RequestPrivate::BodyParsed;
523 static inline bool isSlit(
QChar c)
525 return c == u
';' || c == u
',';
528 int findNextSplit(
const QString &text,
int from,
int length)
530 while (from < length) {
531 if (isSlit(text.
at(from))) {
539 static inline bool isLWS(
QChar c)
541 return c == u
' ' || c == u
'\t' || c == u
'\r' || c == u
'\n';
544 static int nextNonWhitespace(
const QString &text,
int from,
int length)
550 while (from < length) {
551 if (isLWS(text.
at(from)))
561 static std::pair<QString, QString> nextField(
const QString &text,
int &position)
563 std::pair<QString, QString> ret;
568 const int length = text.
length();
569 position = nextNonWhitespace(text, position, length);
571 int semiColonPosition = findNextSplit(text, position, length);
572 if (semiColonPosition < 0)
573 semiColonPosition = length;
576 if (equalsPosition < 0 || equalsPosition > semiColonPosition) {
581 int secondLength = semiColonPosition - equalsPosition - 1;
582 if (secondLength > 0) {
586 position = semiColonPosition;
590 void RequestPrivate::parseCookies()
const 592 const QString cookieString = engineRequest->headers.header(QStringLiteral(
"COOKIE"));
594 const int length = cookieString.
length();
595 while (position < length) {
596 const auto field = nextField(cookieString, position);
597 if (field.first.isEmpty()) {
603 if (field.second.isEmpty()) {
607 cookies.insert(field.first, field.second);
611 parserStatus |= RequestPrivate::CookiesParsed;
614 QVariantMap RequestPrivate::paramsMultiMapToVariantMap(
const ParamsMultiMap ¶ms)
620 ret.insert(ret.constBegin(), end.key(), end.value());
625 #include "moc_request.cpp" QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QString url(QUrl::FormattingOptions options) const const
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
Request(EngineRequest *engineRequest)
QString & append(QChar ch)
QString method() const noexcept
typename QMap< Key, T >::const_iterator constFind(const Key &key, const T &value) const const
QJsonDocument toJsonDocument() const const
QJsonArray array() const const
typename QMap< Key, T >::iterator replace(const Key &key, const T &value)
QVariant bodyData() const
bool isDelete() const noexcept
QJsonObject object() const const
QMap::const_iterator constBegin() const const
QStringList arguments() const noexcept
QJsonArray bodyJsonArray() const
QIODevice * body
The QIODevice containing the body (if any) of the request.
QString toString() const const
void setMatch(const QString &match)
QString match() const noexcept
QString protocol() const noexcept
Cutelyst Upload handles file upload request
void setPath(const QString &path, QUrl::ParsingMode mode)
ParamsMultiMap queryParams() const
ParamsMultiMap bodyParameters() const
void addQueryItem(const QString &key, const QString &value)
QVector< Upload * > uploads() const
QHostAddress address() const noexcept
void setAuthority(const QString &authority, QUrl::ParsingMode mode)
QString fromUtf8(const char *str, int size)
QString addressString() const
const Key & key() const const
QMultiMap< QString, Upload * > uploadsMap() const
Headers headers() const noexcept
bool isGet() const noexcept
QMap::const_iterator constEnd() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
ParamsMultiMap cookies() const
void setScheme(const QString &scheme)
The Cutelyst namespace holds all public Cutelyst API.
QJsonObject bodyJsonObject() const
void setCaptures(const QStringList &captures)
QStringView trimmed() const const
void setArguments(const QStringList &arguments)
QJsonDocument bodyJsonDocument() const
QVariant fromValue(const T &value)
QHostInfo fromName(const QString &name)
ParamsMultiMap queryParameters() const
bool isPost() const noexcept
ParamsMultiMap mangleParams(const ParamsMultiMap &args, bool append=false) const
bool xhr() const noexcept
QMultiMap< K, V > & unite(const QMultiMap< K, V > &other)
QStringList captures() const noexcept
QString toString() const const
const QChar at(int position) const const
void setQuery(const QString &query, QUrl::ParsingMode mode)
QString queryKeywords() const
void push_back(const T &value)
QString fromLatin1(const char *str, int size)
QString cookie(const QString &name) const
bool isPut() const noexcept
void prepend(const T &value)
QVariantMap bodyParametersVariant() const
void setHost(const QString &host, QUrl::ParsingMode mode)
bool secure() const noexcept
bool isPatch() const noexcept
QUrl uriWith(const ParamsMultiMap &args, bool append=false) const
QList::const_iterator constEnd() const const
QList::const_iterator constBegin() const const
QHostInfo::HostInfoError error() const const
QVariantMap queryParametersVariant() const
QString remoteUser() const noexcept
bool isHead() const noexcept
QString path() const noexcept
Engine * engine() const noexcept
QStringView mid(qsizetype start) const const
QString hostName() const const