source: SMSSender/lib/libgateway/src/business/HttpHelper.cpp @ 50:bd7860a63824

3.0
Last change on this file since 50:bd7860a63824 was 50:bd7860a63824, checked in by Sämy Zehnder <saemy.zehnder@…>, 12 years ago
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}
154
155QString HttpHelper::getRequestResult() const {
156    return requestResult_;
157}
158
159void HttpHelper::responseHeaderReceived(const QHttpResponseHeader& responseHeader) {
160    //qDebug() << responseHeader.statusCode() << " " << responseHeader.reasonPhrase();
161    //qDebug() << responseHeader.values();
162
163    switch (responseHeader.statusCode()) {
164        case 200:
165            break;                  // Ok
166
167        case 301:                   // Moved Permanently
168        case 302:                   // Found
169        case 303:                   // See Other
170        case 307:                   // Temporary Redirect
171            qDebug() << "Have to redirect [" + QString::number(request_.httpRequestId) + "]";
172
173            request_.httpRequestId = -1; // To avoid error in httpRequestFinished
174            http_->abort();
175
176            // Since the responseHeaderReceived-Slot could eventually not be called yet in cookieManager -> this would lead to a wrong header in doRequest
177            cookieManager_->processResponseHeader(responseHeader);
178
179            //cookiemanager has not handled the response yet...
180            doRequest(responseHeader.value("location")); // Do the redirect
181            break;
182
183        default:
184            throw Http::EReadException("Unknown response code!");
185            break;
186    }
187}
188
189void HttpHelper::httpRequestFinished(int httpRequestId, bool error) {
190     if (request_.httpRequestId != httpRequestId) {
191         qDebug() << "Request [" + QString::number(httpRequestId) + "] finished (but is not parsed, since it is detached)";
192         return;
193     }
194
195     qDebug() << "Quitting request loop";
196     requestLoop_.quit();
197
198     if (error) {
199         qDebug() << "Request [" + QString::number(httpRequestId) + "] finished with an error: " + http_->errorString();
200         throw Http::EReadException(http_->errorString()); // TODO: Perhaps this error has to be thrown in the waitForRequest by passing a status value to requestLoop_.exit()
201     } else {
202         qDebug() << "Request [" + QString::number(httpRequestId) + "] finished";
203         requestResult_ = /*request.buffer.readAll()*/ http_->readAll();
204         //qDebug() << requestResult_;
205     }
206 }
207
208void HttpHelper::sslErrors(const QList<QSslError>& errors) {
209    QListIterator<QSslError> i(errors);
210    while (i.hasNext()){
211        QSslError err = i.next();
212        qDebug() << "SSL-error: " + err.errorString();
213    }
214}
Note: See TracBrowser for help on using the repository browser.