pasagir
pasagirAug. 16, 2018, 12:48 p.m.

HTTP QNetworkAccessManager

C++, Qt, QNetworkAccessManager, http




Пытаюсь создать post() запрос -залогиниться на сервере и получить cookie. Велосипед изобретать не стал - все сделалкак по книге:  

 QNetworkAccessManager *manager;

    manager = new QNetworkAccessManager ();

    QNetworkRequest req;

    req.setUrl(QUrl("http://********.by/login"));
    req.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");


    //get-запрос идет нормально
    //manager->get(QNetworkRequest(QUrl("http://env-2764881.mycloud.by/login")));

    QByteArray postData;
    postData.append("email=*******@gmail.com&");
    postData.append("password=******");
    //Создаем QCookieJar:
    manager->setCookieJar(new QNetworkCookieJar(manager));

    connect (manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(replyFinished(QNetworkReply *)));
  manager->post(req, postData);  
СЛОТ


void Downloader::replyFinished(QNetworkReply *reply)
{
    qDebug()<<"answer";

    if(reply->error())
    {
          qDebug()<<"ERROR";
          qDebug()<<reply->errorString();
    }
    else
    {
           qDebug()<<"reply->readAll()\n"<<reply->readAll();       
    }
    reply->deleteLater();
}

Как получить html-код страницы после входа?
We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

12
Evgenii Legotckoi
  • Aug. 23, 2018, 4:05 a.m.

Добрый день

Надеюсь, что не сильно поздно отвечаю (я в отпуске был, и через неделю также продолжу отпуск), но тем не менее
Возможно, стоит просто включить возможность перенаправления в запросе, тогда может быть автоматический переход на страницу после авторизации.
QNetworkRequest request;    // Отправляемый запрос
request.setUrl(url);        // Устанавлвиваем URL в запрос
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true)


    pasagir
    • Aug. 23, 2018, 8:19 a.m.

    Спасибо, ща попробую

      pasagir
      • Aug. 23, 2018, 11:05 a.m.

      Наверное я куду-то не туда вставляю

      request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true)

      код страницы не выдает, нашел вот такой способ. В слот пишем следующий код
      void Downloader::replyFinished(QNetworkReply *reply)
      {
          if(reply->error() == QNetworkReply::NoError)
          {
              //Получаем код статуса http
              int v = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
              qDebug()<<"v  '"<<v<<"'";
      if (v >= 200 && v < 300) //Успешно { //Получаем окончательный ответ QString replyText = reply->readAll(); qDebug()<<"qwer\n"<<replyText; } else if (v >= 300 && v < 400) //Перенаправление { qDebug()<<"asdf\n"; //Получаем URL перенаправления QUrl newUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); //Поскольку URL перенаправления может быть относительным, //мы должны использовать предыдущий, чтобы его разрешить newUrl = reply->url().resolved(newUrl); QNetworkAccessManager *manager = reply->manager(); QNetworkRequest redirection(newUrl); QNetworkReply *newReply = manager->get(redirection); return; //Для вызова следующего запроса } } else { //Error qDebug()<<reply->errorString(); } }

      сначала появляется код страницы до регистрации, потом код страницы после регистрации.
      З.Ы. Извините, что отвлек от отпуска


        Evgenii Legotckoi
        • Aug. 27, 2018, 3:34 a.m.

        Да, ваш вариант тоже может быть вполне подходящим под задачу.

        Только проверку кодов я бы сделал через switch case, иначе можно словить вместо редиректа какой-нибудь мусор или ошибку.
        switch (v)
        {
        	case 200:
        	case 201:
        	{
        		 //Получаем окончательный ответ
        		QString replyText = reply->readAll();
        		qDebug()<<"qwer\n"<<replyText;
        		break;
        	}
        	case 300:
        	case 301:
        	case 302:
        	{
        		qDebug()<<"asdf\n";
        		//Получаем URL перенаправления
        		QUrl newUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
        		//Поскольку URL перенаправления может быть относительным,
        		//мы должны использовать предыдущий, чтобы его разрешить
        		newUrl = reply->url().resolved(newUrl);
        
        		QNetworkAccessManager *manager = reply->manager();
        		QNetworkRequest redirection(newUrl);
        		QNetworkReply *newReply = manager->get(redirection);
        
        		return; //Для вызова следующего запроса
        	}
        }

        Я думаю, что обрабатывать нужно конкретные редиректы, а не весь диапазон этих редиректов. Неизвестно что может быть например в случае редиректа 306...
          pasagir
          • Aug. 27, 2018, 4:31 a.m.

          Спасибо

            pasagir
            • Aug. 31, 2018, 5:26 a.m.

            Еще один вопрос. Как в указанном примере на сервер можно передать несколько строк?


              Evgenii Legotckoi
              • Sept. 1, 2018, 3:55 a.m.

              Вообще да, почему нет?

              Просто что именно под строками подразумеваете?
              Также всё зависит от того, как написано API на сервере.
              Если вы там REST API написали, которое может разобрать массив строк из JSON, то можно просто подготовить этот массив в JSON и отправить всё пачкой.


                pasagir
                • Sept. 1, 2018, 3:51 p.m.

                Я пытаюсь получить cookies  и вставить их в повторный запрос. Пробую через QNeworkCookieJar, но пока не получается. Может есть какой пример?

                  Evgenii Legotckoi
                  • Sept. 5, 2018, 3:18 a.m.

                  К сожалению с куками не было повода поработать. Так что пока такой информации на сайте нет о QNeworkCookieJar

                    pasagir
                    • Sept. 14, 2018, 8:54 a.m.
                    • (edited)

                    разобрался - просто полученные cookies пихаем в наш, уже существующий  слот, правда, программа зацикливается, но это решаемо. Кстати, чем лучше пользоваться для прекращения работы программы при получения ответа от сервера?

                    void Downloader::replyFinished(QNetworkReply *reply)
                    {   
                        QByteArray data;//Для куков
                        QByteArray answ;//сюда пишем ответ от сервера
                        QVariant varCookies;//для куков
                        QList<QNetworkCookie> cookies;//контейнер с куками
                    
                        static int counter = 0;//Просто счетчик чтоб видеть приходит ли ответ и с какого раза
                    
                        if(counter < 1)//Чтобы лишний раз не забирать хедеры
                        {
                            varCookies = reply->header(QNetworkRequest::SetCookieHeader);//Получаем куки
                            cookies = varCookies.value<QList<QNetworkCookie>>();//Пихаем куки в контейнер
                    
                    
                            
                            foreach (QNetworkCookie c, cookies)//Тут переделываем куки в из QNetworkCookie в QBayteArray
                            {
                                data.append(c.toRawForm());//Получаем значения cookies из списка
                                data.append(';');
                            }
                    
                    //        qDebug()<<"data "<<data;
                    //        qDebug()<<"varCookies"<<varCookies;
                    //        qDebug()<<"cookies"<<cookies;
                        }
                        static QByteArray zxcv = data.mid(0, 43);//Копируем  JSESSIONID - не нужно (просто посмотреть)
                        //qDebug()<<"cookieArray "<<zxcv;
                        QList<QByteArray> reqHeaderReplay = reply->rawHeaderList();//Сюда пишутся все хедеры полученные от сервера
                        
                        QByteArray reqName, reqValue;//Имя хедера и его значение
                        foreach(reqName, reqHeaderReplay)
                        {
                            reqValue = reply->rawHeader(reqName);//Получаем имя хедера и его значения
                            //qDebug()<<reqName<<", "<<reqValue;
                        }
                    
                        if(reply->error() == QNetworkReply::NoError)
                        {
                            qDebug()<<counter<<"--------------------------------------------";
                            QNetworkRequest requ;//Создаем еще один запрос
                            QString sUrlN = "http://novy-adress.by/message";//Новый адрес
                            requ.setUrl(sUrlN);
                            requ.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
                            requ.setRawHeader(reqName, reqValue);
                            //qDebug()<<"zxcv"<<zxcv;
                            QByteArray postDat;//Новый пост запрос
                            postDat.append("param1=123&param2=456");//Параметры которые нужно передать
                    
                            manager->post(requ, postDat);//Наш новый post-запрос
                            qDebug()<<"post-1--post";
                            answ = reply->readAll();//Ловим ответ
                            qDebug()<<"answer"<<counter<<answ;
                    
                            counter++;
                    
                            //Получаем код статуса http
                            int v = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
                            qDebug()<<"v  '"<<v<<"'";
                            switch (v)
                            {
                                case 200:
                                case 201:
                                {
                    
                                    //Получаем окончательный ответ
                                    QString replyText = reply->readAll();//Тут получаем HTML-страницы - осталось с прошлого раза))
                                    qDebug()<<"200-201\n"<<replyText;
                                    //QVariant varCookies = reply->header(QNetworkRequest::SetCookieHeader);
                    
                                    break;
                                }
                                case 300:
                                case 301:
                                case 302:
                                {
                                    qDebug()<<"300-301-302\n";
                                    //Получаем URL перенаправления
                                    QUrl newUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
                                    //Поскольку URL перенаправления может быть относительным,
                                    //мы должны использовать предыдущий, чтобы его разрешить
                                    newUrl = reply->url().resolved(newUrl);
                    
                                    QNetworkAccessManager *manager = reply->manager();
                                    QNetworkRequest redirection(newUrl);
                                    QNetworkReply *newReply = manager->get(redirection);
                    
                    //                qDebug()<<"cookies300"<<cookies;
                    //                qDebug()<<"newReply"<<newReply;
                                    return; //Для вызова следующего запроса
                                }
                            }
                        }
                        else
                        {
                            //Error
                            qDebug()<<reply->errorString();
                        }
                    
                        //qDebug()<<"counter"<<counter;
                    
                        reply->deleteLater();
                        if(answ != "")
                        {
                            return;
                        }
                    }
                      Evgenii Legotckoi
                      • Sept. 15, 2018, 6:23 a.m.

                      Вообще, для выхода из программы можно использовать и доступ к инстансу приложения, через qApp->quit()

                      Также, если у вас есть главное окно приложения, то можно просто его закрыть.

                      mainwindow->close();

                      В данном случае, когда не остаётся активных окон, то приложение завершается.

                      И замечания по вашему коду

                      Вот это кусок кода бесполезный. Вы в любом случае выходите из метода.

                      if(answ != "")
                      {
                          return;
                      }

                      Также рекомендую делать проверку так

                      if(!answ.isEmpty())
                      {
                          return;
                      }

                      Это сделает более полную проверку на наличие символов в QByteArray.

                      Не используйте foreach, подробнее в этой статье



                        pasagir
                        • Sept. 15, 2018, 8:03 a.m.

                        Спасибо

                          Comments

                          Only authorized users can post comments.
                          Please, Log in or Sign up
                          МВ

                          Qt - Test 001. Signals and slots

                          • Result:68points,
                          • Rating points-1
                          ЛС

                          C++ - Test 001. The first program and data types

                          • Result:53points,
                          • Rating points-4
                          АА

                          C++ - Test 001. The first program and data types

                          • Result:60points,
                          • Rating points-1
                          Last comments
                          ИМ
                          Игорь МаксимовOct. 5, 2024, 7:51 a.m.
                          Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                          d
                          dblas5July 5, 2024, 11:02 a.m.
                          QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                          k
                          kmssrFeb. 8, 2024, 6:43 p.m.
                          Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                          Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                          EVA
                          EVADec. 25, 2023, 10:30 a.m.
                          Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                          Now discuss on the forum
                          C
                          CharlesmekOct. 3, 2024, 1:15 a.m.
                          добавить qlineseries в функции +7 (3812) 56-56-65 — городской телефон 052-83 — МТС 670 — Tele2 +7 (923) 699-30-03 — Мегафон 07-045 — Билайн https://mypsyhealth.ru/терапия/2022/04/27/blood-pressure 14 https://mypsyhealth…
                          JW
                          Jhon WickOct. 1, 2024, 3:52 p.m.
                          Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
                          КГ
                          Кирилл ГусаревSept. 27, 2024, 9:09 a.m.
                          Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
                          F
                          FynjyJuly 22, 2024, 4:15 a.m.
                          при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

                          Follow us in social networks