This repository was archived by the owner on Aug 19, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 98
/
Copy pathtabcache.cpp
110 lines (93 loc) · 4.2 KB
/
tabcache.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "tabcache.h"
#include "QsLog.h"
#include <QDir>
#include <QDateTime>
// TabCache
//
// This class is a 'work around' for path of exile API not using 'ETag' headers
// and supporting existing cache methods that QNetworkDiskCache would have
// otherwise supported directly. If they ever fix this we should be able to
// just remove this implementation and use QNetworkDiskCache directly.
//
// Currently the API sends headers that look like this:
//
// DEBUG 2016-01-16T13:04:10.054 "Server" "nginx/1.4.4"
// DEBUG 2016-01-16T13:04:10.054 "Date" "Sat, 16 Jan 2016 19:04:10 GMT"
// DEBUG 2016-01-16T13:04:10.054 "Content-Type" "application/json"
// DEBUG 2016-01-16T13:04:10.054 "Expires" "Thu, 19 Nov 1981 08:52:00 GMT"
// DEBUG 2016-01-16T13:04:10.055 "Cache-Control" "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"
// DEBUG 2016-01-16T13:04:10.055 "Pragma" "no-cache"
// DEBUG 2016-01-16T13:04:10.055 "X-Frame-Options" "SAMEORIGIN"
//
// 'no-cache' - actually allows client to cache requests, but *requests*
// revalidation to use cached data (using ETag or Last Modified headers).
// clients can choose to ignore revalidation request and use possibly
// stale content.
//
// 'must-revalidate' - *requires* revalidation of cached content. If no
// revalidation method exists don't use cached data.
//
// 'no-store' - *requires* client to not store content to disk. This is the what
// really disables caching.
//
// So the plan is to basically just to ignore the Cache-Control and Pragma headers.
// This is achieved by overridding QNetworkDiskCache 'prepare' method so it
// effectively doesn't seem them.
//
// A helper method is needed however to create our network requests properly such
// such that the requests always prefer hitting in the cache.
//
// The method is:
//
// Request(url, <flags>);
//
// Where <flags> can be used to force an eviction, causing a reload
// Request(url, TabCache::Refresh);
//
// If 'Refresh' is not specified we're guaranteed to hit in cache if entry exists
// and fetch otherwise.
//
// So, to minimize overall API requests it will become a matter of minimizing requests
// that ask for a refresh. From the point of view of the rest of the application it will
// always appear as if we request all the tabs.
TabCache::TabCache(QObject* parent)
:QNetworkDiskCache(parent)
{
}
QNetworkRequest TabCache::Request(const QUrl &url, Flags flags) {
QNetworkRequest request{url};
bool evicted = false;
if (flags.testFlag(Refresh)) {
remove(url);
evicted = true;
}
// At this point we've evicted any request that should be refreshed, so we always
// tell the 'real' request to prefer but not require the entry be in the cache.
// If it is not in the cache it will be fetched from the network regardless.
request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, QNetworkRequest::PreferCache);
QLOG_DEBUG() << "Evicted:" << evicted << ":" << url.toDisplayString();
return request;
}
QIODevice *TabCache::prepare(const QNetworkCacheMetaData &metaData) {
QNetworkCacheMetaData local{metaData};
//Default policy based on received HTTP headers is to not save to disk.
//Override here, and set proper expiration so items are put in cache
//(setSaveToDisk) and valid when retrieved using metaData call -
//(setExpirationDate)
local.setSaveToDisk(true);
// Need to set some reasonable length of time in which our cache entries
// will expire. It's possible we'll want to allow users to customize this.
local.setExpirationDate(QDateTime().currentDateTime().addDays(kCacheExpireInDays));
QNetworkCacheMetaData::RawHeaderList headers;
for (auto &header: local.rawHeaders()) {
// Modify Cache-Control headers - basically need to drop 'no-store'
// as we want to store to cache and 'must-revalidate' as we don't have
// ETag or last modified headers available to attempt re-validation. To
// be on the safe side though just drop Cache-Control and Pragma headers.
if (header.first == "Cache-Control") continue;
if (header.first == "Pragma") continue;
headers.push_back(header);
}
local.setRawHeaders(headers);
return QNetworkDiskCache::prepare(local);
}