Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-18411

Qt 4.7.2 fails to add HTTP Authorization header and refetch after 401

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 4.8.0, 5.0.0
    • 4.7.2
    • None
    • Linux Qt App with Qt 4.7.2. Also, QtWebKit and Qt 4.7.2 DumpRenderTree

    Description

      Originally reported in

      https://bugs.webkit.org/show_bug.cgi?id=55767
      Bug 55767 - [Qt] Two http auth tests fail with Qt 4.7.2

      This seems to be a problem in Qt 4.7.2. Works just fine in 4.7.1.
      This WebKit test fails: LayoutTests/http/tests/appcache/auth.html.

      It does 3 http loads, auth.html, setup.php, and iframe.php.
      setup.php is XMLHttpRequest with username/password. Both
      setup.php and iframe.php require an HTTP Authorization header
      with user name and password to succeed. Here is load sequence
      when this works correctly.

        HTTP GET auth.html
        HTTP 200 for auth.html
        HTTP GET setup.php
        HTTP 401 Unauthorize error for setup.php
        HTTP GET setup.php again with Authorization Header
        HTTP 200 for setup.php
        HTTP GET iframe.php
        HTTP 401 Unauthorize error for iframe.php
        HTTP GET iframe.php again with Authorization Header
        HTTP 200 for iframe.php
      

      What I see when I run the Qt App below with Qt 4.7.2, is that the 2nd
      load for HTTP GET iframe does not go out. Could be that the socket
      state or authorization get out of synch, or possibly some race
      condition.

      I also see this fail differently on QtWebKit with DumpRenderTree.
      With DumpRenderTree on Qt 4.7.2, the 2nd fetch for setup.php
      fails to be issued. So it fails earlier.

      Attached is a small Qt App,xmlhttptest.tar.gz that loads the WebKit Layout test

      #include <QApplication>
      #include <QtWebKit/qwebview.h>
      
      int main(int argc, char *argv[])
      {
        QApplication a(argc, argv);
        QWebView*  pWidget = new QWebView();
        // Appache server on my ubuntu box points at the Webkit
        // LayoutTests/http/tests/appcache/auth.html test.
        //
        // ls -l /var/www/t
        // /var/www/t -> /home/jwild/dev/webkit/WebKit.2011.03.17/
      
        pWidget->setUrl(QUrl("http://localhost/t/LayoutTests/http/tests/appcache/auth.html"));
        pWidget->show();
        a.exec();
        delete pWidget;
        return 0;
      }
      

      This is not the best test since I believe it requires window.layoutTestController
      to fully display correctly. I didn't want to get into writing another test where I could have
      changed something significant, so I just traced the results on Qt 4.7.1 and 4.7.2.

      Below are the details of those traces, etc.

      Qt 4.7.1 and 4.7.2 Logs for auth.html test.

      4.7.1
      
      auth.html
      QAbstractSocket::writeData(0x9c94078 "GET /t/LayoutTests/http/tests/ap...", 359) == 359
      QAbstractSocket::readData(0x9caddc8 "HTTP/1.1 200 OK\r\nDate: Sun, 27 M...", 16384) == 766
      
      setup.php XMLHttpRequest
      QAbstractSocket::writeData(0x9c9a2a8 "GET /t/LayoutTests/http/tests/ap...", 345) == 345
      QAbstractSocket::readData(0x9c9a310 "HTTP/1.0 401 Unauthorized\r\nDate:...", 16384) == 348
      QAbstractSocket::writeData(0x9c9eca0 "GET /t/LayoutTests/http/tests/ap...", 388) == 388
      QAbstractSocket::readData(0x9c9a310 "HTTP/1.1 200 OK\r\nDate: Sun, 27 M...", 16384) == 296
      
      iframe.php
      QAbstractSocket::writeData(0x9ca6528 "GET /t/LayoutTests/http/tests/ap...", 446) == 446
      QAbstractSocket::readData(0x9caddc8 "HTTP/1.0 401 Unauthorized\r\nDate:...", 16384) == 348
      QAbstractSocket::writeData(0x9d53fe8 "GET /t/LayoutTests/http/tests/ap...", 489) == 489
      QAbstractSocket::readData(0x9caddc8 "HTTP/1.1 200 OK\r\nDate: Sun, 27 M...", 16384) == 415
      
      
      4.7.2 
      
      auth.html
      QAbstractSocket::writeData(0x9a306f0 "GET /t/LayoutTests/http/tests/ap...", 359) == 359
      QAbstractSocket::readData(0x9997b30 "HTTP/1.1 200 OK\r\nDate: Mon, 28 M...", 16384) == 766
      
      setup.php
      QAbstractSocket::writeData(0x99a8980 "GET /t/LayoutTests/http/tests/ap...", 345) == 345
      QAbstractSocket::readData(0x9a002c0 "HTTP/1.0 401 Unauthorized\r\nDate:...", 16384) == 348
      JPW: handleAuthenticateChallenge url =  "http://login:pasword@localhost/t/LayoutTests/http/tests/appcache/resources/auth/setup.php" 
      JPW: handleAuthenticateChallenge ret resend = 1 
      JPW: createAuthorization url =  "http://localhost/t/LayoutTests/http/tests/appcache/resources/auth/setup.php" 
      JPW: createAuthorization chan =  0 
      JPW: createAuthorization Authorization Header 
      QAbstractSocket::writeData(0x99edf28 "GET /t/LayoutTests/http/tests/ap...", 388) == 388
      QAbstractSocket::readData(0x9a002c0 "HTTP/1.1 200 OK\r\nDate: Mon, 28 M...", 16384) == 296
      
      iframe.php
      JPW: createAuthorization url =  "http://localhost/t/LayoutTests/http/tests/appcache/resources/auth/iframe.php" 
      JPW: createAuthorization chan =  0 
      QAbstractSocket::writeData(0x99eb878 "GET /t/LayoutTests/http/tests/ap...", 446) == 446
      QAbstractSocket::readData(0x9997b30 "HTTP/1.0 401 Unauthorized\r\nDate:...", 16384) == 348
      JPW: handleAuthenticateChallenge after socket close ret resend = 1 
      QAbstractSocket::close()
      

      And that's all she wrote. No more http activity.

      And for iframe.php it looks like it fails here.

      bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply,
                                                                      bool isProxy, bool &resend)
      {
      ...
              // - Changing values in QAuthenticator will reset the 'phase'. Therefore if it is still "Done"
              //   then nothing was filled in by the user or the cache
              // - If withCredentials has been set to false (e.g. by QtWebKit for a cross-origin XMLHttpRequest) then
              //   we need to bail out if authentication is required.
              if (priv->phase == QAuthenticatorPrivate::Done || !reply->request().withCredentials()) {
                  QNetworkReply::NetworkError errorCode =
                      isProxy
                      ? QNetworkReply::ProxyAuthenticationRequiredError
                      : QNetworkReply::AuthenticationRequiredError;
                  reply->d_func()->errorString = errorDetail(errorCode, socket);
                  emit reply->finishedWithError(errorCode, reply->d_func()->errorString);
                  // ### at this point the reply could be deleted
                  socket->close();
          qDebug() << "JPW: handleAuthenticateChallenge after socket close ret resend = 1";
                  return true;
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            phartman Peter Hartmann (closed Nokia identity) (Inactive)
            joseph.wild@nokia.com Joseph Wild
            Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes