source: SMSSender/lib/libgateway/src/business/HttpHelper.cpp @ 49:3b8d4abd0ee6

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