##// END OF EJS Templates
Basic Async implementation of downloader...
jeandet -
r1343:d543c61b5a4e
parent child
Show More
@@ -10,14 +10,16
10
10
11 #include <QString>
11 #include <QString>
12 #include <QByteArray>
12 #include <QByteArray>
13 #include <QUuid>
13
14
14 /**
15 /**
15 * @brief The Downloader handles all data donwloads in SciQLOP.
16 * @brief The Downloader handles all data donwloads in SciQLOP.
16 */
17 */
17 class SCIQLOP_CORE_EXPORT Downloader{
18 class SCIQLOP_CORE_EXPORT Downloader{
18 public:
19 public:
19 static Response get(const QString& url);
20 static Response get(const QString& url, const QString& user="", const QString& passwd="");
20 static Response get(const QString& url, const QString& user, const QString& passwd);
21 static QUuid getAsync(const QString& url, std::function<void (QUuid, Response)> callback, const QString& user="", const QString& passwd="");
22 static bool downloadFinished(QUuid uuid);
21
23
22 static Downloader& instance()
24 static Downloader& instance()
23 {
25 {
@@ -9,12 +9,30
9 #include <QHash>
9 #include <QHash>
10 #include <QPair>
10 #include <QPair>
11 #include <QCoreApplication>
11 #include <QCoreApplication>
12 #include <QReadWriteLock>
12
13
13 class Downloader::p_Downloader
14 class Downloader::p_Downloader
14 {
15 {
15 using login_pair=QPair<QString,QString>;
16 using login_pair=QPair<QString,QString>;
16 QNetworkAccessManager manager;
17 QNetworkAccessManager manager;
17 QHash<QString,login_pair> auth;
18 QHash<QString,login_pair> auth;
19 QReadWriteLock pending_requests_lock;
20 QHash<QUuid,QNetworkReply*> pending_requests;
21
22 QNetworkRequest buildRequest(const QString& url, const QString &user="", const QString &passwd="")
23 {
24 QNetworkRequest request;
25 request.setUrl(QUrl(url));
26 request.setRawHeader("User-Agent", "SciQLop 1.0");
27 if(user!="" and passwd!="")
28 {
29 //might grow quickly since we can have tons of URLs for the same host
30 auth[url]=login_pair(user,passwd);
31 QString login = "Basic "+user+":"+passwd;
32 request.setRawHeader("Authorization",login.toLocal8Bit());
33 }
34 return request;
35 }
18
36
19 public:
37 public:
20 explicit p_Downloader()
38 explicit p_Downloader()
@@ -29,37 +47,70 public:
29 authenticator->setPassword(login.second);
47 authenticator->setPassword(login.second);
30 }
48 }
31 };
49 };
50
32 QObject::connect(&manager, &QNetworkAccessManager::authenticationRequired, login_bambda);
51 QObject::connect(&manager, &QNetworkAccessManager::authenticationRequired, login_bambda);
33 }
52 }
34
53
35 Response get(const QString& url, const QString &user="", const QString &passwd="")
54 Response get(const QString& url, const QString &user="", const QString &passwd="")
36 {
55 {
37 QNetworkRequest request;
56 QNetworkRequest request = buildRequest(url, user, passwd);
38 request.setUrl(QUrl(url));
39 request.setRawHeader("User-Agent", "SciQLop 1.0");
40 if(user!="" and passwd!="")
41 {
42 //might grow quickly since we can have tons of URLs for the same host
43 auth[url]=login_pair(user,passwd);
44 QString login = "Basic "+user+":"+passwd;
45 request.setRawHeader("Authorization",login.toLocal8Bit());
46 }
47 QNetworkReply *reply = manager.get(request);
57 QNetworkReply *reply = manager.get(request);
48 while (!reply->isFinished())
58 while (!reply->isFinished())
49 QCoreApplication::processEvents();
59 QCoreApplication::processEvents();
50 QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
60 QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
51 return Response(reply->readAll(), status_code.toInt());
61 Response resp = Response(reply->readAll(), status_code.toInt());
62 delete reply;
63 return resp;
64 }
65
66 QUuid getAsync(const QString &url, std::function<void (QUuid ,Response)> callback, const QString &user, const QString &passwd)
67 {
68 auto uuid = QUuid::createUuid();
69 QNetworkRequest request = buildRequest(url, user, passwd);
70 QNetworkReply *reply = manager.get(request);
71 auto callback_wrapper = [uuid, callback, this](){
72 QNetworkReply* reply;
73 {
74 QWriteLocker locker(&pending_requests_lock);
75 reply = pending_requests.take(uuid);
76 }
77 QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
78 Response resp = Response(reply->readAll(), status_code.toInt());
79 delete reply;
80 callback(uuid, resp);
81 };
82 QObject::connect(reply, &QNetworkReply::finished, callback_wrapper);
83 {
84 QWriteLocker locker(&pending_requests_lock);
85 pending_requests[uuid] = reply;
86 }
87 return uuid;
88 }
89 bool downloadFinished(QUuid uuid)
90 {
91 QReadLocker locker(&pending_requests_lock);
92 if(pending_requests.contains(uuid))
93 {
94 auto req = pending_requests[uuid];
95 return req->isFinished();
96 }
97 return true;
52 }
98 }
53 };
99 };
54
100
55 Response Downloader::get(const QString &url)
101 Response Downloader::get(const QString &url, const QString &user, const QString &passwd)
56 {
102 {
57 return Downloader::instance().impl->get(url);
103 return Downloader::instance().impl->get(url, user, passwd);
58 }
104 }
59
105
60 Response Downloader::get(const QString &url, const QString &user, const QString &passwd)
106 QUuid Downloader::getAsync(const QString &url, std::function<void (QUuid ,Response)> callback, const QString &user, const QString &passwd)
61 {
107 {
62 return Downloader::instance().impl->get(url, user, passwd);
108 return Downloader::instance().impl->getAsync(url, callback, user, passwd);
109 }
110
111 bool Downloader::downloadFinished(QUuid uuid)
112 {
113 return Downloader::instance().impl->downloadFinished(uuid);
63 }
114 }
64
115
65 Downloader::Downloader()
116 Downloader::Downloader()
@@ -22,6 +22,29 private slots:
22 QCOMPARE(resp.data(), QString("{\n \"user-agent\": \"SciQLop 1.0\"\n}\n"));
22 QCOMPARE(resp.data(), QString("{\n \"user-agent\": \"SciQLop 1.0\"\n}\n"));
23 }
23 }
24
24
25 void simpleAsyncGet()
26 {
27 bool done = false;
28 int status = -1;
29 QByteArray data;
30 auto callback = [&done, &status, &data](QUuid uuid,Response resp)
31 {
32 status = resp.status_code();
33 done = true;
34 data = resp.data();
35 };
36 auto uuid = Downloader::getAsync("http://ovh.net/files/1Mio.dat", callback);
37 QCOMPARE(Downloader::downloadFinished(uuid), false);
38 while (!done)
39 {
40 QCoreApplication::processEvents();
41 }
42 QCOMPARE(Downloader::downloadFinished(uuid), true);
43 QCOMPARE(status, 200);
44 QCOMPARE(data[0],'\xBA');
45 QCOMPARE(data[data.length()-1],'\x20');
46 }
47
25 void wrongUrl()
48 void wrongUrl()
26 {
49 {
27 auto resp = Downloader::get("https://lpp.polytechniqe2.fr");
50 auto resp = Downloader::get("https://lpp.polytechniqe2.fr");
General Comments 0
You need to be logged in to leave comments. Login now