18 #include "request_p.h"
22 #include "multipartformdataparser.h"
26 #include <QJsonDocument>
28 #include <QJsonObject>
33 d_ptr(new RequestPrivate)
35 d_ptr->engineRequest = engineRequest;
41 qDeleteAll(d_ptr->uploads);
49 return d->engineRequest->remoteAddress;
57 quint32 data = d->engineRequest->remoteAddress.toIPv4Address(&ok);
61 return d->engineRequest->remoteAddress.toString();
71 if (!d->remoteHostname.isEmpty()) {
72 ret = d->remoteHostname;
78 qCDebug(CUTELYST_REQUEST) <<
"DNS lookup for the client hostname failed" << d->engineRequest->remoteAddress;
83 ret = d->remoteHostname;
87 quint16 Request::port()
const
90 return d->engineRequest->remotePort;
98 if (!(d->parserStatus & RequestPrivate::UrlParsed)) {
100 if (d->engineRequest->serverAddress.isEmpty()) {
106 uri.
setScheme(d->engineRequest->isSecure ? QStringLiteral(
"https") : QStringLiteral(
"http"));
111 if (!d->engineRequest->query.isEmpty()) {
116 d->parserStatus |= RequestPrivate::UrlParsed;
125 if (!(d->parserStatus & RequestPrivate::BaseParsed)) {
126 base = d->engineRequest->isSecure ? QStringLiteral(
"https://") : QStringLiteral(
"http://");
129 if (d->engineRequest->serverAddress.isEmpty()) {
132 base.
append(d->engineRequest->serverAddress);
139 d->parserStatus |= RequestPrivate::BaseParsed;
147 return d->engineRequest->path;
186 bool Request::secure()
const
189 return d->engineRequest->isSecure;
201 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
224 return RequestPrivate::paramsMultiMapToVariantMap(
bodyParameters());
230 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
242 while (it != query.
constEnd() && it.
key() == key) {
252 if (!(d->parserStatus & RequestPrivate::QueryParsed)) {
255 return d->queryKeywords;
266 if (!(d->parserStatus & RequestPrivate::QueryParsed)) {
269 return d->queryParam;
278 while (it != query.
constEnd() && it.
key() == key) {
288 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
292 return d->cookies.value(name);
300 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
304 auto it = d->cookies.constFind(name);
305 while (it != d->cookies.constEnd() && it.key() == name) {
315 if (!(d->parserStatus & RequestPrivate::CookiesParsed)) {
324 return d->engineRequest->headers;
330 return d->engineRequest->method;
336 return d->engineRequest->method == QStringLiteral(
"POST");
342 return d->engineRequest->method == QStringLiteral(
"GET");
348 return d->engineRequest->method == QStringLiteral(
"HEAD");
354 return d->engineRequest->method == QStringLiteral(
"PUT");
360 return d->engineRequest->method == QStringLiteral(
"PATCH");
366 return d->engineRequest->method == QStringLiteral(
"DELETE");
372 return d->engineRequest->protocol;
378 return d->engineRequest->headers.header(QStringLiteral(
"X_REQUESTED_WITH")) == QStringLiteral(
"XMLHttpRequest");
384 return d->engineRequest->remoteUser;
390 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
399 if (!(d->parserStatus & RequestPrivate::BodyParsed)) {
402 return d->uploadsMap;
409 const auto range = map.equal_range(name);
410 for (
auto i = range.first; i != range.second; ++i) {
425 ret.
replace(it.key(), it.value());
453 void RequestPrivate::parseUrlQuery()
const
456 if (engineRequest->query.size()) {
458 if (engineRequest->query.indexOf(
'=') < 0) {
460 queryKeywords = Utils::decodePercentEncoding(&aux);
462 if (parserStatus & RequestPrivate::UrlParsed) {
463 queryParam = Utils::decodePercentEncoding(engineRequest->query.data(), engineRequest->query.size());
467 queryParam = Utils::decodePercentEncoding(aux.
data(), aux.
size());
471 parserStatus |= RequestPrivate::QueryParsed;
474 void RequestPrivate::parseBody()
const
477 parserStatus |= RequestPrivate::BodyParsed;
481 bool sequencial = body->isSequential();
482 qint64 posOrig = body->pos();
483 if (sequencial && posOrig) {
484 qCWarning(CUTELYST_REQUEST) <<
"Can not parse sequential post body out of beginning";
485 parserStatus |= RequestPrivate::BodyParsed;
489 const QString contentTypeKey = QStringLiteral(
"CONTENT_TYPE");
490 const QString contentType = engineRequest->headers.header(contentTypeKey);
499 bodyParam = Utils::decodePercentEncoding(line.
data(), line.
size());
507 for (
Upload *upload : ups) {
508 if (upload->filename().isEmpty() && upload->headers().header(contentTypeKey).isEmpty()) {
512 uploadsMap.insert(upload->name(), upload);
528 parserStatus |= RequestPrivate::BodyParsed;
531 static inline bool isSlit(
QChar c)
536 int findNextSplit(
const QString &text,
int from,
int length)
538 while (from < length) {
539 if (isSlit(text.
at(from))) {
547 static inline bool isLWS(
QChar c)
552 static int nextNonWhitespace(
const QString &text,
int from,
int length)
558 while (from < length) {
559 if (isLWS(text.
at(from)))
569 static std::pair<QString, QString> nextField(
const QString &text,
int &position)
571 std::pair<QString, QString> ret;
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 if (equalsPosition < 0 || equalsPosition > semiColonPosition) {
588 ret.first = text.
mid(position, equalsPosition - position).
trimmed();
589 int secondLength = semiColonPosition - equalsPosition - 1;
590 if (secondLength > 0) {
591 ret.second = text.
mid(equalsPosition + 1, secondLength).
trimmed();
594 position = semiColonPosition;
598 void RequestPrivate::parseCookies()
const
600 const QString cookieString = engineRequest->headers.header(QStringLiteral(
"COOKIE"));
602 const int length = cookieString.
length();
603 while (position < length) {
604 const auto field = nextField(cookieString, position);
605 if (field.first.isEmpty()) {
611 if (field.second.isEmpty()) {
615 cookies.insert(field.first, field.second);
619 parserStatus |= RequestPrivate::CookiesParsed;
622 QVariantMap RequestPrivate::paramsMultiMapToVariantMap(
const ParamsMultiMap ¶ms)
628 ret.insert(ret.constBegin(), end.key(), end.value());
633 #include "moc_request.cpp"
QIODevice * body
The QIODevice containing the body (if any) of the request.
QMultiMap< QString, Upload * > uploadsMap() const
QVariantMap bodyParametersVariant() const
QVariantMap queryParametersVariant() const
QString addressString() const
QString queryKeywords() const
QVector< Upload * > uploads() const
ParamsMultiMap bodyParameters() const
QJsonArray bodyJsonArray() const
QHostAddress address() const
QJsonObject bodyJsonObject() const
QUrl uriWith(const ParamsMultiMap &args, bool append=false) const
QJsonDocument bodyJsonDocument() const
ParamsMultiMap mangleParams(const ParamsMultiMap &args, bool append=false) const
void setCaptures(const QStringList &captures)
ParamsMultiMap queryParameters() const
QStringList captures() const
QString cookie(const QString &name) const
Request(EngineRequest *engineRequest)
void setArguments(const QStringList &arguments)
void setMatch(const QString &match)
ParamsMultiMap cookies() const
Cutelyst Upload handles file upload request
The Cutelyst namespace holds all public Cutelyst API.
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(const T &value)
const Key & key() const const
QMap::const_iterator constBegin() const const
QMap::const_iterator constEnd() const const
typename QMap< Key, T >::const_iterator constFind(const Key &key, const T &value) const const
typename QMap< Key, T >::iterator replace(const Key &key, const T &value)
QMultiMap< K, V > & unite(const QMultiMap< K, V > &other)
QString & append(QChar ch)
const QChar at(int position) const const
QString fromLatin1(const char *str, int size)
QString fromUtf8(const char *str, int size)
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString mid(int position, int n) const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString trimmed() const const
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(const T &value)
QJsonDocument toJsonDocument() const const
void push_back(const T &value)