QNetworkAccessManager purges cookies if following redirect
-
Hello everyone, does someone know how to force QNetworkAccessManager to send back cookies even if it's following a redirect?
Seems like if it receive a 301 or 302 response and the QNetworkRequest::FollowRedirectsAttribute is set to true in the request, it actually follow the redirect but ignores all the cookies received.
Is it a bug or an exptected behaviour? -
@Jiloc
depends how you use QNetworkAccessManager.
If you reuse the same instance (or at least take over it's cookie-jar) it definitely works.
If that is the case then it depends what the server sends. -
@raven-worx I am not talking about multiple requestes. It's a problem with the single request.
If i send a request like that:
SsoNetworkManager::SsoNetworkManager(QObject *parent) : QNetworkAccessManager(parent) { connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), this, SLOT(onAuthenticationRequired(QNetworkReply*,QAuthenticator*))); connect(this, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*))); } void SsoNetworkManager::onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *auth) { auth->setUser(QString("test")); auth->setPassword(QString("test")); } void SsoNetworkManager::onFinished(QNetworkReply *reply){ qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); } ... SsoNetworkManager nam; QNetworkRequest request("http://127.0.0.1:8000/admin/"); request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); nam.get(request); ...
The server works like that
- 302 and redirects to /admin/login/
- 401 asking for basic auth
- 302 , sets cookie sessionid and redirects to /admin/
- reads sessionid and replies with 200
If i follow this procedure with the browser or with python it works like a charm.
If i try this with the code above the server does't receive any cookie, they are always empty, and the client enters in a redirect loop.I just tried to remove the QNetworkRequest::FollowRedirectsAttribute and manually handle the redirects. This way it stores the cookies, but I don't want to keep doing it manually.
To me it seems a bug
-
Taking a look at the source code of /network/access/qnetworkreplyhttpimpl.cpp in qtbase, it looks like that when a redirect request is created it just take care of copying the original request changing the url, it doesn't take into account any other information got from the response.
QNetworkRequest QNetworkReplyHttpImplPrivate::createRedirectRequest(const QNetworkRequest &originalRequest, const QUrl &url, int maxRedirectsRemaining) { QNetworkRequest newRequest(originalRequest); newRequest.setUrl(url); newRequest.setMaximumRedirectsAllowed(maxRedirectsRemaining); return newRequest; }
-
@Jiloc
this doesn't mean anything.
Important is what happens before/after this method by the QNetworkAccessManager. If it stores the cookies from the reply or not.
Means the reply isn't responsible for storing the cookies of course.
I don't have time to check the sources right now. -
@raven-worx
You are right, I investigated further.to set cookies QNetworkAccessManager uses
request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies));
Anyway the QNetworkAccessManager uses the CookieJar only inside this method:
QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &originalReq, QIODevice *outgoingData) { //... }
Which is only called by the public methods "head, get, post, put, deleteResources and sendCustomRequest" which are not called to send the redirected requests.
They are internally handled, the redirection process is completely transparent to the QNetworkAccessManager.
-
@Jiloc
then probably it's the best to open a new Qt bugreport -
@raven-worx
I did as you suggested https://bugreports.qt.io/browse/QTBUG-63313 . Hope the bug report is properly documented