1 #include "http.h"
2
3 #include "networkhttpreply.h"
4
5 namespace {
6
networkAccessManager()7 QNetworkAccessManager *networkAccessManager() {
8 static thread_local QNetworkAccessManager *nam = new QNetworkAccessManager();
9 return nam;
10 }
11
12 int defaultReadTimeout = 10000;
13 int defaultMaxRetries = 3;
14 } // namespace
15
Http()16 Http::Http()
17 : requestHeaders(getDefaultRequestHeaders()), readTimeout(defaultReadTimeout),
18 maxRetries(defaultMaxRetries) {}
19
setRequestHeaders(const QMap<QByteArray,QByteArray> & headers)20 void Http::setRequestHeaders(const QMap<QByteArray, QByteArray> &headers) {
21 requestHeaders = headers;
22 }
23
getRequestHeaders()24 QMap<QByteArray, QByteArray> &Http::getRequestHeaders() {
25 return requestHeaders;
26 }
27
addRequestHeader(const QByteArray & name,const QByteArray & value)28 void Http::addRequestHeader(const QByteArray &name, const QByteArray &value) {
29 requestHeaders.insert(name, value);
30 }
31
setReadTimeout(int timeout)32 void Http::setReadTimeout(int timeout) {
33 readTimeout = timeout;
34 }
35
instance()36 Http &Http::instance() {
37 static Http i;
38 return i;
39 }
40
getDefaultRequestHeaders()41 const QMap<QByteArray, QByteArray> &Http::getDefaultRequestHeaders() {
42 static const QMap<QByteArray, QByteArray> defaultRequestHeaders = [] {
43 QMap<QByteArray, QByteArray> h;
44 h.insert("Accept-Charset", "utf-8");
45 h.insert("Connection", "Keep-Alive");
46 return h;
47 }();
48 return defaultRequestHeaders;
49 }
50
setDefaultReadTimeout(int timeout)51 void Http::setDefaultReadTimeout(int timeout) {
52 defaultReadTimeout = timeout;
53 }
54
networkReply(const HttpRequest & req)55 QNetworkReply *Http::networkReply(const HttpRequest &req) {
56 QNetworkRequest request(req.url);
57
58 QMap<QByteArray, QByteArray> &headers = requestHeaders;
59 if (!req.headers.isEmpty()) headers = req.headers;
60
61 QMap<QByteArray, QByteArray>::const_iterator it;
62 for (it = headers.constBegin(); it != headers.constEnd(); ++it)
63 request.setRawHeader(it.key(), it.value());
64
65 if (req.offset > 0)
66 request.setRawHeader("Range", QStringLiteral("bytes=%1-").arg(req.offset).toUtf8());
67
68 QNetworkAccessManager *manager = networkAccessManager();
69
70 QNetworkReply *networkReply = nullptr;
71 switch (req.operation) {
72 case QNetworkAccessManager::GetOperation:
73 networkReply = manager->get(request);
74 break;
75
76 case QNetworkAccessManager::HeadOperation:
77 networkReply = manager->head(request);
78 break;
79
80 case QNetworkAccessManager::PostOperation:
81 networkReply = manager->post(request, req.body);
82 break;
83
84 case QNetworkAccessManager::PutOperation:
85 networkReply = manager->put(request, req.body);
86 break;
87
88 case QNetworkAccessManager::DeleteOperation:
89 networkReply = manager->deleteResource(request);
90 break;
91
92 default:
93 qWarning() << "Unknown operation:" << req.operation;
94 }
95
96 return networkReply;
97 }
98
request(const HttpRequest & req)99 HttpReply *Http::request(const HttpRequest &req) {
100 return new NetworkHttpReply(req, *this);
101 }
102
request(const QUrl & url,QNetworkAccessManager::Operation operation,const QByteArray & body,uint offset)103 HttpReply *Http::request(const QUrl &url,
104 QNetworkAccessManager::Operation operation,
105 const QByteArray &body,
106 uint offset) {
107 HttpRequest req;
108 req.url = url;
109 req.operation = operation;
110 req.body = body;
111 req.offset = offset;
112 return request(req);
113 }
114
get(const QUrl & url)115 HttpReply *Http::get(const QUrl &url) {
116 return request(url, QNetworkAccessManager::GetOperation);
117 }
118
head(const QUrl & url)119 HttpReply *Http::head(const QUrl &url) {
120 return request(url, QNetworkAccessManager::HeadOperation);
121 }
122
post(const QUrl & url,const QMap<QString,QString> & params)123 HttpReply *Http::post(const QUrl &url, const QMap<QString, QString> ¶ms) {
124 QByteArray body;
125 QMapIterator<QString, QString> i(params);
126 while (i.hasNext()) {
127 i.next();
128 body += QUrl::toPercentEncoding(i.key()) + '=' + QUrl::toPercentEncoding(i.value()) + '&';
129 }
130 HttpRequest req;
131 req.url = url;
132 req.operation = QNetworkAccessManager::PostOperation;
133 req.body = body;
134 req.headers = requestHeaders;
135 req.headers.insert("Content-Type", "application/x-www-form-urlencoded");
136 return request(req);
137 }
138
post(const QUrl & url,const QByteArray & body,const QByteArray & contentType)139 HttpReply *Http::post(const QUrl &url, const QByteArray &body, const QByteArray &contentType) {
140 HttpRequest req;
141 req.url = url;
142 req.operation = QNetworkAccessManager::PostOperation;
143 req.body = body;
144 req.headers = requestHeaders;
145 QByteArray cType = contentType;
146 if (cType.isEmpty()) cType = "application/x-www-form-urlencoded";
147 req.headers.insert("Content-Type", cType);
148 return request(req);
149 }
150
151
put(const QUrl & url,const QByteArray & body,const QByteArray & contentType)152 HttpReply *Http::put(const QUrl &url, const QByteArray &body, const QByteArray &contentType) {
153 HttpRequest req;
154 req.url = url;
155 req.operation = QNetworkAccessManager::PutOperation;
156 req.body = body;
157 req.headers = requestHeaders;
158 QByteArray cType = contentType;
159 if (cType.isEmpty()) cType = "application/x-www-form-urlencoded";
160 req.headers.insert("Content-Type", cType);
161 return request(req);
162 }
163
164
deleteResource(const QUrl & url)165 HttpReply *Http::deleteResource(const QUrl &url) {
166 HttpRequest req;
167 req.url = url;
168 req.operation = QNetworkAccessManager::DeleteOperation;
169 req.headers = requestHeaders;
170 return request(req);
171 }
172
getMaxRetries() const173 int Http::getMaxRetries() const {
174 return maxRetries;
175 }
176
setMaxRetries(int value)177 void Http::setMaxRetries(int value) {
178 maxRetries = value;
179 }
180