Russian Qt Forum

Qt => Работа с сетью => Тема начата: rudireg от Март 13, 2013, 21:01



Название: Обертка для QNetworkAccessManager
Отправлено: rudireg от Март 13, 2013, 21:01
Доброго дня уважаемые....
Решил поработать с сетью, выбор пал на QNetworkAccessManager
Почитав документацию понял что нужно писать свою обертку над данным классом
чтобы я мог использовать в программе напрмер такой код
Код:
MyClass *http = new MyClass; 
if(http->get("http://gogle.ru"))  //Если запрос успешный, то ...
   QString htmlBody =  http->inbuff(); // Получаю html тело документиа
Иными словами задача состоит в том, чтобы выполнение программы приостанавливалось покуда не будет получен ответ от http->get("http://gogle.ru")

Я накидал код - обертку для  QNetworkAccessManager
Прошу высказать ваши замечаеия и поделиться ссылками на подобные обертки для преобритения опыта, в которых так же реализованы HTTP запросы, приятно поковыряться в чужом коде и узнать для себя чтото новое. Буду рад выслушать ваши мнения и предложения...
Планирую подключить работу с тайм-аутом, HTTPS , прокси и скосками

rhttp.h
Код:
#ifndef RHTTP_H
#define RHTTP_H

#include <QObject>
#include <QByteArray>
#include <QNetworkAccessManager>
#include <QNetworkCookieJar>
#include <QNetworkReply>
#include <QEventLoop>
#include <QUrl>
#include <QPair>
#include <QTimer>

class RHttp : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QByteArray m_inbuff READ inbuff)
    Q_PROPERTY(int m_networkError READ networkError)
    Q_PROPERTY(int m_httpStatusCode READ httpStatusCode)
    Q_PROPERTY(QString m_httpReasonPhrase READ httpReasonPhrase)
    Q_PROPERTY(bool m_autoRedirect READ autoRedirect WRITE setAutoRedirect)
    Q_PROPERTY(bool m_ajax READ ajax WRITE setAjax)
    Q_PROPERTY(const QList <QNetworkReply::RawHeaderPair> *m_listHeaders READ headersPair)

public:
    explicit RHttp(QObject *parent = 0);
    ~RHttp();

    bool get(const QString &uri);
    bool post(const QString &uri, const QByteArray &data);

    //Property functions
    QByteArray inbuff() {return this->m_inbuff;}
    int        networkError() {return this->m_networkError;}
    int        httpStatusCode() {return this->m_httpStatusCode;}
    QString    httpReasonPhrase() {return this->m_httpReasonPhrase;}
    bool       autoRedirect() {return this->m_autoRedirect;}
    void       setAutoRedirect(bool val) {this->m_autoRedirect = val;}
    bool       ajax() {return this->m_ajax;}
    void       setAjax(bool val) {this->m_ajax = val;}
    const QList <QNetworkReply::RawHeaderPair> *headersPair() {return this->m_listHeaders;}
    QString    headersString();

private:
    QNetworkAccessManager *manager;
    QNetworkCookieJar     *cookieJar;

    const QList <QNetworkReply::RawHeaderPair> *m_listHeaders;
    QByteArray m_inbuff;
    int        m_networkError;
    int        m_httpStatusCode;
    QString    m_httpReasonPhrase;
    bool       m_autoRedirect;
    bool       m_ajax;
    
signals:
    
public slots:
    
};

#endif // RHTTP_H


rhttp.cpp
Код:
#include "rhttp.h"
//-------------------------------------------------------------
RHttp::RHttp(QObject *parent) :
    QObject(parent)
{
    this->manager   = new QNetworkAccessManager(parent);
    this->cookieJar = new QNetworkCookieJar(parent);
    this->manager->setCookieJar(this->cookieJar);


    this->m_autoRedirect = false;
    this->m_ajax = false;
}
//-------------------------------------------------------------
RHttp::~RHttp()
{
    this->manager->deleteLater();
}
//-------------------------------------------------------------
bool RHttp::get(const QString &uri)
{
    //Clear
    this->m_inbuff.clear();
    this->m_httpStatusCode =0;
    this->m_httpReasonPhrase.clear();

    QUrl url(uri);
    QEventLoop eventLoop;

    QNetworkRequest request(url);
    request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
    request.setRawHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20100101 Firefox/19.0");
    request.setRawHeader("Accept-Language", "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3");
    request.setRawHeader("charset", "utf-8");
    request.setRawHeader("Connection", "keep-alive");


    QNetworkReply *reply = this->manager->get(request);
    QObject::connect(reply,SIGNAL(finished()),&eventLoop, SLOT(quit()));
    QTimer::singleShot(30000, &eventLoop, SLOT(quit())); // TimeOut
    eventLoop.exec(); //Waiting for request finished

    //Save code of network connection
    this->m_networkError = reply->error();

    //If conection error - return false
    if(reply->error() != QNetworkReply::NoError) return false;

    //Save http code: 200, 304, 404, 401, etc
    this->m_httpStatusCode   = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    this->m_httpReasonPhrase = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();

    //Processing of Http Status Code, currently 302
    if(this->m_httpStatusCode == 302 && this->m_autoRedirect == true) {
        QUrl reUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
        if(reUrl.isRelative()) reUrl = url.resolved(reUrl).toString();
        reply->deleteLater();
        return this->get(reUrl.toString());
    }
    else //Save request answer (inbuff)
    {
        this->m_inbuff = reply->readAll();
        this->m_listHeaders = &reply->rawHeaderPairs();
    }


   reply->deleteLater();

    return true;
}
//-------------------------------------------------------------

bool RHttp::post(const QString &uri, const QByteArray &data)
{
    //Clear
    this->m_inbuff.clear();
    this->m_httpStatusCode =0;
    this->m_httpReasonPhrase.clear();

    QUrl url(uri);
    QEventLoop eventLoop;

    QNetworkRequest request(url);
    request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
    request.setRawHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20100101 Firefox/19.0");
    request.setRawHeader("Accept-Language", "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3");
    request.setRawHeader("charset", "utf-8");
    request.setRawHeader("Connection", "keep-alive");
    //Is Ajax request
    if(this->m_ajax == true) {
        this->m_ajax = false;
        request.setRawHeader("X-Requested-With", "XMLHttpRequest");
    }

    QNetworkReply *reply = this->manager->post(request, data);
    QObject::connect(reply,SIGNAL(finished()),&eventLoop, SLOT(quit()));
     QTimer::singleShot(30000, &eventLoop, SLOT(quit())); // TimeOut
    eventLoop.exec(); //Waiting for request finished

    //Save code of network connection
    this->m_networkError = reply->error();

    //If conection error - return false
    if(reply->error() != QNetworkReply::NoError) return false;

    //Save http code: 200, 304, 404, 401, etc
    this->m_httpStatusCode   = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    this->m_httpReasonPhrase = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();

    //Processing of Http Status Code, currently 302
    if(this->m_httpStatusCode == 302 && this->m_autoRedirect == true) {
        QUrl reUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
        if(reUrl.isRelative()) reUrl = url.resolved(reUrl).toString();
        reply->deleteLater();
        return this->get(reUrl.toString());
    }
    else //Save request answer (inbuff)
    {
        this->m_inbuff = reply->readAll();
        this->m_listHeaders = &reply->rawHeaderPairs();
    }

    reply->deleteLater();

    return true;
}
//-------------------------------------------------------------
//Отобразить Header полученого заголовка в виде текста
QString RHttp::headersString()
{
    QString headersString;
    QNetworkReply::RawHeaderPair header;

    headersString  = QString::number(this->m_httpStatusCode);
    headersString += " | ";
    headersString += this->m_httpReasonPhrase;
    headersString += "\r\n";

    int size = this->m_listHeaders->size();
    for(int i=0; i<size; ++i) {
        header = this->m_listHeaders->at(i);
        headersString += header.first;
        headersString += ": ";
        headersString += header.second;
        headersString += "\r\n";
    }
    return headersString;
}
//-------------------------------------------------------------


Название: Re: Обертка для QNetworkAccessManager
Отправлено: IGreench от Март 14, 2013, 17:57
Приветствую.
Сам я не сильно разбираюсь, скорее бы хотел потыкаться в вашем коде, чтобы самому получить опыт.

А можно описание вашего решения? Чем оно отличается от стандартного?


Название: Re: Обертка для QNetworkAccessManager
Отправлено: Figaro от Март 17, 2013, 13:09
Вы уверены что там (http://gogle.ru)  ajax?

P.S. что такое "преобритения опыта"?