8#include "multipartformdataparser.h"
14#include <QJsonDocument>
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;
76quint16 Request::port() const noexcept
79 return d->engineRequest->remotePort;
87 if (!(d->parserStatus & RequestPrivate::UrlParsed)) {
89 if (d->engineRequest->serverAddress.isEmpty()) {
95 uri.
setScheme(d->engineRequest->isSecure ? QStringLiteral(
"https")
96 : QStringLiteral(
"http"));
100 uri.
setPath(d->engineRequest->path);
102 if (!d->engineRequest->query.isEmpty()) {
107 d->parserStatus |= RequestPrivate::UrlParsed;
116 if (!(d->parserStatus & RequestPrivate::BaseParsed)) {
117 base = d->engineRequest->isSecure ? QStringLiteral(
"https://") : QStringLiteral(
"http://");
120 if (d->engineRequest->serverAddress.isEmpty()) {
127 d->parserStatus |= RequestPrivate::BaseParsed;
135 return d->engineRequest->path;
174bool Request::secure() const noexcept
177 return d->engineRequest->isSecure;
189 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
217 return RequestPrivate::paramsMultiMapToVariantMap(
bodyParameters());
223 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
235 while (it != query.
constEnd() && it.
key() == key) {
245 if (!(d->parserStatus & RequestPrivate::QueryParsed)) {
248 return d->queryKeywords;
259 if (!(d->parserStatus & RequestPrivate::QueryParsed)) {
262 return d->queryParam;
271 while (it != query.
constEnd() && it.
key() == key) {
281 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
285 return d->cookies.value(name).value;
293 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
297 for (
auto it = d->cookies.constFind(name); it != d->cookies.constEnd() && it->name == name;
307 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
316 return d->engineRequest->headers;
322 return d->engineRequest->method;
328 return d->engineRequest->method.compare(
"POST") == 0;
334 return d->engineRequest->method.compare(
"GET") == 0;
340 return d->engineRequest->method.compare(
"HEAD") == 0;
346 return d->engineRequest->method.compare(
"PUT") == 0;
352 return d->engineRequest->method.compare(
"PATCH") == 0;
358 return d->engineRequest->method.compare(
"DELETE") == 0;
364 return d->engineRequest->protocol;
370 return d->engineRequest->headers.header(
"X-Requested-With").compare(
"XMLHttpRequest") == 0;
376 return d->engineRequest->remoteUser;
382 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
391 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
394 return d->uploadsMap;
401 const auto range = map.equal_range(name);
402 for (
auto i = range.first; i != range.second; ++i) {
417 ret.
replace(it.key(), it.value());
445void RequestPrivate::parseUrlQuery()
const
448 if (engineRequest->query.size()) {
450 if (engineRequest->query.indexOf(
'=') < 0) {
452 queryKeywords = Utils::decodePercentEncoding(&aux);
454 if (parserStatus & RequestPrivate::UrlParsed) {
455 queryParam = Utils::decodePercentEncoding(engineRequest->query.data(),
456 engineRequest->query.size());
460 queryParam = Utils::decodePercentEncoding(aux.
data(), aux.
size());
464 parserStatus |= RequestPrivate::QueryParsed;
467void RequestPrivate::parseBody()
const
470 parserStatus |= RequestPrivate::BodyParsed;
474 bool sequencial = body->isSequential();
475 qint64 posOrig = body->pos();
476 if (sequencial && posOrig) {
477 qCWarning(CUTELYST_REQUEST) <<
"Can not parse sequential post body out of beginning";
478 parserStatus |= RequestPrivate::BodyParsed;
482 const QByteArray contentType = engineRequest->headers.header(
"Content-Type");
483 if (contentType.
startsWith(
"application/x-www-form-urlencoded")) {
491 bodyParam = Utils::decodePercentEncoding(line.
data(), line.
size());
493 }
else if (contentType.
startsWith(
"multipart/form-data")) {
499 for (
Upload *upload : ups) {
500 if (upload->filename().isEmpty() &&
501 upload->headers().header(
"Content-Type").isEmpty()) {
505 uploadsMap.insert(upload->name(), upload);
509 }
else if (contentType.
startsWith(
"application/cbor")) {
515 }
else if (contentType.
startsWith(
"application/json")) {
527 parserStatus |= RequestPrivate::BodyParsed;
531inline bool isSlit(
char c)
533 return c ==
';' || c ==
',';
538 while (from < length) {
539 if (isSlit(text.
at(from))) {
547inline bool isLWS(
char c)
549 return c ==
' ' || c ==
'\t' || c ==
'\r' || c ==
'\n';
558 while (from < length) {
559 if (isLWS(text.
at(from))) {
577 const int length = text.
length();
578 position = nextNonWhitespace(text, position, length);
580 int semiColonPosition = findNextSplit(text, position, length);
581 if (semiColonPosition < 0) {
582 semiColonPosition = length;
585 int equalsPosition = text.
indexOf(
'=', position);
586 if (equalsPosition < 0 || equalsPosition > semiColonPosition) {
591 int secondLength = semiColonPosition - equalsPosition - 1;
592 if (secondLength > 0) {
596 position = semiColonPosition;
601void RequestPrivate::parseCookies()
const
603 const QByteArray cookieString = engineRequest->headers.header(
"Cookie");
605 const int length = cookieString.
length();
606 while (position < length) {
607 const auto cookie = nextField(cookieString, position);
618 cookies.insert(cookie.name, cookie);
622 parserStatus |= RequestPrivate::CookiesParsed;
625QVariantMap RequestPrivate::paramsMultiMapToVariantMap(
const ParamsMultiMap ¶ms)
631 ret.insert(ret.constBegin(), end.key(), end.value());
636#include "moc_request.cpp"
QVariantMap bodyParametersVariant() const
QCborValue bodyCbor() const
QVariantMap queryParametersVariant() const
QMultiMap< QAnyStringView, Cookie > cookies() const
QString addressString() const
bool isGet() const noexcept
QString queryKeywords() const
QVector< Upload * > uploads() const
ParamsMultiMap bodyParameters() const
QJsonArray bodyJsonArray() const
bool xhr() const noexcept
QJsonObject bodyJsonObject() const
QStringList captures() const noexcept
bool isPut() const noexcept
bool isDelete() const noexcept
QMultiMap< QAnyStringView, Upload * > uploadsMap() const
QUrl uriWith(const ParamsMultiMap &args, bool append=false) const
bool isPost() const noexcept
QJsonDocument bodyJsonDocument() const
ParamsMultiMap mangleParams(const ParamsMultiMap &args, bool append=false) const
void setCaptures(const QStringList &captures)
Headers headers() const noexcept
QIODevice * body() const noexcept
ParamsMultiMap queryParameters() const
bool isPatch() const noexcept
Engine * engine() const noexcept
QByteArray cookie(QAnyStringView name) const
Request(EngineRequest *engineRequest)
bool isHead() const noexcept
void setArguments(const QStringList &arguments)
QHostAddress address() const noexcept
void setMatch(const QString &match)
Cutelyst Upload handles file upload requests.
The Cutelyst namespace holds all public Cutelyst API.
bool isEmpty() const const
qsizetype length() const const
qsizetype size() const const
bool startsWith(QByteArrayView bv) const const
char at(qsizetype n) const const
qsizetype indexOf(QByteArrayView bv, qsizetype from) const const
qsizetype length() const const
QByteArrayView sliced(qsizetype pos) const const
QByteArray toByteArray() const const
QByteArrayView trimmed() const const
QCborValue fromCbor(QCborStreamReader &reader)
QString toString() const const
QHostInfo::HostInfoError error() const const
QHostInfo fromName(const QString &name)
QString hostName() const const
QJsonArray array() const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QJsonObject object() const const
void prepend(QList::parameter_type value)
void push_back(QList::parameter_type value)
const Key & key() const const
QMultiMap::const_iterator constBegin() const const
QMultiMap::const_iterator constEnd() const const
QMultiMap::const_iterator constFind(const Key &key) const const
QMultiMap::iterator replace(const Key &key, const T &value)
QMultiMap< Key, T > & unite(QMultiMap< Key, T > &&other)
QString & append(QChar ch)
QString fromLatin1(QByteArrayView str)
QString fromUtf8(QByteArrayView str)
void setAuthority(const QString &authority, QUrl::ParsingMode mode)
void setHost(const QString &host, QUrl::ParsingMode mode)
void setPath(const QString &path, QUrl::ParsingMode mode)
void setQuery(const QString &query, QUrl::ParsingMode mode)
void setScheme(const QString &scheme)
QString url(QUrl::FormattingOptions options) const const
void addQueryItem(const QString &key, const QString &value)
QVariant fromValue(T &&value)
QJsonDocument toJsonDocument() const const