Skip to content

Commit eb6f0a6

Browse files
添加Http库文件
1 parent d8a4c73 commit eb6f0a6

22 files changed

+1243
-0
lines changed

qt_http/http/CMakeLists.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
cmake_minimum_required(VERSION 3.12)
2+
project(http LANGUAGES CXX)
3+
4+
set(CMAKE_CXX_STANDARD 14)
5+
set(CMAKE_AUTOMOC ON)
6+
7+
find_package(Qt5 REQUIRED COMPONENTS Core Network)
8+
9+
add_library(http
10+
src/cachedhttp.h
11+
src/cachedhttp.cpp
12+
src/http.h
13+
src/http.cpp
14+
src/httpreply.h
15+
src/httprequest.h
16+
src/httpreply.cpp
17+
src/localcache.h
18+
src/localcache.cpp
19+
src/networkhttpreply.h
20+
src/networkhttpreply.cpp
21+
src/throttledhttp.h
22+
src/throttledhttp.cpp
23+
)
24+
25+
target_link_libraries(http Qt5::Network)

qt_http/http/http.pri

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
INCLUDEPATH += $$PWD/src
3+
DEFINES += HTTP
4+
5+
HEADERS += \
6+
$$PWD/src/cachedhttp.h \
7+
$$PWD/src/http.h \
8+
$$PWD/src/httpreply.h \
9+
$$PWD/src/httprequest.h \
10+
$$PWD/src/localcache.h \
11+
$$PWD/src/networkhttpreply.h \
12+
$$PWD/src/throttledhttp.h
13+
14+
SOURCES += \
15+
$$PWD/src/cachedhttp.cpp \
16+
$$PWD/src/http.cpp \
17+
$$PWD/src/httpreply.cpp \
18+
$$PWD/src/localcache.cpp \
19+
$$PWD/src/networkhttpreply.cpp \
20+
$$PWD/src/throttledhttp.cpp

qt_http/http/http.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
TEMPLATE = lib
2+
include(http.pri)

qt_http/http/marketplace.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"$schema": "http://qt.io/schema/extension-schema-v1#",
3+
"title": "Http",
4+
"extensionType": [
5+
"library"
6+
],
7+
"version": "1",
8+
"vendor": {
9+
"name": "Flavio Tordini",
10+
"url": "https://flavio.tordini.org"
11+
},
12+
"contact": "Flavio Tordini <flavio.tordini@gmail.com>",
13+
"copyright": [
14+
"Flavio Tordini"
15+
],
16+
"author": "Flavio Tordini",
17+
"icon": "https://flavio.tordini.org/favicon-196x196.png",
18+
"licenses": [
19+
{
20+
"licenseType": "MIT",
21+
"licenseUrl": "https://opensource.org/licenses/MIT"
22+
}
23+
],
24+
"created": "2016-07-02",
25+
"platforms": [
26+
"Windows",
27+
"Linux",
28+
"macOS",
29+
"Android",
30+
"iOS"
31+
],
32+
"qtVersions": [
33+
"5.10.0-or-later"
34+
],
35+
"tags": [
36+
"http,web,rest,networking,freeproduct,tools,utility"
37+
],
38+
"price": {
39+
"listprice": 0
40+
},
41+
"support": "flavio.tordini@gmail.com",
42+
"bugUrl": "https://github.com/flaviotordini/http/issues",
43+
"sourceRepoUrl": "https://github.com/flaviotordini/http",
44+
"userManuals": [
45+
"https://github.com/flaviotordini/http/blob/master/README.md"
46+
],
47+
"dependencies": [
48+
"Network"
49+
]
50+
}

qt_http/http/src/cachedhttp.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#include "cachedhttp.h"
2+
#include "localcache.h"
3+
#include <QtNetwork>
4+
5+
CachedHttpReply::CachedHttpReply(const QByteArray &body, const QUrl &url, bool autoSignals)
6+
: bytes(body), requestUrl(url) {
7+
if (autoSignals) QTimer::singleShot(0, this, SLOT(emitSignals()));
8+
}
9+
10+
QByteArray CachedHttpReply::body() const {
11+
return bytes;
12+
}
13+
14+
void CachedHttpReply::emitSignals() {
15+
emit data(body());
16+
emit finished(*this);
17+
deleteLater();
18+
}
19+
20+
WrappedHttpReply::WrappedHttpReply(CachedHttp &cachedHttp,
21+
LocalCache *cache,
22+
const QByteArray &key,
23+
HttpReply *httpReply)
24+
: HttpReply(httpReply), cachedHttp(cachedHttp), cache(cache), key(key), httpReply(httpReply) {
25+
connect(httpReply, &HttpReply::finished, this, &WrappedHttpReply::originFinished);
26+
}
27+
28+
void WrappedHttpReply::originFinished(const HttpReply &reply) {
29+
qDebug() << reply.statusCode() << reply.url();
30+
bool success = reply.isSuccessful();
31+
if (!success) {
32+
// Fallback to stale cached data on HTTP error
33+
const QByteArray value = cache->possiblyStaleValue(key);
34+
if (!value.isNull()) {
35+
qDebug() << "Using stale cache value" << reply.url();
36+
emit data(value);
37+
auto replyFromCache = new CachedHttpReply(value, reply.url(), false);
38+
emit finished(*replyFromCache);
39+
replyFromCache->deleteLater();
40+
return;
41+
}
42+
}
43+
44+
bool doCache = success;
45+
if (doCache) {
46+
const auto &validators = cachedHttp.getValidators();
47+
if (!validators.isEmpty()) {
48+
const QByteArray &mime = reply.header("Content-Type");
49+
auto i = validators.constFind(mime);
50+
if (i != validators.constEnd()) {
51+
auto validator = i.value();
52+
doCache = validator(reply);
53+
} else {
54+
i = validators.constFind("*");
55+
if (i != validators.constEnd()) {
56+
auto validator = i.value();
57+
doCache = validator(reply);
58+
}
59+
}
60+
}
61+
}
62+
63+
if (doCache)
64+
cache->insert(key, reply.body());
65+
else
66+
qDebug() << "Not caching" << reply.statusCode() << reply.url();
67+
68+
if (success) {
69+
emit data(reply.body());
70+
} else {
71+
emit error(reply.reasonPhrase());
72+
}
73+
emit finished(reply);
74+
}
75+
76+
CachedHttp::CachedHttp(Http &http, const char *name)
77+
: http(http), cache(LocalCache::instance(name)), cachePostRequests(false) {}
78+
79+
void CachedHttp::setMaxSeconds(uint seconds) {
80+
cache->setMaxSeconds(seconds);
81+
}
82+
83+
void CachedHttp::setMaxSize(uint maxSize) {
84+
cache->setMaxSize(maxSize);
85+
}
86+
87+
HttpReply *CachedHttp::request(const HttpRequest &req) {
88+
bool cacheable = req.operation == QNetworkAccessManager::GetOperation ||
89+
(cachePostRequests && req.operation == QNetworkAccessManager::PostOperation);
90+
if (!cacheable) {
91+
qDebug() << "Not cacheable" << req.url;
92+
return http.request(req);
93+
}
94+
const QByteArray key = requestHash(req);
95+
const QByteArray value = cache->value(key);
96+
if (!value.isNull()) {
97+
// qDebug() << "HIT" << key << req.url;
98+
return new CachedHttpReply(value, req.url);
99+
}
100+
// qDebug() << "MISS" << key << req.url;
101+
return new WrappedHttpReply(*this, cache, key, http.request(req));
102+
}
103+
104+
QByteArray CachedHttp::requestHash(const HttpRequest &req) {
105+
const char sep = '|';
106+
107+
QByteArray s;
108+
if (ignoreHostname) {
109+
s = (req.url.scheme() + sep + req.url.path() + sep + req.url.query()).toUtf8();
110+
} else {
111+
s = req.url.toEncoded();
112+
}
113+
s += sep + req.body + sep + QByteArray::number(req.offset);
114+
if (req.operation == QNetworkAccessManager::PostOperation) {
115+
s.append(sep);
116+
s.append("POST");
117+
}
118+
return LocalCache::hash(s);
119+
}

qt_http/http/src/cachedhttp.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#ifndef CACHEDHTTP_H
2+
#define CACHEDHTTP_H
3+
4+
#include "http.h"
5+
6+
class LocalCache;
7+
8+
class CachedHttp : public Http {
9+
public:
10+
CachedHttp(Http &http = Http::instance(), const char *name = "http");
11+
void setMaxSeconds(uint seconds);
12+
void setMaxSize(uint maxSize);
13+
void setCachePostRequests(bool value) { cachePostRequests = value; }
14+
void setIgnoreHostname(bool value) { ignoreHostname = value; }
15+
auto &getValidators() { return validators; }
16+
HttpReply *request(const HttpRequest &req);
17+
18+
private:
19+
QByteArray requestHash(const HttpRequest &req);
20+
21+
Http &http;
22+
LocalCache *cache;
23+
bool cachePostRequests;
24+
bool ignoreHostname = false;
25+
26+
/// Mapping is MIME -> validating function
27+
/// Use * as MIME to define a catch-all validator
28+
QMap<QByteArray, std::function<bool(const HttpReply &)>> validators;
29+
};
30+
31+
class CachedHttpReply : public HttpReply {
32+
Q_OBJECT
33+
34+
public:
35+
CachedHttpReply(const QByteArray &body, const QUrl &url, bool autoSignals = true);
36+
QUrl url() const { return requestUrl; }
37+
int statusCode() const { return 200; }
38+
QByteArray body() const;
39+
40+
private slots:
41+
void emitSignals();
42+
43+
private:
44+
const QByteArray bytes;
45+
const QUrl requestUrl;
46+
};
47+
48+
class WrappedHttpReply : public HttpReply {
49+
Q_OBJECT
50+
51+
public:
52+
WrappedHttpReply(CachedHttp &cachedHttp,
53+
LocalCache *cache,
54+
const QByteArray &key,
55+
HttpReply *httpReply);
56+
QUrl url() const { return httpReply->url(); }
57+
int statusCode() const { return httpReply->statusCode(); }
58+
QByteArray body() const { return httpReply->body(); }
59+
60+
private slots:
61+
void originFinished(const HttpReply &reply);
62+
63+
private:
64+
CachedHttp &cachedHttp;
65+
LocalCache *cache;
66+
QByteArray key;
67+
HttpReply *httpReply;
68+
};
69+
70+
#endif // CACHEDHTTP_H

0 commit comments

Comments
 (0)