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 <edward.welbourne@qt.io>
This commit is contained in:
Timur Pocheptsov 2017-09-28 14:40:02 +02:00
parent 1cb5943aee
commit 9e268185bb

View File

@ -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";