Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QWebSocket refuses to follow HTTP 301 Redirect



  • Hello,

    I am trying to use QWebSockets to connect to a service that is located behind an nginx balancer.
    Nginx is returning HTTP 301 redirects during the HTTP handshake, and this is breaking the QWebSocket connection.

    I would like to have my QWebSocket automatically follow the redirect so that it will be able to connect with the service; however, I can't seem to get it working, or find any documentation on how to accomplish this.

    The QNetworkRequest allows you to follow redirects, so I attempted to create a QWebSocket based on this, but was unsuccessful.

    QWebSocket *socket = new QWebSocket;
    std::string url = "someUrlThatGoesThroughNGINX";
    
    QNetworkRequest nr(QUrl::fromUserInput(QString::fromStdString("ws://" + url)));
    nr.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
    nr.setRawHeader(QByteArray("Connection"), QByteArray("Upgrade"));
    nr.setRawHeader(QByteArray("Upgrade"), QByteArray("WebSocket"));
    
    socket->open(nr); // This throws QWebSocket::error with socket->errorString() = QWebSocketPrivate:processHandshake: Unhandled http status code: 301 (Moved Permanently).
    

    I know nginx is working properly because normal HTTP requests work fine, I just can't seem to get it working with a QWebSocket.

    Any ideas?



  • It turned out that nginx was returning 301 while trying to redirect from http to https (it had nothing to do with the endpoint itself thankfully).

    I changed my websocket URL to "wss://" + url and that seemed to resolve the issue for me.

    For future readers, if you are still experiencing errors with a Secure WebSocket you may want to adjust the SSL configuration of the QWebSocket.

    QSslConfiguration sslConfig;
    
    sslConfig.setProtocol(whateverProtocolYouDesire);
    // Set additional properties of sslConfig here...
    
    socket->setSslConfiguration(sslConfig);
    


  • Some thoughts.

    QWebSocket::open() is able to do the handshake from a supplied QUrl. No need to handle the connection upgrade yourself.

    In case you supply a QUrl and still get the unexpected HTTP 301, can't you get the Location response header from the previous QNetworkRequest's reply and use that URL instead? It's even permanent. You don't need to figure it out on each run.



  • It turned out that nginx was returning 301 while trying to redirect from http to https (it had nothing to do with the endpoint itself thankfully).

    I changed my websocket URL to "wss://" + url and that seemed to resolve the issue for me.

    For future readers, if you are still experiencing errors with a Secure WebSocket you may want to adjust the SSL configuration of the QWebSocket.

    QSslConfiguration sslConfig;
    
    sslConfig.setProtocol(whateverProtocolYouDesire);
    // Set additional properties of sslConfig here...
    
    socket->setSslConfiguration(sslConfig);
    

Log in to reply