Add username/password support to QNetworkRequestFactory
Task-number: QTBUG-114717 Change-Id: I8d6beb6f81668dcba59cbaee6044606fb874bad2 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
b72701a690
commit
98b240d00a
@ -349,6 +349,86 @@ void QNetworkRequestFactory::clearBearerToken()
|
||||
d->bearerToken.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the username set to this factory.
|
||||
|
||||
\sa setUserName(), clearUserName(), password()
|
||||
*/
|
||||
QString QNetworkRequestFactory::userName() const
|
||||
{
|
||||
return d->userName;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the username of this factory to \a userName.
|
||||
|
||||
The username is set in the request URL when \l request() is called.
|
||||
The QRestAccessManager / QNetworkAccessManager will attempt to use
|
||||
these credentials when the server indicates that authentication
|
||||
is required.
|
||||
|
||||
\sa userName(), clearUserName(), password()
|
||||
*/
|
||||
void QNetworkRequestFactory::setUserName(const QString &userName)
|
||||
{
|
||||
if (d->userName == userName)
|
||||
return;
|
||||
d.detach();
|
||||
d->userName = userName;
|
||||
}
|
||||
|
||||
/*!
|
||||
Clears the username set to this factory.
|
||||
*/
|
||||
void QNetworkRequestFactory::clearUserName()
|
||||
{
|
||||
if (d->userName.isEmpty())
|
||||
return;
|
||||
d.detach();
|
||||
d->userName.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the password set to this factory.
|
||||
|
||||
\sa password(), clearPassword(), userName()
|
||||
*/
|
||||
QString QNetworkRequestFactory::password() const
|
||||
{
|
||||
return d->password;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the password of this factory to \a password.
|
||||
|
||||
The password is set in the request URL when \l request() is called.
|
||||
The QRestAccessManager / QNetworkAccessManager will attempt to use
|
||||
these credentials when the server indicates that authentication
|
||||
is required.
|
||||
|
||||
\sa password(), clearPassword(), userName()
|
||||
*/
|
||||
void QNetworkRequestFactory::setPassword(const QString &password)
|
||||
{
|
||||
if (d->password == password)
|
||||
return;
|
||||
d.detach();
|
||||
d->password = password;
|
||||
}
|
||||
|
||||
/*!
|
||||
Clears the password set to this factory.
|
||||
|
||||
\sa password(), setPassword(), userName()
|
||||
*/
|
||||
void QNetworkRequestFactory::clearPassword()
|
||||
{
|
||||
if (d->password.isEmpty())
|
||||
return;
|
||||
d.detach();
|
||||
d->password.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets \a timeout used for transfers.
|
||||
|
||||
@ -471,6 +551,10 @@ QUrl QNetworkRequestFactoryPrivate::requestUrl(const QString *path,
|
||||
QUrl resultUrl = baseUrl;
|
||||
QUrlQuery resultQuery(providedQuery);
|
||||
QString basePath = baseUrl.path();
|
||||
|
||||
resultUrl.setUserName(userName);
|
||||
resultUrl.setPassword(password);
|
||||
|
||||
// Separate the path and query parameters components on the application-provided path
|
||||
const QString requestPath{providedPath.path()};
|
||||
const QUrlQuery pathQueryItems{providedPath};
|
||||
@ -518,6 +602,8 @@ bool QNetworkRequestFactoryPrivate::equals(
|
||||
#endif
|
||||
baseUrl == other.baseUrl &&
|
||||
bearerToken == other.bearerToken &&
|
||||
userName == other.userName &&
|
||||
password == other.password &&
|
||||
headers.equals(other.headers) &&
|
||||
queryParameters == other.queryParameters;
|
||||
}
|
||||
@ -541,6 +627,8 @@ QDebug operator<<(QDebug debug, const QNetworkRequestFactory &factory)
|
||||
<< ", queryParameters = " << factory.queryParameters().queryItems()
|
||||
<< ", bearerToken = " << (factory.bearerToken().isEmpty() ? "(empty)" : "(is set)")
|
||||
<< ", transferTimeout = " << factory.transferTimeout()
|
||||
<< ", userName = " << (factory.userName().isEmpty() ? "(empty)" : "(is set)")
|
||||
<< ", password = " << (factory.password().isEmpty() ? "(empty)" : "(is set)")
|
||||
#if QT_CONFIG(ssl)
|
||||
<< ", SSL configuration"
|
||||
<< (factory.sslConfiguration().isNull() ? " is not set (default)" : " is set")
|
||||
|
@ -59,6 +59,14 @@ public:
|
||||
Q_NETWORK_EXPORT void setBearerToken(const QByteArray &token);
|
||||
Q_NETWORK_EXPORT void clearBearerToken();
|
||||
|
||||
Q_NETWORK_EXPORT QString userName() const;
|
||||
Q_NETWORK_EXPORT void setUserName(const QString &userName);
|
||||
Q_NETWORK_EXPORT void clearUserName();
|
||||
|
||||
Q_NETWORK_EXPORT QString password() const;
|
||||
Q_NETWORK_EXPORT void setPassword(const QString &password);
|
||||
Q_NETWORK_EXPORT void clearPassword();
|
||||
|
||||
Q_NETWORK_EXPORT void setTransferTimeout(std::chrono::milliseconds timeout);
|
||||
Q_NETWORK_EXPORT std::chrono::milliseconds transferTimeout() const;
|
||||
|
||||
|
@ -42,6 +42,8 @@ public:
|
||||
QUrl baseUrl;
|
||||
QHttpHeaders headers;
|
||||
QByteArray bearerToken;
|
||||
QString userName;
|
||||
QString password;
|
||||
QUrlQuery queryParameters;
|
||||
std::chrono::milliseconds transferTimeout{0};
|
||||
};
|
||||
|
@ -25,6 +25,7 @@ private Q_SLOTS:
|
||||
void bearerToken();
|
||||
void operators();
|
||||
void timeout();
|
||||
void userInfo();
|
||||
|
||||
private:
|
||||
const QUrl url1{u"http://foo.io"_s};
|
||||
@ -335,5 +336,31 @@ void tst_QNetworkRequestFactory::timeout()
|
||||
QCOMPARE(request.transferTimeoutAsDuration(), timeout);
|
||||
}
|
||||
|
||||
void tst_QNetworkRequestFactory::userInfo()
|
||||
{
|
||||
QNetworkRequestFactory factory;
|
||||
QVERIFY(factory.userName().isEmpty());
|
||||
QVERIFY(factory.password().isEmpty());
|
||||
|
||||
const auto uname = u"a_username"_s;
|
||||
const auto password = u"a_password"_s;
|
||||
factory.setUserName(uname);
|
||||
QCOMPARE(factory.userName(), uname);
|
||||
factory.setPassword(password);
|
||||
QCOMPARE(factory.password(), password);
|
||||
|
||||
// Verify that debug output does not contain password
|
||||
QString debugOutput;
|
||||
QDebug debug(&debugOutput);
|
||||
debug << factory;
|
||||
QVERIFY(debugOutput.contains("password = (is set)"));
|
||||
QVERIFY(!debugOutput.contains(password));
|
||||
|
||||
factory.clearUserName();
|
||||
factory.clearPassword();
|
||||
QVERIFY(factory.userName().isEmpty());
|
||||
QVERIFY(factory.password().isEmpty());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QNetworkRequestFactory)
|
||||
#include "tst_qnetworkrequestfactory.moc"
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <QtNetwork/qrestaccessmanager.h>
|
||||
#include <QtNetwork/qauthenticator.h>
|
||||
#include <QtNetwork/qnetworkreply.h>
|
||||
#include <QtNetwork/qnetworkrequestfactory.h>
|
||||
#include <QtNetwork/qrestreply.h>
|
||||
|
||||
#include <QTest>
|
||||
@ -35,6 +36,7 @@ private slots:
|
||||
void networkRequestReply();
|
||||
void abort();
|
||||
void authentication();
|
||||
void userInfo();
|
||||
void errors();
|
||||
void body();
|
||||
void json();
|
||||
@ -513,6 +515,45 @@ void tst_QRestAccessManager::authentication()
|
||||
QCOMPARE(serverSideRequest.headers["Authorization"_ba], "Basic YV91c2VyOmFfcGFzc3dvcmQ="_ba);
|
||||
}
|
||||
|
||||
void tst_QRestAccessManager::userInfo()
|
||||
{
|
||||
// Tests setting of username and password into the request factory
|
||||
using ReplyPtr = std::unique_ptr<QRestReply, QScopedPointerDeleteLater>;
|
||||
QRestAccessManager manager;
|
||||
manager.setDeletesRepliesOnFinished(false);
|
||||
HttpTestServer server;
|
||||
QTRY_VERIFY(server.isListening());
|
||||
|
||||
QNetworkRequestFactory factory(server.url());
|
||||
factory.setUserName(u"a_user"_s);
|
||||
const auto password = u"a_password"_s;
|
||||
factory.setPassword(password);
|
||||
|
||||
HttpData serverSideRequest;
|
||||
server.setHandler([&](HttpData request, HttpData& response, ResponseControl&) {
|
||||
if (!request.headers.contains("Authorization"_ba)) {
|
||||
response.status = 401;
|
||||
response.headers.insert("WWW-Authenticate: "_ba, "Basic realm=\"secret_place\""_ba);
|
||||
} else {
|
||||
response.status = 200;
|
||||
}
|
||||
serverSideRequest = request; // store for checking later the 'Authorization' header value
|
||||
});
|
||||
|
||||
ReplyPtr reply(manager.get(factory.request()));
|
||||
QTRY_VERIFY(reply.get()->isFinished());
|
||||
QVERIFY(reply.get()->isSuccess());
|
||||
QCOMPARE(reply.get()->httpStatus(), 200);
|
||||
QCOMPARE(serverSideRequest.headers["Authorization"_ba], "Basic YV91c2VyOmFfcGFzc3dvcmQ="_ba);
|
||||
|
||||
// Verify that debug output does not contain password
|
||||
QString debugOutput;
|
||||
QDebug debug(&debugOutput);
|
||||
debug << factory;
|
||||
QVERIFY(debugOutput.contains("password = (is set)"));
|
||||
QVERIFY(!debugOutput.contains(password));
|
||||
}
|
||||
|
||||
#define VERIFY_HTTP_ERROR_STATUS(STATUS) \
|
||||
serverSideResponse.status = STATUS; \
|
||||
reply = manager.get(request); \
|
||||
|
Loading…
x
Reference in New Issue
Block a user