c++qtqnetworkaccessmanagerqnetworkreplyqnetworkrequest

How do I know a QNetWorkReply comes from which proxy?


It's a HTTP request sending method. When the goal website responses, httpFinished() will be called.

void HTTPClientBase:: HttpRequestGet()
{
    network_manager.setProxy(proxy);
    QNetworkRequest network_request;

    network_request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
    network_request.setUrl(URL);


    reply = network_manager.get(network_request);
    connect(reply, SIGNAL(finished(QNetWorkReply*)), this, SLOT(httpFinished(QNetWorkReply*)));
}

void HTTPClientBase::httpFinished(QNetWorkReply* reply)
{
    // How do I know this reply comes from which proxy?
}

I can call HttpRequestGet() in a loop.

static HTTPClientBase myClient;
for(int i=0; i<20; i++)
{
  myClient.setUrl("https:\\www.google.com");
  myClient.setProxy("123.123.123.123:1234"); // The proxy changes every time in this loop.
  myClient.HttpRequestGet();
}

When HTTPClientBase::httpFinished(QNetWorkReply* reply) is called, How do I know this reply comes from which proxy? }


Solution

  • As per the QNetworkReply document, you can get the corresponding request using the member function QNetworkReply::request().

    Anyway, QNetworkRequest has not member function of setProxy.

    But if you are setting proxy for QNetworkAccessManager you can have a pointer to the corresponding manager by QNetworkReply::manager().

    Notice the connect command. finished() has no QNetworkReply* argument so your connect command will also fail and you have to change HTTPClientBase::httpFinished(QNetWorkReply* reply) to HTTPClientBase::httpFinished().

    ...
        connect(reply, SIGNAL(finished()), this, 
        SLOT(httpFinished()));
    }
    
    void HTTPClientBase::httpFinished()
    {
        QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
        if(reply){
            QNetworkAccessManager * manager = reply->manager();
            QNetworkProxy proxy = manager->proxy();
            // now you have the proxy 
        }
    
    }
    

    As you see, you have to use sender() to obtain the actual signal sender. You need to create different QNetworkAccessManager instances for each proxy you have. If you have a proxy pool, create your QNetworkAccessManager instances first and choose them according to your specific needs.

    If you don't want to create a new QNetworkAccessManager for each proxy, you can do something like this:

    void HTTPClientBase:: HttpRequestGet()
    {
        network_manager.setProxy(proxy);
        QNetworkRequest network_request;
    
        network_request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
        network_request.setUrl(URL);
    
        reply = network_manager.get(network_request);
        //new member variable: QHash<QNetworkReply*,QString> m_RequestToProxy;
        m_RequestToProxy.insert(reply,proxy);
    
        connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
    }
    
    void HTTPClientBase::httpFinished()
    {
        QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
        if(reply){
            QString proxy = m_RequestToProxy.take(reply);
            //check if proxy is valid
            //and then do whatever you want
        }
    }
    

    And another better solution is to set a property of reply and get it in slot.

    void HTTPClientBase:: HttpRequestGet()
    {
        network_manager.setProxy(proxy);
        QNetworkRequest network_request;
    
        network_request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
        network_request.setUrl(URL);
    
        reply = network_manager.get(network_request);
        reply->setProperty("_proxy_",proxy);
    
        connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
    }
    
    void HTTPClientBase::httpFinished()
    {
        QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
        if(reply){
            QVariant v_proxy = reply->property("_proxy_");
            //check if proxy is valid
            if(v_proxy.isValid()){
                 QString proxy = v_proxy.toString();
                 //and then do whatever you want
            }
    
        }
    }