-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathrate_limit_key_builder.cpp
More file actions
76 lines (65 loc) · 2.56 KB
/
rate_limit_key_builder.cpp
File metadata and controls
76 lines (65 loc) · 2.56 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
#include "rate_limit_key_builder.hpp"
#include <functional>
#include <sstream>
namespace flapi {
namespace {
constexpr const char* kAnonymousMarker = "anonymous";
std::string hashAuthHeader(const std::string& authorization_header) {
// Stable, non-cryptographic hash of the Authorization header. We do
// not need cryptographic strength — we only need:
// 1) determinism so the same caller hashes to the same bucket
// 2) no plaintext token in the key (it gets logged at DEBUG)
// std::hash satisfies both for our purposes. Operators who want
// stronger guarantees should put a reverse proxy in front and key
// on a header it injects.
const std::size_t h = std::hash<std::string>{}(authorization_header);
std::ostringstream oss;
oss << "u" << std::hex << h;
return oss.str();
}
std::string principalForUserStrategy(const std::string& authorization_header) {
if (authorization_header.empty()) {
return std::string(kAnonymousMarker);
}
return hashAuthHeader(authorization_header);
}
} // namespace
RateLimitKeyStrategy RateLimitKeyStrategyUtils::parse(const std::string& value) {
if (value == "user") {
return RateLimitKeyStrategy::User;
}
if (value == "user-or-ip") {
return RateLimitKeyStrategy::UserOrIp;
}
// `ip`, empty, or unknown — preserve historical behaviour.
return RateLimitKeyStrategy::Ip;
}
std::string RateLimitKeyStrategyUtils::toString(RateLimitKeyStrategy strategy) {
switch (strategy) {
case RateLimitKeyStrategy::Ip: return "ip";
case RateLimitKeyStrategy::User: return "user";
case RateLimitKeyStrategy::UserOrIp: return "user-or-ip";
}
return "ip";
}
std::string RateLimitKeyBuilder::buildKey(RateLimitKeyStrategy strategy,
const std::string& client_ip,
const std::string& authorization_header,
const std::string& path) const {
std::string principal;
switch (strategy) {
case RateLimitKeyStrategy::Ip:
principal = client_ip;
break;
case RateLimitKeyStrategy::User:
principal = principalForUserStrategy(authorization_header);
break;
case RateLimitKeyStrategy::UserOrIp:
principal = authorization_header.empty()
? client_ip
: principalForUserStrategy(authorization_header);
break;
}
return principal + "|" + path;
}
} // namespace flapi