source: SMSSender/lib/libgateway/src/business/HttpHelper.cpp @ 51:5ae27b38b78b

3.0
Last change on this file since 51:5ae27b38b78b was 51:5ae27b38b78b, checked in by Sämy Zehnder <saemy.zehnder@…>, 12 years ago
  • The usual stuff... ;)
File size: 7.1 KB
Line 
1#include "HttpHelper.h"
2
3#include <QBuffer>
4#include <QDebug>
5#include <QSslError>
6#include <QUrl>
7
8#include <HttpExceptions.h>
9
10HttpHelper::HttpHelper() {
11    // TODO: Proxy...
12
13    http_ = new QHttp();
14
15    connect(http_, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)),
16            this, SLOT(responseHeaderReceived(const QHttpResponseHeader&)));
17    connect(http_, SIGNAL(requestFinished(int, bool)),
18            this, SLOT(httpRequestFinished(int, bool)));
19    connect(http_, SIGNAL(sslErrors(const QList<QSslError>&)),
20            this, SLOT(sslErrors(const QList<QSslError>&)));
21
22
23    cookieManager_ = new HttpCookieManager(http_);
24
25    defaultHeader_ = new QHttpRequestHeader();
26    defaultHeader_->setContentType("application/x-www-form-urlencoded");
27    defaultHeader_->setValue("user-agent", "Mozilla/3.0 (compatible; SMSSender; http://www.gorrion.ch/p/smssender)"); //TODO: include version, if needed (don't generate the instance here, but in a central bchttpmanager or so)
28}
29
30HttpHelper::~HttpHelper() {
31    delete defaultHeader_;
32    delete cookieManager_;
33    delete http_;
34}
35
36
37QHttp* HttpHelper::http() const {
38    return http_;
39}
40HttpCookieManager* HttpHelper::cookieManager() const {
41    return cookieManager_;
42}
43
44QHttpRequestHeader HttpHelper::defaultHeader(const QUrl& url) const {
45    QHttpRequestHeader req = QHttpRequestHeader(*defaultHeader_); // return a copy, to not get touched by further modifications
46    cookieManager_->addCookieToHeader(&req, url);
47
48    return req;
49}
50
51QString HttpHelper::get(const QString& destination, const QMap<QString, QString>& requests /* = QMap<QString, QString>() */) {
52    waitForRequest(false); // Wait until a running request has been finished
53
54    startRequest("GET", destination, requests, QMap<QString, QString>());
55    waitForRequest();
56    return getRequestResult();
57}
58
59QString HttpHelper::post(const QString& destination, const QMap<QString, QString>& requests /* = QMap<QString, QString>() */,
60        const QMap<QString, QString>& posts /* = QMap<QString, QString>() */)
61{
62    waitForRequest(false); // Wait until a running request has been finished
63
64    startRequest("POST", destination, requests, posts);
65    waitForRequest();
66    return getRequestResult();
67}
68
69void HttpHelper::startRequest(const QString& method, const QString& destination, const QMap<QString, QString>& requests /* = QMap<QString, QString>() */,
70        const QMap<QString, QString>& posts /* = QMap<QString, QString>() */)
71{
72    requestResult_ = "";
73
74    QUrl url_ = QUrl(destination);
75
76    // Add request parameters to url_
77    QMapIterator<QString, QString> i(requests);
78    while (i.hasNext()){
79        i.next();
80        url_.addQueryItem(i.key(), i.value());
81    }
82
83    QString uri_ = url_.scheme() + "://" + url_.host() + url_.encodedPath() + "?" + url_.encodedQuery();
84    //qDebug() << uri_;
85
86    /* Create the request record */
87    request_.method = method;
88    request_.posts  = getParamStr(posts);
89
90    /* Do the request */
91    doRequest(uri_);
92}
93
94int HttpHelper::doRequest(const QString& destination) {
95    QUrl url_ = QUrl(destination);
96
97    /* Connection */
98    QHttp::ConnectionMode mode = url_.scheme().toLower() == "https" ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp;
99    http_->setHost(url_.host(), mode, url_.port(0));
100
101    if (!url_.userName().isEmpty())
102        http_->setUser(url_.userName(), url_.password());
103
104    /* Header */
105    QHttpRequestHeader header_ = defaultHeader(url_);
106    header_.setValue("Host", url_.host());
107    header_.setValue("Connection", "Keep-Alive");
108
109    QByteArray path_ = url_.encodedPath();
110    if (path_.isEmpty())
111        path_ = "/";
112
113    header_.setRequest(request_.method, path_ + "?" + url_.encodedQuery());
114
115    /* Start the request */
116    //qDebug() << destination;
117    //qDebug() << header_.toString();
118    //qDebug() << request_.posts;
119
120    request_.httpRequestId = http_->request(header_, request_.posts.toUtf8()/*, req.buffer*/);
121    qDebug() << "Started request " + QString::number(request_.httpRequestId) + ": " + request_.method + ": " + url_.path();
122
123    return request_.httpRequestId;
124}
125
126
127QString HttpHelper::getParamStr(const QMap<QString, QString>& params) {
128    QString params_ = "";
129
130    QMapIterator<QString, QString> i(params);
131    while (i.hasNext()) {
132        i.next();
133        if (i.key().trimmed() != ""){
134            params_ += i.key() + "=" + i.value() + "&";
135        }
136    }
137    params_.remove(QRegExp("[&]$")); // remove last &
138
139    return params_;
140}
141
142/*bool HttpAccountHelper::isRequestFinished(const int& requestId) const {
143    return finishedRequests_.contains(requestId);
144}*/
145
146void HttpHelper::waitForRequest(bool createIfNotExisting /* = true */) {
147    if (!requestLoop_.isRunning() && !createIfNotExisting){
148        return;
149    }
150
151    qDebug() << "Starting request loop";
152    requestLoop_.exec();
153    qDebug() << "Request loop quitted";
154}
155
156QString HttpHelper::getRequestResult() const {
157    return requestResult_;
158}
159
160void HttpHelper::responseHeaderReceived(const QHttpResponseHeader& responseHeader) {
161    //qDebug() << responseHeader.statusCode() << " " << responseHeader.reasonPhrase();
162    //qDebug() << responseHeader.values();
163
164    switch (responseHeader.statusCode()) {
165        case 200:
166            break;                  // Ok
167
168        case 301:                   // Moved Permanently
169        case 302:                   // Found
170        case 303:                   // See Other
171        case 307:                   // Temporary Redirect
172            qDebug() << "Have to redirect [" + QString::number(request_.httpRequestId) + "]";
173
174            request_.httpRequestId = -1; // To avoid error in httpRequestFinished
175            http_->abort();
176
177            // Since the responseHeaderReceived-Slot could eventually not be called yet in cookieManager -> this would lead to a wrong header in doRequest
178            cookieManager_->processResponseHeader(responseHeader);
179
180            //cookiemanager has not handled the response yet...
181            doRequest(responseHeader.value("location")); // Do the redirect
182            break;
183
184        default:
185            throw Http::EReadException("Unknown response code!");
186            break;
187    }
188}
189
190void HttpHelper::httpRequestFinished(int httpRequestId, bool error) {
191     if (request_.httpRequestId != httpRequestId) {
192         qDebug() << "Request [" + QString::number(httpRequestId) + "] finished (but is not parsed, since it is detached)";
193         return;
194     }
195
196     qDebug() << "Quitting request loop";
197     requestLoop_.quit();
198
199     if (error) {
200         qDebug() << "Request [" + QString::number(httpRequestId) + "] finished with an error: " + http_->errorString();
201         throw Http::EReadException(http_->errorString()); // TODO: Perhaps this error has to be thrown in the waitForRequest by passing a status value to requestLoop_.exit()
202     } else {
203         qDebug() << "Request [" + QString::number(httpRequestId) + "] finished";
204         requestResult_ = /*request.buffer.readAll()*/ http_->readAll();
205         //qDebug() << requestResult_;
206     }
207 }
208
209void HttpHelper::sslErrors(const QList<QSslError>& errors) {
210    QListIterator<QSslError> i(errors);
211    while (i.hasNext()){
212        QSslError err = i.next();
213        qDebug() << "SSL-error: " + err.errorString();
214    }
215}
Note: See TracBrowser for help on using the repository browser.