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

QWebSocket cannot handle HTTP 407 response ("Proxy Authentication Required")

    XMLWordPrintable

Details

    • 8
    • c73ee7353 (dev), 6ab5ec5b4 (6.6), 32f027816 (6.5)
    • Foundation Sprint 74, Foundation Sprint 75, Foundation Sprint 76, Foundation Sprint 77, Foundation Sprint 78, Foundations Sprint 79, Foundations Sprint 80, Foundation Sprint 81, Foundation Sprint 82, Foundation Sprint 83, Foundation Sprint 84, Foundation Sprint 85, Foundation Sprint 86, Foundation Sprint 87, Foundation Sprint 88, Foundation Sprint 89, Foundation Sprint 90, Foundation Sprint 91, Foundation Sprint 92

    Description

      Problems

      When QWebSocket makes tries to connect via a proxy that requires authentication,

      1. The proxyAuthenticationRequired() is not emitted.
      2. When the HTTP 407 response is received, QWebSocket attempts to re-connect immediately without sending authentication data.

      As a result, the authentication requirement is not detectable from C++, and the proxy server is spammed with connection attempts that will never work.

       

      Steps to reproduce

      1. Download the attached project
      2. Run the attached Python script, failingproxy.py
      3. Build and run the attached Qt project
      # failingproxy.py
      from http.server import BaseHTTPRequestHandler, HTTPServer
      from http import HTTPStatus
      
      class FailingProxy(BaseHTTPRequestHandler):
          def do_CONNECT(self):
              print("New HTTP request: CONNECT")
              self.send_response(HTTPStatus.PROXY_AUTHENTICATION_REQUIRED)
              self.send_header("Server", "Proxy")
              self.send_header("Proxy-Authenticate", "NTLM")
              self.send_header("Proxy-Authenticate", "Basic realm=\"CCProxy Authorization\"")
              self.send_header("Proxy-Connection", "Close")
              self.end_headers()
              self.close_connection = True
      
      if __name__ == "__main__":
          HOST, PORT = "localhost", 8880
      
          try:
              print(f"Starting HTTP server at {HOST}:{PORT}")
      
              with HTTPServer((HOST, PORT), FailingProxy) as server:
                  server.serve_forever()
          except KeyboardInterrupt:
              pass
      
          print("Server stopped.")
      
      // main.cpp
      #include <QCoreApplication>
      #include <QWebSocket>
      #include <QAuthenticator>
      
      class SampleClient : public QObject
      {
          Q_OBJECT
      
      public:
          SampleClient(const QUrl& wsUrl, QObject* parent = nullptr) : QObject(parent)
          {
              qDebug("Creating SampleClient");
              QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::ProxyType::HttpProxy, "localhost", 8880));
      
              auto socket = new QWebSocket(QString(), QWebSocketProtocol::Version::VersionLatest, this);
              socket->open(wsUrl);
      
              connect(socket, &QWebSocket::proxyAuthenticationRequired, this, []
              {
                  qDebug("proxyAuthenticationRequired() signal emitted");
              });
          }
      };
      
      int main(int argc, char* argv[])
      {
          QCoreApplication app(argc, argv);
          
          SampleClient client(QUrl("ws://google.com"));
          return app.exec();
      }
      
      #include "main.moc"
      

       

      Actual outcome
      Server prints:

      Starting HTTP server at localhost:8880
      New HTTP request: CONNECT
      127.0.0.1 - - [30/Dec/2022 14:11:41] "CONNECT google.com:80 HTTP/1.1" 407 -
      New HTTP request: CONNECT
      127.0.0.1 - - [30/Dec/2022 14:11:43] "CONNECT google.com:80 HTTP/1.1" 407 -
      New HTTP request: CONNECT
      127.0.0.1 - - [30/Dec/2022 14:11:45] "CONNECT google.com:80 HTTP/1.1" 407 -
      New HTTP request: CONNECT
      127.0.0.1 - - [30/Dec/2022 14:11:47] "CONNECT google.com:80 HTTP/1.1" 407 -
      New HTTP request: CONNECT
      ...
      

       

      Client prints:

      Creating SampleClient
      

       

      Expected outcome

      Client should also print "proxyAuthenticationRequired() signal emitted"

      Attachments

        Issue Links

          For Gerrit Dashboard: QTBUG-109718
          # Subject Branch Project Status CR V

          Activity

            People

              oyheskes Øystein Heskestad
              skoh-qt Sze Howe Koh
              Vladimir Minenko Vladimir Minenko
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes