363 lines
10 KiB
C++
363 lines
10 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
** Contact: http://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL21$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at http://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
** following information to ensure the GNU Lesser General Public License
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** As a special exception, The Qt Company gives you certain additional
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "qhttpnetworkrequest_p.h"
|
|
#include "private/qnoncontiguousbytedevice_p.h"
|
|
|
|
#ifndef QT_NO_HTTP
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op,
|
|
QHttpNetworkRequest::Priority pri, const QUrl &newUrl)
|
|
: QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0),
|
|
autoDecompress(false), pipeliningAllowed(false), spdyAllowed(false),
|
|
withCredentials(true), preConnect(false), followRedirect(false), redirectCount(0)
|
|
{
|
|
}
|
|
|
|
QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequestPrivate &other)
|
|
: QHttpNetworkHeaderPrivate(other)
|
|
{
|
|
operation = other.operation;
|
|
priority = other.priority;
|
|
uploadByteDevice = other.uploadByteDevice;
|
|
autoDecompress = other.autoDecompress;
|
|
pipeliningAllowed = other.pipeliningAllowed;
|
|
spdyAllowed = other.spdyAllowed;
|
|
customVerb = other.customVerb;
|
|
withCredentials = other.withCredentials;
|
|
ssl = other.ssl;
|
|
preConnect = other.preConnect;
|
|
followRedirect = other.followRedirect;
|
|
redirectCount = other.redirectCount;
|
|
}
|
|
|
|
QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate()
|
|
{
|
|
}
|
|
|
|
bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &other) const
|
|
{
|
|
return QHttpNetworkHeaderPrivate::operator==(other)
|
|
&& (operation == other.operation)
|
|
&& (priority == other.priority)
|
|
&& (uploadByteDevice == other.uploadByteDevice)
|
|
&& (autoDecompress == other.autoDecompress)
|
|
&& (pipeliningAllowed == other.pipeliningAllowed)
|
|
&& (spdyAllowed == other.spdyAllowed)
|
|
// we do not clear the customVerb in setOperation
|
|
&& (operation != QHttpNetworkRequest::Custom || (customVerb == other.customVerb))
|
|
&& (withCredentials == other.withCredentials)
|
|
&& (ssl == other.ssl)
|
|
&& (preConnect == other.preConnect);
|
|
}
|
|
|
|
QByteArray QHttpNetworkRequest::methodName() const
|
|
{
|
|
switch (d->operation) {
|
|
case QHttpNetworkRequest::Get:
|
|
return "GET";
|
|
case QHttpNetworkRequest::Head:
|
|
return "HEAD";
|
|
case QHttpNetworkRequest::Post:
|
|
return "POST";
|
|
case QHttpNetworkRequest::Options:
|
|
return "OPTIONS";
|
|
case QHttpNetworkRequest::Put:
|
|
return "PUT";
|
|
case QHttpNetworkRequest::Delete:
|
|
return "DELETE";
|
|
case QHttpNetworkRequest::Trace:
|
|
return "TRACE";
|
|
case QHttpNetworkRequest::Connect:
|
|
return "CONNECT";
|
|
case QHttpNetworkRequest::Custom:
|
|
return d->customVerb;
|
|
default:
|
|
break;
|
|
}
|
|
return QByteArray();
|
|
}
|
|
|
|
QByteArray QHttpNetworkRequest::uri(bool throughProxy) const
|
|
{
|
|
QUrl::FormattingOptions format(QUrl::RemoveFragment | QUrl::RemoveUserInfo | QUrl::FullyEncoded);
|
|
|
|
// for POST, query data is sent as content
|
|
if (d->operation == QHttpNetworkRequest::Post && !d->uploadByteDevice)
|
|
format |= QUrl::RemoveQuery;
|
|
// for requests through proxy, the Request-URI contains full url
|
|
if (!throughProxy)
|
|
format |= QUrl::RemoveScheme | QUrl::RemoveAuthority;
|
|
QUrl copy = d->url;
|
|
if (copy.path().isEmpty())
|
|
copy.setPath(QStringLiteral("/"));
|
|
QByteArray uri = copy.toEncoded(format);
|
|
return uri;
|
|
}
|
|
|
|
QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request, bool throughProxy)
|
|
{
|
|
QList<QPair<QByteArray, QByteArray> > fields = request.header();
|
|
QByteArray ba;
|
|
ba.reserve(40 + fields.length()*25); // very rough lower bound estimation
|
|
|
|
ba += request.methodName();
|
|
ba += ' ';
|
|
ba += request.uri(throughProxy);
|
|
|
|
ba += " HTTP/";
|
|
ba += QByteArray::number(request.majorVersion());
|
|
ba += '.';
|
|
ba += QByteArray::number(request.minorVersion());
|
|
ba += "\r\n";
|
|
|
|
QList<QPair<QByteArray, QByteArray> >::const_iterator it = fields.constBegin();
|
|
QList<QPair<QByteArray, QByteArray> >::const_iterator endIt = fields.constEnd();
|
|
for (; it != endIt; ++it) {
|
|
ba += it->first;
|
|
ba += ": ";
|
|
ba += it->second;
|
|
ba += "\r\n";
|
|
}
|
|
if (request.d->operation == QHttpNetworkRequest::Post) {
|
|
// add content type, if not set in the request
|
|
if (request.headerField("content-type").isEmpty() && ((request.d->uploadByteDevice && request.d->uploadByteDevice->size() > 0) || request.d->url.hasQuery())) {
|
|
//Content-Type is mandatory. We can't say anything about the encoding, but x-www-form-urlencoded is the most likely to work.
|
|
//This warning indicates a bug in application code not setting a required header.
|
|
//Note that if using QHttpMultipart, the content-type is set in QNetworkAccessManagerPrivate::prepareMultipart already
|
|
qWarning("content-type missing in HTTP POST, defaulting to application/x-www-form-urlencoded. Use QNetworkRequest::setHeader() to fix this problem.");
|
|
ba += "Content-Type: application/x-www-form-urlencoded\r\n";
|
|
}
|
|
if (!request.d->uploadByteDevice && request.d->url.hasQuery()) {
|
|
QByteArray query = request.d->url.query(QUrl::FullyEncoded).toLatin1();
|
|
ba += "Content-Length: ";
|
|
ba += QByteArray::number(query.size());
|
|
ba += "\r\n\r\n";
|
|
ba += query;
|
|
} else {
|
|
ba += "\r\n";
|
|
}
|
|
} else {
|
|
ba += "\r\n";
|
|
}
|
|
return ba;
|
|
}
|
|
|
|
|
|
// QHttpNetworkRequest
|
|
|
|
QHttpNetworkRequest::QHttpNetworkRequest(const QUrl &url, Operation operation, Priority priority)
|
|
: d(new QHttpNetworkRequestPrivate(operation, priority, url))
|
|
{
|
|
}
|
|
|
|
QHttpNetworkRequest::QHttpNetworkRequest(const QHttpNetworkRequest &other)
|
|
: QHttpNetworkHeader(other), d(other.d)
|
|
{
|
|
}
|
|
|
|
QHttpNetworkRequest::~QHttpNetworkRequest()
|
|
{
|
|
}
|
|
|
|
QUrl QHttpNetworkRequest::url() const
|
|
{
|
|
return d->url;
|
|
}
|
|
void QHttpNetworkRequest::setUrl(const QUrl &url)
|
|
{
|
|
d->url = url;
|
|
}
|
|
|
|
bool QHttpNetworkRequest::isSsl() const
|
|
{
|
|
return d->ssl;
|
|
}
|
|
void QHttpNetworkRequest::setSsl(bool s)
|
|
{
|
|
d->ssl = s;
|
|
}
|
|
|
|
bool QHttpNetworkRequest::isPreConnect() const
|
|
{
|
|
return d->preConnect;
|
|
}
|
|
void QHttpNetworkRequest::setPreConnect(bool preConnect)
|
|
{
|
|
d->preConnect = preConnect;
|
|
}
|
|
|
|
bool QHttpNetworkRequest::isFollowRedirects() const
|
|
{
|
|
return d->followRedirect;
|
|
}
|
|
|
|
void QHttpNetworkRequest::setFollowRedirects(bool followRedirect)
|
|
{
|
|
d->followRedirect = followRedirect;
|
|
}
|
|
|
|
int QHttpNetworkRequest::redirectCount() const
|
|
{
|
|
return d->redirectCount;
|
|
}
|
|
|
|
void QHttpNetworkRequest::setRedirectCount(int count)
|
|
{
|
|
d->redirectCount = count;
|
|
}
|
|
|
|
qint64 QHttpNetworkRequest::contentLength() const
|
|
{
|
|
return d->contentLength();
|
|
}
|
|
|
|
void QHttpNetworkRequest::setContentLength(qint64 length)
|
|
{
|
|
d->setContentLength(length);
|
|
}
|
|
|
|
QList<QPair<QByteArray, QByteArray> > QHttpNetworkRequest::header() const
|
|
{
|
|
return d->fields;
|
|
}
|
|
|
|
QByteArray QHttpNetworkRequest::headerField(const QByteArray &name, const QByteArray &defaultValue) const
|
|
{
|
|
return d->headerField(name, defaultValue);
|
|
}
|
|
|
|
void QHttpNetworkRequest::setHeaderField(const QByteArray &name, const QByteArray &data)
|
|
{
|
|
d->setHeaderField(name, data);
|
|
}
|
|
|
|
QHttpNetworkRequest &QHttpNetworkRequest::operator=(const QHttpNetworkRequest &other)
|
|
{
|
|
d = other.d;
|
|
return *this;
|
|
}
|
|
|
|
bool QHttpNetworkRequest::operator==(const QHttpNetworkRequest &other) const
|
|
{
|
|
return d->operator==(*other.d);
|
|
}
|
|
|
|
QHttpNetworkRequest::Operation QHttpNetworkRequest::operation() const
|
|
{
|
|
return d->operation;
|
|
}
|
|
|
|
void QHttpNetworkRequest::setOperation(Operation operation)
|
|
{
|
|
d->operation = operation;
|
|
}
|
|
|
|
QByteArray QHttpNetworkRequest::customVerb() const
|
|
{
|
|
return d->customVerb;
|
|
}
|
|
|
|
void QHttpNetworkRequest::setCustomVerb(const QByteArray &customVerb)
|
|
{
|
|
d->customVerb = customVerb;
|
|
}
|
|
|
|
QHttpNetworkRequest::Priority QHttpNetworkRequest::priority() const
|
|
{
|
|
return d->priority;
|
|
}
|
|
|
|
void QHttpNetworkRequest::setPriority(Priority priority)
|
|
{
|
|
d->priority = priority;
|
|
}
|
|
|
|
bool QHttpNetworkRequest::isPipeliningAllowed() const
|
|
{
|
|
return d->pipeliningAllowed;
|
|
}
|
|
|
|
void QHttpNetworkRequest::setPipeliningAllowed(bool b)
|
|
{
|
|
d->pipeliningAllowed = b;
|
|
}
|
|
|
|
bool QHttpNetworkRequest::isSPDYAllowed() const
|
|
{
|
|
return d->spdyAllowed;
|
|
}
|
|
|
|
void QHttpNetworkRequest::setSPDYAllowed(bool b)
|
|
{
|
|
d->spdyAllowed = b;
|
|
}
|
|
|
|
bool QHttpNetworkRequest::withCredentials() const
|
|
{
|
|
return d->withCredentials;
|
|
}
|
|
|
|
void QHttpNetworkRequest::setWithCredentials(bool b)
|
|
{
|
|
d->withCredentials = b;
|
|
}
|
|
|
|
void QHttpNetworkRequest::setUploadByteDevice(QNonContiguousByteDevice *bd)
|
|
{
|
|
d->uploadByteDevice = bd;
|
|
}
|
|
|
|
QNonContiguousByteDevice* QHttpNetworkRequest::uploadByteDevice() const
|
|
{
|
|
return d->uploadByteDevice;
|
|
}
|
|
|
|
int QHttpNetworkRequest::majorVersion() const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
int QHttpNetworkRequest::minorVersion() const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
#endif
|
|
|