From 9e268185bbb39285ee087868f9d904d7c9f6fe61 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 28 Sep 2017 14:40:02 +0200 Subject: HTTP/2 protocol handler: set the redirect URL on reply For HTTP/1 it's done when no data expected and response headers received - protocol handler emits channel->allDone which handles the status code and sets (if needed) a redirectUrl. HTTP/2 protocol handler cannot emit allDone (it has many requests multiplexed and actually cannot say allDone yet). So we set a redirect url if we have the corresponding status code and found 'location' header. Before it's too late. Task-number: QTBUG-63471 Change-Id: Icfa871fb999e676650d62c45a20e689596da4028 Reviewed-by: Edward Welbourne --- src/network/access/qhttp2protocolhandler.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index 5032f6017f..cf1be28337 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -1042,12 +1042,18 @@ void QHttp2ProtocolHandler::updateStream(Stream &stream, const HPack::HttpHeader } const auto httpReplyPrivate = httpReply->d_func(); + int statusCode = 0; for (const auto &pair : headers) { const auto &name = pair.name; auto value = pair.value; if (name == ":status") { - httpReply->setStatusCode(value.left(3).toInt()); + // TODO: part of this code copies what SPDY does when processing + // headers. It would be nice to re-factor HTTP/2 protocol handler + // to make it more strict in extracting things. For example, the + // status code below ... yeah, should be an integer, right? + statusCode = value.left(3).toInt(); + httpReply->setStatusCode(statusCode); httpReplyPrivate->reasonPhrase = QString::fromLatin1(value.mid(4)); } else if (name == ":version") { httpReplyPrivate->majorVersion = value.at(5) - '0'; @@ -1058,6 +1064,17 @@ void QHttp2ProtocolHandler::updateStream(Stream &stream, const HPack::HttpHeader if (ok) httpReply->setContentLength(length); } else { + if (statusCode > 300 && statusCode <= 308 && name == "location") { + // For HTTP/1 'location' is handled (and redirect URL set) when + // a protocol handler emits channel->allDone(). Http/2 protocol + // handler never emits allDone, since we have many requests + // multiplexed in one channel at any moment and we are never + // done :) So it's time to extract location. + const QUrl redirectUrl(QUrl::fromEncoded(value)); + if (redirectUrl.isValid()) + httpReply->setRedirectUrl(redirectUrl); + } + QByteArray binder(", "); if (name == "set-cookie") binder = "\n"; -- cgit v1.2.3