pasagir
pasagir16 августа 2018 г. 12:48

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-код страницы после входа?
Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

12
Evgenii Legotckoi
  • 23 августа 2018 г. 4:05

Добрый день

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


    pasagir
    • 23 августа 2018 г. 8:19

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

      pasagir
      • 23 августа 2018 г. 11:05

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

      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
        • 27 августа 2018 г. 3:34

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

        Только проверку кодов я бы сделал через 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
          • 27 августа 2018 г. 4:31

          Спасибо

            pasagir
            • 31 августа 2018 г. 5:26

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


              Evgenii Legotckoi
              • 1 сентября 2018 г. 3:55

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

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


                pasagir
                • 1 сентября 2018 г. 15:51

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

                  Evgenii Legotckoi
                  • 5 сентября 2018 г. 3:18

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

                    pasagir
                    • 14 сентября 2018 г. 8:54
                    • (ред.)

                    разобрался - просто полученные 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
                      • 15 сентября 2018 г. 6:23

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

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

                      mainwindow->close();

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

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

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

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

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

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

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

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



                        pasagir
                        • 15 сентября 2018 г. 8:03

                        Спасибо

                          Комментарии

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

                          C++ - Тест 004. Указатели, Массивы и Циклы

                          • Результат:50баллов,
                          • Очки рейтинга-4
                          m
                          • molni99
                          • 26 октября 2024 г. 1:37

                          C++ - Тест 004. Указатели, Массивы и Циклы

                          • Результат:80баллов,
                          • Очки рейтинга4
                          m
                          • molni99
                          • 26 октября 2024 г. 1:29

                          C++ - Тест 004. Указатели, Массивы и Циклы

                          • Результат:20баллов,
                          • Очки рейтинга-10
                          Последние комментарии
                          i
                          innorwall14 ноября 2024 г. 21:26
                          Qt/C++ - Урок 031. QCustomPlot - строим график по времени buy generic priligy We can just chat, and we will not lose too much time anyway
                          i
                          innorwall14 ноября 2024 г. 19:03
                          Qt/C++ - Урок 060. Настройка внешнего вида приложения в рантайме I didnt have an issue work colors priligy dapoxetine 60mg revia cost uk August 3, 2022 Reply
                          i
                          innorwall14 ноября 2024 г. 11:42
                          Как Копировать Файлы в Linux If only females relatives with DZ offspring were considered these percentages were 23 order priligy online uk
                          i
                          innorwall14 ноября 2024 г. 9:09
                          Qt/C++ - Урок 068. Hello World с использованием системы сборки CMAKE в CLion ditropan pristiq dosing With the Yankees leading, 4 3, Rivera jogged in from the bullpen to a standing ovation as he prepared for his final appearance in Chicago buy priligy pakistan
                          Сейчас обсуждают на форуме
                          i
                          innorwall14 ноября 2024 г. 3:39
                          добавить qlineseries в функции priligy amazon canada 93 GREB1 protein GREB1 AB011147 6
                          i
                          innorwall11 ноября 2024 г. 10:55
                          Всё ещё разбираюсь с кешем. priligy walgreens levitra dulcolax carbs The third ring was found to be made up of ultra relativistic electrons, which are also present in both the outer and inner rings
                          9
                          9Anonim25 октября 2024 г. 9:10
                          Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
                          ИМ
                          Игорь Максимов3 октября 2024 г. 4:05
                          Реализация навигации по разделам Спасибо Евгений!

                          Следите за нами в социальных сетях