-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathCachingApp.h
More file actions
113 lines (82 loc) · 3.1 KB
/
CachingApp.h
File metadata and controls
113 lines (82 loc) · 3.1 KB
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
110
111
112
113
#ifndef UWS_CACHINGAPP_H
#define UWS_CACHINGAPP_H
#include "App.h"
#include <unordered_map>
#include <string>
#include <functional>
#include <string_view>
namespace uWS {
struct StringViewHash {
size_t operator()(std::string_view sv) const {
return std::hash<std::string_view>{}(sv);
}
};
struct StringViewEqual {
bool operator()(std::string_view sv1, std::string_view sv2) const {
return sv1 == sv2;
}
};
class CachingHttpResponse {
public:
CachingHttpResponse(uWS::HttpResponse<false> *res)
: res(res) {}
void write(std::string_view data) {
buffer.append(data);
}
void end(std::string_view data = "") {
buffer.append(data);
// end for all queued up sockets also
res->end(buffer);
created = time(0);
}
public:
uWS::HttpResponse<false>* res; // should be a vector of waiting sockets
std::string buffer; // body
time_t created;
};
typedef std::unordered_map<std::string_view, CachingHttpResponse *,
StringViewHash,
StringViewEqual> CacheType;
// we can also derive from H3app later on
template <bool SSL>
struct CachingApp : public uWS::TemplatedApp<SSL, CachingApp<SSL>> {
public:
CachingApp(SocketContextOptions options = {}) : uWS::TemplatedApp<SSL, CachingApp<SSL>>(options) {}
using uWS::TemplatedApp<SSL, CachingApp<SSL>>::get;
CachingApp(const CachingApp &other) = delete;
CachingApp(CachingApp<SSL> &&other) : uWS::TemplatedApp<SSL, CachingApp<SSL>>(std::move(other)) {
// also move the cache
}
~CachingApp() {
}
// variant 1: only taking URL into account
CachingApp& get(const std::string& url, std::function<void(CachingHttpResponse*, uWS::HttpRequest*)> handler, unsigned int secondsToExpiry) {
((uWS::TemplatedApp<SSL, CachingApp<SSL>> *)this)->get(url, [this, handler, secondsToExpiry](auto* res, auto* req) {
/* We need to know the cache key and the time of now */
std::string_view cache_key = req->getFullUrl();
time_t now = static_cast<LoopData *>(us_loop_ext((us_loop_t *)uWS::Loop::get()))->cacheTimepoint;
auto it = cache.find(cache_key);
if (it != cache.end()) {
if (it->second->created + secondsToExpiry > now) {
res->end(it->second->buffer); // tryEnd!
return;
}
/* We are no longer valid, delete old cache and fall through to create a new entry */
delete it->second;
// is the cache completed? if not, add yourself to the waiting list of sockets to that cache
// if the cache completed? ok, is it still valid? use it
}
// immediately take the place in the cache
CachingHttpResponse *cachingRes;
cache[cache_key] = (cachingRes = new CachingHttpResponse(res));
handler(cachingRes, req);
});
return *this;
}
// variant 2: taking URL and a list of headers into account
// todo
private:
CacheType cache;
};
}
#endif